Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

MVC "create view" when there is one to many relationship in model

My model is simple, one client can have many phone numbers :

I have represented this in Entity Framework

Generated client class is as below.

public partial class Client
{
    public Client()
    {
        this.PhoneNumbers = new HashSet<PhoneNumber>();
    }

    public int Id { get; set; }
    public string Name { get; set; }

    public virtual ICollection<PhoneNumber> PhoneNumbers { get; set; }
}

And now I need to create a view page for "create client". This page should have space to enter PhoneNumbers also (ex: By default there should be two text boxes to enter phone numbers)

<fieldset>
    <legend>Client</legend>

    <div class="editor-label">
        @Html.LabelFor(model => model.Name)
    </div>
    <div class="editor-field">
        @Html.EditorFor(model => model.Name)
        @Html.ValidationMessageFor(model => model.Name)
    </div>

    <p>
        <input type="submit" value="Create" />
    </p>
</fieldset>

as the above "create view" we can easily give an space for "model.Name", because it is a simple property. But how can i do something similar for collection of phone numbers..??

I know that we can achieve this with ugly javascript code, but I would like to know the best easy and simple way, that we can use with ASP.NET MVC ... ?

like image 980
Janaka Priyadarshana Avatar asked Feb 15 '23 22:02

Janaka Priyadarshana


1 Answers

You have to do a few things:

First create a ViewModel that has the properties you need:

public class ClientViewModel
{
   public int Id {get;set;}
   public string Name {get;set;}
   public PhoneNumber PhoneNumber1 {get;set;}
   public PhoneNumber PhoneNumber2 {get;set;}
}

Change Create to return the ClientViewModel

[HttpGet]
public ActionResult Create()
{
   return View(new ClientViewModel());
}

Map the HttpPost to use the ClientViewModel and map the values to it:

[HttpPost]
public ActionResult Create(ClientViewModel clientViewModel)
{
   var client = new Client();
   client.Name = clientViewModel.Name;
   client.PhoneNumbers.Add(clientViewModel.PhoneNumber1);
   client.PhoneNumbers.Add(clientViewModel.PhoneNumber2);
   db.Clients.Add(client);
   db.SaveChanges();
   return RedirectToAction("Index", "Client");
}

Then, finally, modify your view:

<fieldset>
   <legend>Client</legend>

   <div class="editor-label">
      @Html.LabelFor(model => model.Name)
   </div>
   <div class="editor-field">
      @Html.EditorFor(model => model.Name)
      @Html.ValidationMessageFor(model => model.Name)
   </div>

   <div class="editor-label">
      @Html.LabelFor(model => model.PhoneNumber1.Number)
   </div>
   <div class="editor-field">
      @Html.EditorFor(model => model.PhoneNumber1.Number)
      @Html.ValidationMessageFor(model => model.PhoneNumber1.Number)
   </div>

   <div class="editor-label">
      @Html.LabelFor(model => model.PhoneNumber2.Number)
   </div>
   <div class="editor-field">
      @Html.EditorFor(model => model.PhoneNumber2.Number)
      @Html.ValidationMessageFor(model => model.PhoneNumber2.Number)
   </div>

   <p>
      <input type="submit" value="Create" />
   </p>
</fieldset>
like image 97
SOfanatic Avatar answered Feb 22 '23 00:02

SOfanatic