Save data group in Post method

Asked

Viewed 494 times

0

I’m using the Begincollectionitem to save a list of data in my add method.

For that, I created a ViewModel with the main data to the list I want to save, in the method POST.

I own the ViewModel TipoPrestacaoVencimentoViewModel which has the following attributes:

public class TipoPrestacaoVencimentoViewModel
{
[Key]
public int TipoPrestacaoId { get; set; }

[Required(ErrorMessage = "Digite o nome da Prestação.")]
public string Descricao { get; set; }

[Display(Name = "Tipo de vencimento")]
[Required(ErrorMessage = "Escolha o tipo de Prestação.")]
public string TipoVencimento { get; set; }

[Display(Name = "Responsável TCE")]
public string Responsave { get; set; }

[Display(Name = "Quantidade de Arquivos")]
public int? QuantidadeArquivos { get; set; }

[Required(ErrorMessage = "Digite o ano da prestação!")]
[Display(Name = "Ano Vigência")]
public string AnoVigencia { get; set; }

public virtual ICollection<AnexoPrestacaoViewModel> Anexos { get; set; }
}

And I pass with it, a collection of Attachments:

 public class AnexoPrestacaoViewModel
    {
        public int AnexoPrestacaoId { get; set; }
        public string Titulo { get; set; }
        public string Sequencia { get; set; }
        public byte[] Arquivo { get; set; }
        public DateTime DataArquivo { get; set; }
    }

In my Add method, I send a new product to View, thus:

public ActionResult Adicionar()
{
    var recipePrestacao = new TipoPrestacaoVencimentoViewModel();

    return View(recipePrestacao);
}

And saved with the POST thus:

