Doubt in View and Controller construction with cardinality dependent entity N

Asked

Viewed 436 times

1

I am on a project that I have a relationship of 1:N. Explaining better: Project is for a school where there are students and their occurrences. Then you 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/Occurrences.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. Only that when generated the views of occurrences was generated a dropdownlist with the name of the students to be inserted the occurrence. But actually that’s not what I want.

And here 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 incident was tied to the student, I say his ID, and not a dropdownlist to choose the student. I want everything to stay in the same place. Someone has a tip?

  • It would be nice if you paste that Model, Controller and View scheme here, to make more sense.

  • What do I have in the other question ? Or all their code ?

  • Let me do it. Better.

  • Quiet then !

1 answer

3


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

http://www.nuget.org/packages/BeginCollectionItem/

The original doubt began here: Map Id of one model to another without a Dropdownlist, so I copied the code to answer.

Views Student.cshtml

@model Aluno

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

Views _Lineoccurrence.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 the Controller of Ocorrencia, that you’re using originally.

Alunoscontroller.Cs Controllers

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 gets 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);
}
  • Agooora Siim ! So in the occurrences controller you only need Add ? And in it I will be able to edit, delete and the rest ?

  • That’s it. In other actions, as the object already has the Student ID, nothing else needs to be done.

  • Then when I excluded the student would delete everything right? Noooosssa, great, great ! Dude, it helped me a lot. I’m only 1 month away from that and I didn’t know how to do it. It was really worth it ! And by the way I can do the edit action below that ?

  • You can. It’s the same scheme.

  • The list also right ? Same scheme of normal, just put the Tolist() ? And nor need the post method also right ?

  • Also. Anything is just asking more questions ;)

  • Beauty ! I have a question on how to use ajax, I had how to help me use ajax, not need to leave the current page to register,change and list occurrences ?

  • This section here 'var alunos = db.Alunos.Include(a => a.Occurrences);', how can I put it in the detail action and not in the Index ? Because I want to list the occurrences in this view/action.

  • var alunos = db.Alunos.Include(a => a.Ocorrencias).SingleOrDefault(a => a.Id == id);

  • Thank you so much !

Show 5 more comments

Browser other questions tagged

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