Multiple ViewModels in a single MVC View

This post shows how to use multiple models in a single view. The models can be used in separated forms or together in one form. You could use each child model with a separate ajax post if required. Only properties in the parent class affect the child models, but a property in a child model does not effect the Model State of the other child models. In this way multiple models can be used and also validation for each model.

Code https://github.com/damienbod/MultipleModelsDemo

How the ViewModels are implemented:

The parent model class contains all child classes. Each class is another reusable model. In this way, the validation and ModelState can be used.

namespace MultipleModelsDemo.ViewModels
{
    public class IndexViewModel
    {
        public string HeaderText { get; set; }

        public TestOneModel TestOne { get; set; }

        public TestTwoModel TestTwo { get; set; }
    }
}

A child model used for the first form.

using System.ComponentModel.DataAnnotations;

namespace MultipleModelsDemo.ViewModels
{
    public class TestOneModel
    {
        [Required]
        public string PropertyOne { get; set; }

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

A second child model used for the second form.

using System.ComponentModel.DataAnnotations;

namespace MultipleModelsDemo.ViewModels
{
    public class TestTwoModel
    {
        [Required]
        public string PropertyThree { get; set; }

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

In the controller a single action method is used to recieve the form posts. The action method MyEditActionOne uses the Index model. In this action method, the ModelState.IsValid property can be checked. Due to the model structure, separate forms can be sent for each child model, or the whole model as one. Note: Any properties defined in a parent class muss be valid if set as required.

using System;
using System.Web.Mvc;
using MultipleModelsDemo.ViewModels;

namespace MultipleModelsDemo.Controllers
{
    public class HomeController : Controller
    {
        public ActionResult Index()
        {
            var model = new IndexViewModel();
            model.HeaderText = "Strongly typed model used here, no view bag";
            return View(model);
        }

        public ActionResult MyEditActionOne(IndexViewModel model)
        {
            if (ModelState.IsValid)
            {
                return View("Index", model);
            }

            throw new Exception("My Model state is not valid");
        }
    }
}

The html uses razor and can send either a form with just the first child model, or the second child model or the whole model as one. Only what is required for each form is validated. This is due to the model structure.

@model MultipleModelsDemo.ViewModels.IndexViewModel

<div>
    @using (Html.BeginForm("MyEditActionOne", "Home"))
    {
        <div>
            <h4>Send Model One</h4>
            <fieldset>
                @Html.ValidationSummary(true, "ValidationSummary")
                <ol>

                    <li>
                        @Html.LabelFor(m => m.TestOne.PropertyOne)
                        @Html.TextBoxFor(m => m.TestOne.PropertyOne)
                        @Html.ValidationMessageFor(m => m.TestOne.PropertyOne)
                    </li>
                    <li>
                        @Html.LabelFor(m => m.TestOne.PropertyTwo)
                        @Html.TextBoxFor(m => m.TestOne.PropertyTwo)
                        @Html.ValidationMessageFor(m => m.TestOne.PropertyTwo)
                    </li>
                </ol>
            </fieldset>
            
            <input class="btn" type="submit" value="Send" />
        </div>
    }
</div>
<div>
    @using (Html.BeginForm("MyEditActionOne", "Home"))
    {
        <div>
            <h4>Send both Models</h4>
            <fieldset>
                @Html.ValidationSummary(true, "ValidationSummary")
                <ol>

                    <li>
                        @Html.LabelFor(m => m.TestOne.PropertyOne)
                        @Html.TextBoxFor(m => m.TestOne.PropertyOne)
                        @Html.ValidationMessageFor(m => m.TestOne.PropertyOne)
                    </li>
                    <li>
                        @Html.LabelFor(m => m.TestOne.PropertyTwo)
                        @Html.TextBoxFor(m => m.TestOne.PropertyTwo)
                        @Html.ValidationMessageFor(m => m.TestOne.PropertyTwo)
                    </li>
                    <li>
                        @Html.LabelFor(m => m.TestTwo.PropertyThree)
                        @Html.TextBoxFor(m => m.TestTwo.PropertyThree)
                        @Html.ValidationMessageFor(m => m.TestTwo.PropertyThree)
                    </li>
                    <li>
                        @Html.LabelFor(m => m.TestTwo.PropertyFour)
                        @Html.TextBoxFor(m => m.TestTwo.PropertyFour)
                        @Html.ValidationMessageFor(m => m.TestTwo.PropertyFour)
                    </li>
                </ol>
            </fieldset>

            <input class="btn" type="submit" value="Send" />
        </div>
    }
</div>

As shown, it is very easy to implement multiple strongly typed models in a single view. Using this structure it would also be possible to implement a dynamic view with multiple forms or data.

Links:

http://www.asp.net/mvc

http://www.asp.net/mvc/overview/views

http://www.asp.net/mvc/overview/models-%28data%29

3 comments

  1. Your blog contains huge of nice article. It is very impressive.

  2. thank you!!

  3. Blake · · Reply

    Thank you. Very clearly explained

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: