Doubt in View and Controller construction with entity dependent on cardinality N

1

I'm on a project that I have a 1: N relationship. Explaining better: Project is for a school where students have their occurrences. So I would be a student for several occurrences:

Models \ Student.cs

public class Aluno
{
    public long Id { get; set; }

    [Required(ErrorMessage = "O nome do aluno é obrigatório")]
    [MinLength(3, ErrorMessage = "O nome deve ter no mínimo 3 caracteres")]
    [Display(Name = "Nome do Aluno")]
    public string Nome { get; set; }

    [MinLength(3, ErrorMessage = "O nome deve ter no mínimo 3 caracteres")]
    [Display(Name = "Nome do Pai")]
    public string NomePai { get; set; }

   // [Required(ErrorMessage = "O nome da mãe é obrigatório")]
    [MinLength(3, ErrorMessage = "O nome deve ter no mínimo 3 caracteres")]
    [Display(Name = "Nome da Mãe")]
    public string NomeMae { get; set; }

    [MinLength(3, ErrorMessage = "O nome deve ter no mínimo 3 caracteres")]
    [Display(Name = "Nome do Responsável")]
    public string NomeResponsavel { get; set; }

   // [Required(ErrorMessage = "O endereço é obrigatório")]
    [MinLength(10, ErrorMessage = "O endereço deve ter no mínimo 10 caracteres")]
    [Display(Name = "Endereço")]
    public string Endereco { get; set; }

   // [Required(ErrorMessage = "A data de nascimento é obrigatória")]
    [DisplayFormat(DataFormatString = "{0:dd/MM/yyyy}", ApplyFormatInEditMode = true)]
    [DataType(DataType.Date)]
    [Display(Name = "Data de Nascimento")]
    public DateTime DataDeNascimento { get; set; }

    [MaxLength(4, ErrorMessage = "O ano letivo deve ter no máximo 4 caracteres: AAAA ")]
    [Display(Name = "Ano Letivo")]
    public string AnoLetivo { get; set; }

    [Required(ErrorMessage = "Informe o ano que o aluno está cursando")]
    public int Ano { get; set; }

    [Required(ErrorMessage = "Informe a turma do aluno")]
    public string Turma { get; set; }

   // [Required(ErrorMessage = "Informe o numero da turma")]
    public int Numero { get; set; }

    [Required(ErrorMessage = "informe o turno")]
    public string Turno { get; set; }

    //[Required(ErrorMessage="O telefone é obrigatório")]
    [Display(Name="Telefone")]
    public string Telefone { get; set; }

    [Display(Name="Telefone Alternativo")]
    public string TelefoneContato { get; set; }

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

    [Display(Name = "Foto")]
    public string Foto { get; set; }
    public ICollection<Ocorrencia> Ocorrencias { get; set; }
    public Aluno()
    {
        this.Ocorrencias = new HashSet<Ocorrencia>();
    }
}

Models / Ocorrencias.cs

public class Ocorrencia
{
    public long Id { get; set; }
    public string Tipo { get; set; }
    public string Causa { get; set; }
    public string Observacao { get; set; }
    public long AlunoId { get; set; }
    public virtual Aluno Aluno { get; set; }

}

I even made the relationship. But when it generated the views of occurrences a dropdownlist with the name of the students was generated so that the occurrence was inserted. But that's not really what I want.

And here is the Controller:

 public ActionResult Index()
{
    var ocorrencias = db.Ocorrencias.Include(o => o.Aluno);
    return View(ocorrencias.ToList());
}

// GET: /Ocorrencias/Detalhes/5
public ActionResult Detalhes(long? id)
{
    if (id == null)
    {
        return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
    }
    Ocorrencia ocorrencia = db.Ocorrencias.Find(id);
    if (ocorrencia == null)
    {
        return HttpNotFound();
    }
    return View(ocorrencia);
}

// GET: /Ocorrencias/Adiciona
public ActionResult Adiciona()
{
    ViewBag.AlunoId = new SelectList(db.Alunos, "Id", "Nome");
    return View();
}

// POST: /Ocorrencias/Adiciona
// To protect from overposting attacks, please enable the specific properties you            want to bind to, for 
// more details see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Adiciona([Bind(Include="Id,Tipo,Causa,Observacao,AlunoId")]    Ocorrencia ocorrencia)
{
    if (ModelState.IsValid)
    {
        db.Ocorrencias.Add(ocorrencia);
        db.SaveChanges();
        return RedirectToAction("Index");
    }

    ViewBag.AlunoId = new SelectList(db.Alunos, "Id", "Nome", ocorrencia.AlunoId);
    return View(ocorrencia);
}

// GET: /Ocorrencias/Edita/5
public ActionResult Edita(long? id)
{
    if (id == null)
    {
        return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
    }
    Ocorrencia ocorrencia = db.Ocorrencias.Find(id);
    if (ocorrencia == null)
    {
        return HttpNotFound();
    }
    ViewBag.AlunoId = new SelectList(db.Alunos, "Id", "Nome", ocorrencia.AlunoId);
    return View(ocorrencia);
}

// POST: /Ocorrencias/Edita/5
// To protect from overposting attacks, please enable the specific properties you want to bind to, for 
// more details see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edita([Bind(Include="Id,Tipo,Causa,Observacao,AlunoId")] Ocorrencia ocorrencia)
{
    if (ModelState.IsValid)
    {
        db.Entry(ocorrencia).State = EntityState.Modified;
        db.SaveChanges();
        return RedirectToAction("Index");
    }
    ViewBag.AlunoId = new SelectList(db.Alunos, "Id", "Nome", ocorrencia.AlunoId);
    return View(ocorrencia);
}

// GET: /Ocorrencias/Remove/5
public ActionResult Remove(long? id)
{
    if (id == null)
    {
        return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
    }
    Ocorrencia ocorrencia = db.Ocorrencias.Find(id);
    if (ocorrencia == null)
    {
        return HttpNotFound();
    }
    return View(ocorrencia);
}

// POST: /Ocorrencias/Remove/5
[HttpPost, ActionName("Remove")]
[ValidateAntiForgeryToken]
public ActionResult DeleteConfirmed(long id)
{
    Ocorrencia ocorrencia = db.Ocorrencias.Find(id);
    db.Ocorrencias.Remove(ocorrencia);
    db.SaveChanges();
    return RedirectToAction("Index");
}

What I want is that the event was tied to the student, I say Id, not a dropdownlist to choose the student. I want everything to be in the same place. Does anyone have a tip?

    
asked by anonymous 14.05.2014 / 19:17

1 answer

3

In entities with cardinality N, the correct one is to use a NuGet package called BeginCollectionItem :

  

link

The original question started here: Map one model's Id to another without a DropDownList appearing , so I copied the code to respond.

Views \ Aluno.cshtml

@model Aluno

@using (Html.BeginForm()) {
...
    @foreach (var ocorrencia in Model.Ocorrencias) {
        @Html.Partial("_LinhaOcorrencia", ocorrencia)
    }
...
}

Views \ _LineLocation.cshtml

@model Ocorrencia

@using (Html.BeginCollectionItem("Ocorrencias")) {
    @Html.HiddenFor(model => model.AlunoId)

    <div class="form-horizontal">
        <h4>Ocorrencia</h4>
        <hr />
        @Html.ValidationSummary(true)

        <div class="form-group">
            @Html.LabelFor(model => model.Tipo, new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.Tipo)
                @Html.ValidationMessageFor(model => model.Tipo)
            </div>
        </div>

        <div class="form-group">
            @Html.LabelFor(model => model.Causa, new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.Causa)
                @Html.ValidationMessageFor(model => model.Causa)
            </div>
        </div>

        <div class="form-group">
            @Html.LabelFor(model => model.Observacao, new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.Observacao)
                @Html.ValidationMessageFor(model => model.Observacao)
            </div>
        </div>

        <div class="form-group">
            <div class="col-md-offset-2 col-md-10">
                <input type="submit" value="Salvar" class="btn btn-default" />
            </div>
        </div>
    </div>
}

The example only makes sense in Controller of Aluno , and not in Controller of Ocorrencia , which you are using originally.

Controllers \ AlunosController.cs

public ActionResult Index()
{
    var alunos = db.Alunos.Include(a => a.Ocorrencias);
    return View(alunos.ToList());
}

// GET: /Alunos/Detalhes/5
public ActionResult Detalhes(long? id)
{
    if (id == null)
    {
        return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
    }

    var aluno = db.Alunos.Find(id);
    if (aluno == null)
    {
        return HttpNotFound();
    }
    return View(aluno);
}

// GET: /Alunos/Adiciona
public ActionResult Adiciona()
{
    return View();
}

// POST: /Alunos/Adiciona
// To protect from overposting attacks, please enable the specific properties you            want to bind to, for 
// more details see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Adiciona([Bind(Include="/*Campos do Aluno*/")] Aluno aluno)
{
    if (ModelState.IsValid)
    {
        db.Alunos.Add(aluno);
        db.SaveChanges();

        // Salvar ocorrências
        foreach (var ocorrencia in aluno.Ocorrencias) {
            ocorrencia.AlunoId = aluno.Id;
            db.Ocorrencias.Add(ocorrencia);
        }

        db.SaveChanges();
        return RedirectToAction("Index");
    }

    return View(aluno);
}

// GET: /Alunos/Edita/5
public ActionResult Edita(long? id)
{
    if (id == null)
    {
        return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
    }

    var aluno = db.Alunos.Find(id);
    if (aluno == null)
    {
        return HttpNotFound();
    }

    return View(aluno);
}

// POST: /Alunos/Edita/5
// To protect from overposting attacks, please enable the specific properties you want to bind to, for 
// more details see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edita([Bind(Include="Id,Tipo,Causa,Observacao,AlunoId")] Aluno aluno)
{
    if (ModelState.IsValid)
    {
        // Ocorrências

        foreach (var ocorrencia in aluno.Ocorrencias)
        {
            if (ocorrencia.Id == 0)
            {
                ocorrencia.AlunoId = aluno.Id;
                db.Ocorrencias.Add(ocorrencia);
            }
        }

        db.SaveChanges();

        db.Entry(ocorrencia).State = EntityState.Modified;
        db.SaveChanges();
        return RedirectToAction("Index");
    }

    return View(aluno);
}

// GET: /Alunos/Remove/5
public ActionResult Remove(long? id)
{
    if (id == null)
    {
        return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
    }

    var aluno = db.Alunos.Find(id);
    if (aluno == null)
    {
        return HttpNotFound();
    }

    return View(aluno);
}

// POST: /Alunos/Remove/5
[HttpPost, ActionName("Remove")]
[ValidateAntiForgeryToken]
public ActionResult DeleteConfirmed(long id)
{
    var aluno = db.Alunos.Find(id);

    // Ocorrências
    foreach (ocorrencia in aluno.Ocorrencias) {
        db.Ocorrencias.Remove(ocorrencia);
        db.SaveChanges();
    }

    db.Alunos.Remove(aluno);
    db.SaveChanges();
    return RedirectToAction("Index");
}

Pro Controller of Ocorrencias looks like this:

Controllers \ OccurrencesController.cs

// GET: /Ocorrencias/Adiciona
public ActionResult Adiciona(int id) /* Esse Id é de Aluno, não de Ocorrencia */
{
    var aluno = db.Alunos.SingleOrDefault(a => a.Id == id);
    var ocorrencia = new Ocorrencia {
        Aluno = aluno
    };

    return View(ocorrencia);
}
    
14.05.2014 / 19:32