How to use ViewModels in ASP.NET MVC?
Asked Answered
S

2

9

I just started learning about ViewModels in ASP.NET MVC. So, I thought of implementing a sample example as below:

Business Entity

public class AddModel
{
    public int a { get; set; }
    public int b { get; set; }

    public int Add()
    {
        return (this.a + this.b);
    }
}

Add ViewModel

public class AddViewModel
{
    public AddModel addModel;
    public int Total { get; set; }
}

Controller

public class AddController : Controller
{
    [HttpPost]
    public JsonResult Add(AddViewModel model)
    {

        int iSum = model.addModel.a + model.addModel.b;
        model.Total = iSum;
        return Json(model);

    }

    public ActionResult Index()
    {
        return View();
    }
}

View Implementation

@model ViewModelApplication.AddViewModel
<script type="text/javascript" src="../../Scripts/MicrosoftAjax.js"></script>
<script src="../../Scripts/MicrosoftMvcAjax.debug.js" type="text/javascript"></script>
<script type="text/javascript">
    function Callback(data) {
        alert("I am sucess call");
    }

    function Failed() {
        alert("I am a failure call");
    }
</script>

@using (Ajax.BeginForm("Add", "Add", new AjaxOptions { OnSuccess = "Callback", OnFailure = "Failed" }))
{
    <table align="center">
        <tr>
            <td class="tdCol1Align">
                <label>
                    Number1</label>
            </td>
            <td class="tdCol2Align">
                @Html.TextBoxFor(Model => Model.addModel.a)
            </td>
        </tr>
        <tr>
            <td class="tdCol1Align">
                <label>
                    Number2</label>
            </td>
            <td class="tdCol2Align">
                @Html.TextBoxFor(Model => Model.addModel.b)
            </td>
        </tr>
        <tr>
            <td colspan="2" align="center">
                <input type="submit" value="Add" class="button" />
            </td>
        </tr>
    </table>
}

The problem here is that I am unable to retrieve the values entered into the text boxes whenever the Add button is clicked; the corresponding AJAX action is being it.

When I try to access the values of a and b, I get nulls instead of the values entered into the text boxes.

I am not sure where I am going wrong. Please help.

Scarface answered 2/12, 2013 at 8:24 Comment(4)
Do you see the expected values in the form collection? I'm not quite sure, but since your doing an AJAX-postback I believe you model is being serialized when you do a postback. The controller might not recognize it anymore as a viewmodel, but sees it as an collection of posted values. But again, i'm not sure this is what is happening..Bocock
@Rob..yes i could see the values in the form collectionScarface
In general it's not a good idea to include the Model as part of the ViewModel.Repartee
@haim770..i agree with you..but what is the alternative to it..Scarface
F
7

your view model should look like this

public class AddViewModel
    {
        public int a { get; set; }
        public int b { get; set; }
        public int Total { get; set; }
    }

and in the cshtml

            <td class="tdCol2Align">
                @Html.TextBoxFor(m=> m.a)
            </td>

            <td class="tdCol2Align">
                @Html.TextBoxFor(m=> m.b)
            </td>

in the controller

        [HttpPost]
        public JsonResult Add(AddViewModel model)
        {
            int iSum = model.a + model.b;
            model.Total = iSum;
            return Json(model);

        }

Edit

View model is there to render your views don't place any logic inside that. if you have more complex model then it will be hard to map Model with ViewModel. for this you can use AutoMapper or ValueInjector for mapping between model and view model.

link for automapper http://automapper.codeplex.com/

link for value injector http://valueinjecter.codeplex.com/

hope this helps

Fortuitism answered 2/12, 2013 at 10:7 Comment(1)
@Anto..what if u have 20 fields..in the domain model..and i want all of them along with 5 other fields..Scarface
P
5

You should not use the domain (business) entities in your view model. If you do, a view model is pretty useless since it stills contains business logic which you might not want in the view. The model in your example doesn't really represent a real-world scenario, a view model is not really needed for it anyway.

A more common and trivial example of a view model is a login form: You probably have a domain model called User and you want them to log in. The User domain model can be big and just a small part of it is needed for the authentication. It also contains validation logic for the database which doesn't represent validation logic for the login form.

The User domain model:

public class User
{
    [Required]
    public string UserName { get; set; }

    [Required]
    [MaxLength(36)] // The password is hashed so it won't be bigger than 36 chars.
    public string Password { get; set; }

    public string FullName { get; set; }

    public string SalesRepresentative { get; set; }

    // etc..
}

The above domain model represents the database table thus containing validation logic to ensure integrity.

public class LoginModel
{
    [Display(Name = "User Name")]
    [Required(ErrorMessage = "Please fill in your user name.")]
    public string UserName { get; set; }

    [Required(ErrorMessage = "Please fill in your password.")]
    public string Password { get; set; }

    public bool RememberMe { get; set; }
}

The view model above contains just the properties we need for the login form and has it's own data annotations. This helps you to cleanly separate view logic and business/data logic.

Parisian answered 2/12, 2013 at 9:37 Comment(4)
..Thanks for the explanation . But , what if my domain model contains 20 fields and i need 2 more extra fields. Do, i need to put all those fields in the view model which are already there in Domain model..Scarface
@Henk..in my example , view model can be needed in the case where we do not want to create anonymous object while sending back results to view(Example - total in my scenario)Scarface
@Avinash yes sometimes view models are a copy of domain models with, but usually they contain other validation attributes and contain data annotations for display names etc. My personal experience is that I always get in trouble when using domain models in my view.Parisian
@Avinash with a domain model as simple as in your example, you could use it directly in your view. In other words: it's not a good test case for practicing with view models and understanding why you need them.Parisian

© 2022 - 2024 — McMap. All rights reserved.