Insert view with collection property

129 views Asked by At

I have a Person class and a Contact class. A person can have many contacts.

public class Person
{
    [Required]
    public string FirstName { get; set; }

    public string LastName { get; set; }

    public string Notes { get; set; }

    [Required]
    public List<Contact> Contacts { get; set; }


    public Person()
    {
        Contacts = new List<Contact>();
    }
}


public class Contact
{
    [Required]
    public string Title { get; set; }

    [Required]
    public string Value { get; set; }

    public Contact() { Title = ""; Value = ""; }

    public Contact(string title, string value)
    {
        Title = title;
        Value = value;
    }
}

Controller:

public class PersonController : Controller
{

    public ActionResult Create()
    {
        return View(new PersonCreateModel());
    }


    // POST: /Person/Create
    [HttpPost]
    public ActionResult Create(string btnSubmit, PersonCreateModel personModel)
    {
        try
        {
            switch (btnSubmit)
            {
                case "AddContact":
                    personModel.Person.Contacts.Add(new Contact(personModel.NewContact_Title, personModel.NewContact_Value));
                    personModel.NewContact_Title = personModel.NewContact_Value = "";
                    return View(personModel);

                case "CreatePerson"://Add To Database
                    //blabla
                    break;
            }

            return RedirectToAction("Index");
        }
        catch
        {
            return View(personModel);
        }
    }
}

PersonCreateModel:

public class PersonCreateModel
{

    public Person Person { get; set; }

    public string NewContact_Title { get; set; }
    public string NewContact_Value { get; set; }

    public PersonCreateModel()
    {
        Person = new Person();
    }
}

View:

@model MvcApplication1.Models.PersonCreateModel

@{
    ViewBag.Title = "Create";

    var contactsGrid = new WebGrid(Model.Person.Contacts); 
}

<h2>Create</h2>

@using (Html.BeginForm())
{
    @Html.ValidationSummary(true)

    <fieldset>
        <legend>Person</legend>

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

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

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

        <br />
        <div>
            <h4>Contacts:</h4>

            <table>
                <tr>
                    <td>Title: @Html.EditorFor(model => model.NewContact_Title)</td>
                    <td>Value: @Html.EditorFor(model => model.NewContact_Value)</td>
                    <td>
                        <input type="submit" name="btnSubmit" value="AddContact" /></td>
                </tr>
            </table>

            <div>
                @contactsGrid.GetHtml()
            </div>
        </div>

        <p>
            <input type="submit" name="btnSubmit" value="CreatePerson" />
        </p>
    </fieldset>
}

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

@section Scripts {
    @Scripts.Render("~/bundles/jqueryval")
}

What I'm trying to accomplish is that the user can add multiple contacts to the Person before finally clicking Create.

I have two questions:

1- Is this the best approach?, isn't there an easier/shorter way of doing this like using javascript or jquery?

2- when I click AddContact the first time it works great, second time the Person.Contacts is Empty, and also I can't clear the AddContact Textboxes.

I've searched all over the web and here on Stackoverflow but I didn't find any answers, there is an unanswered question here

PS: I'm new to MVC, coming from ASP.NET Webforms.

1

There are 1 answers

4
marcos.borunda On

In my personal point of view, I think a better approach would be to handle the contacts "adding" in the client side, if you aren't doing anything "useful" in the server side with the contact's data (like saving to database or something else).

With little lines of JavaScript using jQuery, you could dynamically add new text inputs for every new contact, and when the user is done, he could just hit submit and send all the information in just one call to the server.

This approach would be better for two reasons, first there would be no page refreshing to distract the user, and second you'll avoid multiple server calls by user, that could mean 100s or 1000s calls saved depending on your traffic.

EDIT:

This is a very simplified example of what could it be, of course you should add more functionality, and styling.

Your view model should look something like this in order to this to work:

public class PersonCreateModel
{
    public Person Person { get; set; }
    public List<Contact> Contacts { get; set; }
}

This is a common problem, so there must be a lot of other solutions, take a look at this approach too it's kind of "old" but the concepts still apply.