Problems generating a PartialView with BeginCollectionItem

2

With the intention of creating an action for Adc / Deleting data dynamically to a table with a relation of 1 to Many, .NET returns the exception " Object reference not set to an instance of an object. When I call PartialView, I try to view the view, following the Models , viewModels , Controller / em>, View and PartialView ...

Models

public class Candidato
{
    [Key]
    public int id { get; set; }
    public string nome { get; set; }
    public string cpf { get; set; }
    public string sexo { get; set; }
}

public class CandidatoEP
{
    [Key]
    public int id { get; set; }
    public int id_candidato { get; set; }
    public string empresa { get; set; }
    public string cargo { get; set; }
    public DateTime inicio { get; set; }
    public DateTime fim { get; set; }
    public string obsEp { get; set; }

    [ForeignKey("id_candidato")]
    public virtual Candidato candidato { get; set; }
}

ViewModel

public class NovoCandidato
{
    [Required(ErrorMessage = "Obrigatório informar o Nome")]
    [Display(Name = "Nome")]
    public string nome { get; set; }

    [Required(ErrorMessage = "Obrigatório informar o CPF")]
    [Display(Name = "CPF")]
    public string cpf { get; set; }

    [Required(ErrorMessage = "Obrigatório informar o Sexo")]
    [Display(Name = "Sexo")]
    public string sexo { get; set; }

    public virtual ICollection<CandidatoEP> CandidatoEPs { get; set; }
}

Controller

public ActionResult Novo()
{
    var novoCandidato = new CandidatoNovo();
    return View(novoCandidato);
}

View part where I insert PartialView )

<div class="form-group col-lg-12" style="margin-bottom:30px;">
    <label>Experiência <small>(opcional)</small></label>
    <div class="dc-form-inside">

        @foreach (var Experiencia in Model.CandidatoEPs)
        {
            Html.RenderPartial("_AddCandidatoExp", Experiencia);
        }

        <a href="#" class="control-add-box">+ Adicionar Experiência</a>

    </div>
</div>

PartialView

@model Site.ViewModels.CandidatoNovo

@using (Html.BeginCollectionItem("CandidatoEPs"))
{
    <div class="dc-box-clonar form experiencia">
        <a href="#" class="fechar-form botao"><i class="glyphicon glyphicon-remove"></i></a>
        <div class="form-group col-lg-12">

            @Html.EditorFor(m => m.empresa, new { htmlAttributes = new { @class = "form-control", @placeholder = "Empresa onde trabalhou" } })
        </div>
        <div class="form-group col-lg-12">

            @Html.EditorFor(m => m.id_departamento, new { htmlAttributes = new { @class = "form-control", @placeholder = "Departamento" } })
        </div>
        <div class="form-group col-lg-12">

            @Html.EditorFor(m => m.cargo, new { htmlAttributes = new { @class = "form-control", @placeholder = "Função exercida" } })
        </div>
        <div class="form-group col-lg-6">

            @Html.EditorFor(m => m.inicio, new { htmlAttributes = new { @class = "form-control", @placeholder = "Início (MM/AAAA)" } })
        </div>
        <div class="form-group col-lg-6">

            @Html.EditorFor(m => m.fim, new { htmlAttributes = new { @class = "form-control", @placeholder = "Fim (MM/AAAA)" } })
        </div>
        <div class="form-group col-lg-12" style="margin-bottom:30px;">

            @Html.TextAreaFor(m => m.obsEp, new { @class = "dc-textarea form-control", @placeholder = "Descreva as atividades exercidas na função...", @rows = "3" })
            @Html.ValidationMessageFor(model => model.obsEp, "", new { @class = "text-danger" })
        </div>
    </div>
}

Already, I use a function in js to add multiple experience boxes.

Javascript

$('.dc-box-clonar').hide();
$('.control-add-box').on('click', function (e) {
    e.preventDefault();
    var newElem = $(this).parent().find('.dc-box-clonar:first').clone();
    newElem.find('input').val('');
    newElem.prependTo($(this).parent()).show();
    var height = $(this).prev('.dc-box-clonar').outerHeight(true);

    $("html, body").stop().animate({ scrollTop: $(this).offset().top - 520 }, 600);
});
    
asked by anonymous 10.11.2015 / 20:01

1 answer

5

Quickly solving the problem, it would look something like this:

<div class="form-group col-lg-12" style="margin-bottom:30px;">
    <label>Experiência <small>(opcional)</small></label>
    <div class="dc-form-inside">

        @if (Model != null && Model.CandidatoEPs != null) 
        {
            foreach (var Experiencia in Model.CandidatoEPs)
            {
                Html.RenderPartial("_AddCandidatoExp", Experiencia);
            }
        }

        <a href="#" class="control-add-box">+ Adicionar Experiência</a>
    </div>
</div>

To add experience, use something like this:

        <script type="text/javascript">
            $("#adicionar-nova-experiencia").click(function () {
                $.get('/Experiencia/NovaLinha', function (template) {
                    $("#area-experiencias").append(template); /* Você pode ainda colocar .then($(...)); */
                });
            });
        </script>

And Controller (using Guid ):

    public ActionResult NovaLinha()
    {
        return PartialView("_LinhaExperiencia", new Experiencia { ExperienciaId = Guid.NewGuid() });
    }

Using int :

    public ActionResult NovaLinha()
    {
        return PartialView("_LinhaExperiencia", new Experiencia());
    }

With int the key is not set in Controller because the key setting is left to the database, at the time you save the record.

Controller receives the following:

[HttpPost]
public ActionResult Novo(CandidatoNovo candidatoNovo)
{
    if (ModelState.IsValid) 
    { 
        /* Aqui candidatoNovo.CandidatoEPs está preenchido */ 
    }
}
    
10.11.2015 / 20:49