[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Adicionar(TipoPrestacaoVencimentoViewModel tipoPrestacao)
{
    if (ModelState.IsValid)
    {
        _prestacaoDB.Adicionar(tipoPrestacao);
        TempData["MensagemSuccess"] = "Prestação adicionada com sucesso!";

        return RedirectToAction("Index");
    }

    return View(tipoPrestacao);
}

And I have a method to add new item to View:

public ActionResult GetNewPrestacao()
{
    return PartialView("_Anexo", new AnexoPrestacaoViewModel());
}

My View is as follows:

@model PrestacaoWeb.Application.ViewModels.TipoPrestacaoVencimentoViewModel

@{
    ViewBag.Title = "Adicionar Tipos de Prestações de Conta";
}

<style>
    body .modal-admin {
        width: 900px;
        margin-left: 120px;
    }
</style>
@using (Html.BeginForm("Adicionar", "Prestacao", FormMethod.Post, new { enctype = "multipart/form-data" }))
{ 
    @Html.AntiForgeryToken()
    <div class="form-horizontal">
        <div class="modal-dialog modal-admin">
            <div class="modal-content">
                <div class="modal-header">
                    <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
                    <h4 class="modal-title" id="myModalLabel">@ViewBag.Title</h4>
                </div>
                <br/>
                <div class="col-md-offset-1">
                    <div class="bs-example">
                        <ul class="nav nav-tabs">
                            <li class="active"><a data-toggle="tab" href="#dadosPrestacao">Prestação</a></li>
                            <li><a data-toggle="tab" href="#Anexo">Anexos</a></li>
                        </ul>
                        <div class="tab-content">
                            <div id="dadosPrestacao" class="tab-pane fade in active">
                                @Html.Partial("_DadosPrestacao")
                            </div>
                            <div id="Anexo" class="tab-pane fade">
                                <fieldset>
                                    <legend>Anexos</legend>
                                    <div class="new-anexo">
                                        @Html.EditorFor(model => model.Anexos)
                                    </div>
                                    <div style="padding: 10px 0px 10px 0px">
                                        <a id="add-anexo" href="javascript:void(0);">Add Anexo</a>
                                    </div>
                                </fieldset>
                            </div>
                        </div>
                    </div>
                    <hr />
                    <div class="form-group">
                        <div class="col-md-offset-2 col-md-10">
                            <div class="col-md-6">
                                <input type="submit" value="Salvar" class="btn btn-primary" id="submitbtn" />
                            </div>
                            @Html.ActionLink("Cancelar", "Index", "Prestacao", null, new
                                {
                                    @id = "btnAddPrestacao",
                                    @class = "btn btn-danger"
                                })
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>
}

@section Scripts
{
<script type="text/javascript">
    $(function () {
        $('#add-anexo').click(function () {
            $.ajax({
                url: '@Url.Action("GetNewPrestacao")',
                type: 'POST',
                success: function (data) {
                    $('.new-anexo').append(data);
                }
            });
            return false;
        });
    });
</script>
}

And the PartialView using the Begincollectionitem thus:

@model PrestacaoWeb.Application.ViewModels.AnexoPrestacaoViewModel

@using (Html.BeginCollectionItem("Anexos"))
{
    <div>
        <div class="form-group">
            @Html.LabelFor(model => model.Titulo, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-7">
                @Html.EditorFor(model => model.Titulo, new { htmlAttributes = new { @class = "form-control" } })
                @Html.ValidationMessageFor(model => model.Titulo, "", new { @class = "text-danger" })
            </div>
        </div>
        <div class="form-group">
            @Html.LabelFor(model => model.Sequencia, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-7">
                @Html.EditorFor(model => model.Sequencia, new { htmlAttributes = new { @class = "form-control" } })
                @Html.ValidationMessageFor(model => model.Sequencia, "", new { @class = "text-danger" })
            </div>
        </div>
        <div class="form-group">
            @Html.LabelFor(model => model.DataArquivo, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-7">
                @Html.EditorFor(model => model.DataArquivo, new { htmlAttributes = new { @class = "form-control" } })
                @Html.ValidationMessageFor(model => model.DataArquivo, "", new { @class = "text-danger" })
            </div>
        </div>
        <div class="form-group">
            @Html.LabelFor(model => model.Arquivo, new { @class = "col-sm-2 control-label", @align = "right" })
            <div class="col-md-10">
                @Html.TextBoxFor(x => x.Arquivo, new { type = "file" })
                @Html.ValidationMessageFor(model => model.Arquivo, String.Empty, new { @class = "help-block" })
            </div>
        </div>
    </div>
}

The problem is that when running my application, I get a System.NullReferenceException from Collection.cshtml. Follow the complete error:

Referência de objeto não definida para uma instância de um objeto.
Descrição: Ocorreu uma exceção sem tratamento durante a execução da atual solicitação da Web. Examine o rastreamento de pilha para obter mais informações sobre o erro e onde foi originado no código. 
Detalhes da Exceção: System.NullReferenceException: Referência de objeto não definida para uma instância de um objeto.
Erro de Origem: 
Linha 2:  
Linha 3:  <ul>                                 
Linha 4:      @foreach (object item in Model)
Linha 5:      {
Linha 6:          <li>
Arquivo de Origem: c:\Users\renilson.meneguci\Documents\Visual Studio 2013\Projects\UEM_ES\Fontes\PrestacaoWeb\src\PrestacaoWeb.UI\Views\Shared\EditorTemplates\Collection.cshtml    Linha: 4 
Rastreamento de Pilha:[NullReferenceException: Referência de objeto não definida para uma instância de um objeto.]
   ASP._Page_Views_Shared_EditorTemplates_Collection_cshtml.Execute() in c:\Users\ti\Documents\Visual Studio 2013\Projects\UEM_ES\Fontes\PrestacaoWeb\src\PrestacaoWeb.UI\Views\Shared\EditorTemplates\Collection.cshtml:4
   System.Web.WebPages.WebPageBase.ExecutePageHierarchy() +279
   System.Web.Mvc.WebViewPage.ExecutePageHierarchy() +125
   System.Web.WebPages.WebPageBase.ExecutePageHierarchy(WebPageContext pageContext, TextWriter writer, WebPageRenderingBase startPage) +124
   System.Web.Mvc.Html.TemplateHelpers.ExecuteTemplate(HtmlHelper html, ViewDataDictionary viewData, String templateName, DataBoundControlMode mode, GetViewNamesDelegate getViewNames, GetDefaultActionsDelegate getDefaultActions) +727
   System.Web.Mvc.Html.TemplateHelpers.TemplateHelper(HtmlHelper html, ModelMetadata metadata, String htmlFieldName, String templateName, DataBoundControlMode mode, Object additionalViewData, ExecuteTemplateDelegate executeTemplate) +1332
   System.Web.Mvc.Html.TemplateHelpers.TemplateHelper(HtmlHelper html, ModelMetadata metadata, String htmlFieldName, String templateName, DataBoundControlMode mode, Object additionalViewData) +109
   System.Web.Mvc.Html.TemplateHelpers.TemplateFor(HtmlHelper1 html, Expression1 expression, String templateName, String htmlFieldName, DataBoundControlMode mode, Object additionalViewData) +157
   System.Web.Mvc.Html.EditorExtensions.EditorFor(HtmlHelper1 html, Expression1 expression) +94
   ASP._Page_Views_Prestacao_Adicionar_cshtml.Execute() in c:\Users\ti\Documents\Visual Studio 2013\Projects\UEM_ES\Fontes\PrestacaoWeb\src\PrestacaoWeb.UI\Views\Prestacao\Adicionar.cshtml:67
   System.Web.WebPages.WebPageBase.ExecutePageHierarchy() +279
   System.Web.Mvc.WebViewPage.ExecutePageHierarchy() +125
   System.Web.WebPages.StartPage.ExecutePageHierarchy() +142
   System.Web.WebPages.WebPageBase.ExecutePageHierarchy(WebPageContext pageContext, TextWriter writer, WebPageRenderingBase startPage) +109
   System.Web.Mvc.ViewResultBase.ExecuteResult(ControllerContext context) +379
   System.Web.Mvc.ControllerActionInvoker.InvokeActionResultFilterRecursive(IList1 filters, Int32 filterIndex, ResultExecutingContext preContext, ControllerContext controllerContext, ActionResult actionResult) +108
   System.Web.Mvc.ControllerActionInvoker.InvokeActionResultFilterRecursive(IList1 filters, Int32 filterIndex, ResultExecutingContext preContext, ControllerContext controllerContext, ActionResult actionResult) +890
   System.Web.Mvc.ControllerActionInvoker.InvokeActionResultWithFilters(ControllerContext controllerContext, IList1 filters, ActionResult actionResult) +97
   System.Web.Mvc.Async.<>c__DisplayClass21.<BeginInvokeAction>b__1e(IAsyncResult asyncResult) +241
   System.Web.Mvc.Controller.<BeginExecuteCore>b__1d(IAsyncResult asyncResult, ExecuteCoreState innerState) +29
   System.Web.Mvc.Async.WrappedAsyncVoid1.CallEndDelegate(IAsyncResult asyncResult) +111
   System.Web.Mvc.Controller.EndExecuteCore(IAsyncResult asyncResult) +53
   System.Web.Mvc.Async.WrappedAsyncVoid1.CallEndDelegate(IAsyncResult asyncResult) +19
   System.Web.Mvc.MvcHandler.<BeginProcessRequest>b__5(IAsyncResult asyncResult, ProcessRequestState innerState) +51
   System.Web.Mvc.Async.WrappedAsyncVoid`1.CallEndDelegate(IAsyncResult asyncResult) +111
   System.Web.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +606
   System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +288

Note: I’m following the model of this answer

  • Which of these sources is the Collection.cshtml?

  • Sorry for the delay @Ciganomorrisonmendez. I was having problems with my internet. Collection.cshtml, it is the same when it was installed by Nuget. I created a partialView I’m calling her in the method.

  • EditorTemplates is not standard of the project. Which Nuget package you used to get it?

  • @Ciganomorrisonmendez I used the Install-Package BeginCollectionItem. With that he has already created this View automatically.

2 answers

2

The mistake starts here:

<div class="new-anexo">
    @Html.EditorFor(model => model.Anexos)
</div>

From what the message says, Anexos is void. Hence the error.

Change:

<div id="Anexo" class="tab-pane fade">
    <fieldset>
        <legend>Anexos</legend>
        <div class="new-anexo">
            @Html.EditorFor(model => model.Anexos)
        </div>
        <div style="padding: 10px 0px 10px 0px">
            <a id="add-anexo" href="javascript:void(0);">Add Anexo</a>
        </div>
    </fieldset>
</div>

For:

<div id="Anexo" class="tab-pane fade">
    <fieldset>
        <legend>Anexos</legend>
        <div class="new-anexo">
            @foreach (var anexo in Model.Anexos) {                    
                Html.RenderPartial("_Anexo", anexo); 
            }
        </div>
        <div style="padding: 10px 0px 10px 0px">
            <a id="add-anexo" href="javascript:void(0);">Adicionar Anexo</a>
        </div>
    </fieldset>
</div>

0

I did not analyze your code much, I did not understand what would be this object "Model" used in foreach. It would not be:

Model.Anexos

But anyway, you are sure that the Model object used in the command below is not NULL?

@foreach (object item in Model)

You cannot iterate as foreach over a NULL element.

  • I’m following the model I posted at the end of the question, and there it is that way. null at the initialization of View. If I exclude the @Html.EditorFor(model => model.Anexos), but I would like you to present an option right after starting View

  • @Wise if he is null you cannot iterate on it. Either set a default value for it (an empty list) or add a if before executing this foreach

  • I’ll check the now.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.