Saturday, May 24, 2014

Handling complex view models in Razor in Asp.Net MVC

Sometimes we all face some difficulties while handling some complex view models in mvc. Most of them are happens while passing view model back to controller form razor view. Following example describes some clear information regarding complex model binding

Here is my complex model,

namespace FEWO.Web.Models
{
    public class PriceModel
    {
        public Guid Id { get; set; }
        public Guid SeasonTimesId { get; set; }
        public Guid CategoryId { get; set; }
        public Guid PercentageId { get; set; }
        public Guid PriceTypeId { get; set; }
        public decimal Value { get; set; }

        public virtual Category Category { get; set; }
        public virtual Percentage Percentage { get; set; }
        public virtual Price_Type Price_Type { get; set; }
        public virtual SeasonTime SeasonTime { get; set; }
    }

    public class GroupedPriceModelBySeasonTime
    {
        public string GroupName { get; set; }
        public List<PriceModel> PriceModelList { get; set; }
    }

      public class HolidayComplexPriceModel
    {
        public Guid HolidayComplexId { get; set; }
        public string Year { get; set; }
        public List<GroupedModelBySeasonTime> SeasonTimeGroupedModel { get; set; }
    }
}


Here I want to pass the HolidayComplexPriceModel to the view from action method. In action method i will bind this view model a follows

List<PriceModel> priceViewModel  = _repo.GetPriceModelList();
List<GroupedModelBySeasonTime> gmodel = new List<GroupedModelBySeasonTime>();
foreach (var item in priceViewModel.GroupBy(con => con.SeasonTimesId).ToList())
   {
        GroupedModelBySeasonTime  m = new GroupedModelBySeasonTime();
         m.GroupName = item.ElementAt(0).SeasonTime.Season_Shortcut
         List<PriceModel> pmodel = new List<PriceModel>();
                foreach (var items in item.OrderBy(con => con.Category.Category_Name))
                 {
                    pmodel.Add(items);
                  }
          m.PriceModelList = pmodel;
          gmodel.Add(m);
    }

return new HolidayComplexPriceModel(){ SeasonTimeGroupedModel  = gmodel }

Following are the important tips, what are the usual mistakes we might do in razor,

1. Dont use any foreach loop to bind the view model, use for loop

    Ex -
 @using (Html.BeginForm("Index", "Price", FormMethod.Post, new { enctype = "multipart/form-data",
  id = "SavePrice" }))
   {
    foreach(var item in Model.SeasonTimeGroupedModel) {}
   // if you use foreach then you might bind element like  item.Id, then razor viewmodel didnot realize the  model    property. So need to bind like this, Model.SeasonTimeGroupedModel[0].Id

    Use simple for loop like below,
  for (int i = 0; i < Model.SeasonTimeGroupedModel.Count; i++) {}
  }

2. Dont do any grouping in view, do the gruoping in controller action. If grouping happens in view,
    ex- var groupList = Model.ExampleList.Group(x => x.Id);  then you need to bind elements like below
    @Html.TextBoxFor(model => groupList.Name) then Razor didnot realize the model property.

3. Using nested for loops,
     @for (int i = 0; i < Model.SeasonTimeGroupedModel.Count; i++)
        {
                  Model.SeasonTimeGroupedModel[i].GroupName
                  for (int e = 0; e < Model.SeasonTimeGroupedModel[i].PriceModelList.Count; e++)
                   {
                    Html.TextBoxFor(model => Model.SeasonTimeGroupedModel[i].PriceModelList[e].Value)
                   }
        }

4. Dont use any action link to post complex view model. It is clear that action link wont post complex      model. if you want to use multiple post in single view then use multiple submits
 Example
  <input type="submit"  name="submitbutton1" value="submit1" />
  <input type="submit"  name="submitbutton2" value="submit2" />

   In controller action differentiate both by
   if (Request.Form["submitbutton1"] != null)
    {
     // Submit button 1 function goes in here
    }
    if (Request.Form["submitbutton2"] != null)
    {
     // Submit button 2 function goes in here
    }

Cool. Those are some few tips from me to keep coding happily, Enjoy :)