Killnine
Killnine

Reputation: 5900

Set List property in View using MVC3

Pretty new to MVC and the like. I have a class the looks like this:

public class SomeExampleModel
{
    public int Id { get; private set; }
    public string Name { get; private set;}
    public string Street { get; private set; }
    public IList<Contact> Contacts { get; private set; }
    ...
}

Where Contact looks like:

public class Contact
{
    public int Id { get; private set; }
    public int SomeExampleModelId { get; private set; }
    public ContactType Type { get; private set; }
    public string ContactValue { get; private set; }
...
}

Now the problem is, I have a Post Create action and Create.cshtml view to add new SomeExampleModel to my database. It works great for all the basic properties, but there isn't anything for the Contacts property (which is a separate table in the database).

How would I be able to add contacts (single for now, plural in the future) using forms on my view?

EDIT: I am sorry if I was not clear. The problem is not getting data to save in the database correctly. I have tested that already and it works fine if I just manually insert a SomeExampleModel record into the database with the SomeExampleContext. What I dont know is how to draft my View so that it allows users to add Contacts to the record

Upvotes: 0

Views: 223

Answers (2)

Prashanth Thurairatnam
Prashanth Thurairatnam

Reputation: 4361

Here is one approach using an EditorTemplate. I have made minor changes to your model classes (this works; however, note that this is only for you to understand the concept. You can extend upon this)

Models

public class SomeExampleModel
{
    public int Id { get; set; }
    public string Name { get; set;}
    public string Street { get; set; }
    public IList<Contact> Contacts { get; set; }    
}

public class Contact
{
    public int Id { get; set; }
    public int SomeExampleModelId { get; set; }
    public ContactType Type { get; set; }
    public string ContactText { get { return Type.ToString(); } }
    public string ContactValue { get; set; }
}

public enum ContactType
{
    email,
    Phone,
    mobile,
    fax
}

Make a note that I've created a property ContactText that returns the enum text (for display purposes)

Create a editor template for Contact (named Contact.cshtml; Template name must match the class name). Find below the screen shot on where to place your editor template.

enter image description here

Here is the code for Contact.cshtml

@model Test1.Models.Contact
<table>
@Html.HiddenFor(a=>a.Type)
<tr>
 <td>@Html.Label(Model.ContactText)</td>
 <td>@Html.TextBoxFor(a => a.ContactValue)</td>
</tr>
</table>

Here is the code for the 'Create' view (ExampleCreateView.cshtml in my case)

@model Test1.Models.SomeExampleModel

@{
    ViewBag.Title = "ExampleCreateView";
}

<h2>ExampleCreateView</h2>

<script src="@Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script>

@using (Html.BeginForm()) {
    @Html.ValidationSummary(true)
    <fieldset>
        <legend>SomeExampleModel</legend>
        @Html.HiddenFor(model=>model.Id)
        <table>
            <tr>
                <td>@Html.LabelFor(model=>model.Name)</td>
                <td>@Html.EditorFor(model=>model.Name)</td>
            </tr>
            <tr>
                <td>@Html.LabelFor(model=>model.Street)</td>
                <td>@Html.EditorFor(model=>model.Street)</td>
            </tr>
            <tr>
                <td>@Html.LabelFor(model=>model.Contacts)</td>
                <td>@Html.EditorFor(model=>model.Contacts)</td>
            </tr>
        </table>
        <p>
            <input type="submit" value="Create" />
        </p>
    </fieldset>
}

<div>
    @Html.ActionLink("Back to List", "Index")
</div>

Make a note on how I've used @Html.EditorFor for the Contacts property.

Here is how the Get, Post actions will look like

    public ActionResult ExampleCreateView()
    {
        SomeExampleModel model = new SomeExampleModel();
        Contact contactEmail = new Contact();
        contactEmail.Type = ContactType.email;

        Contact contactFax = new Contact();
        contactFax.Type = ContactType.fax;

        Contact contactPhone = new Contact();
        contactPhone.Type = ContactType.Phone;

        Contact contactMobile = new Contact();
        contactMobile.Type = ContactType.mobile;

        List<Contact> contacts = new List<Contact>();

        contacts.Add(contactEmail);
        contacts.Add(contactFax);
        contacts.Add(contactPhone);
        contacts.Add(contactMobile);

        model.Contacts = contacts;

        return View(model);
    }

    [HttpPost]
    public ActionResult ExampleCreateView(SomeExampleModel model)
    {
        //Your operations
        return View(model);
    }

Run the application. This is how the view looks like

enter image description here

Screen shot of what you will get in the POST action

enter image description here

Upvotes: 1

StanK
StanK

Reputation: 4770

The way I would do it is to have two separate actions - one that does the initial create of SomeExampleModel, and a separate action for adding a Contact to that model.

That way your create SomeExampleModel view would just have Name and street, and when it saved you would show a readonly version of the SomeExampleModel . The readonly version of SomeExampleModel would list all related contacts in a table below the Name and Street, with an edit and delete link, and an 'add new' contact link under the table

e.g.

<table>
@foreach (var contact in Model.Contacts)
{
    <tr>
        <td>@contact.ContactType</td>
        <td>@contact.ContactValue</td>
        <td>@Html.Action("Edit", "Edit", "Contact",  new { id = contact.Id }</td>
        <td>@Html.Action("Delete", "Delete", "Contact", { id = contact.Id }</td>
    </tr>
}
</table>
@Html.Action("Add new contact", "Add", "Contact" new { id = Model.Id }

Initially, there would be no contacts listed, then later you would have multiple contacts.

Upvotes: 0

Related Questions