-->

09/09/2011

View Controling in MVC.

We all know how View, Model, Controller communicates with each other.

















Everything a View expects is a Model object sent by controller. So, nothing else can effect the View.
So, what if you have a Grid View which has multiple columns and will display them based on certain roles.Keep in mind that View didn't support any CS files.

There are 2 ways of doing it.
1. Create separate Views and invoke them from controller based on the role.
2. Controlling the View by making Visibility matrix as a part of Model.(View Controling)

I believe APPROACH1 is not so appealing, as both the development cost and maintenance cost will be more with it.

So, i have chosen Approach2.


Lets see the sample project which i have developed.

Step 1: I created a model supporting data from different roles. For every Data element, i added two features IsEdit and IsVisible to support Visibility Matrix as a part of Model.

public class GridViewModel
    {
        public string Goal{get;set;}
        public string Self { get; set; }
        public bool SelfIsEdit { get; set; }
        public string ML { get; set; }
        public bool MLIsEdit { get; set; }
        public bool MLIsVisible { get; set; }
        public string RMD { get; set; }
        public bool RMDIsEdit { get; set; }
        public bool RMDIsVisible { get; set; }
        public string SE { get; set;}
        public bool SEIsEdit { get; set; }
        public bool SEIsVisible { get; set; }
        public string LE { get; set; }
        public bool LEIsEdit { get; set; }
        public bool LEIsVisible { get; set; }
        public string FL { get; set; }
        public bool FLIsEdit { get; set; }
        public bool FLIsVisible { get; set; }
    }

Step 2: I created a class defining the data for different roles and their visibility Matrix. In real time scenario, this class will be talking to DB and fetching both Data & Visibility matrix as a part of Model.


public class ModelExtractor
    {
        public List GetFLData()
        {
            List list = new List();
            GridViewModel me = new GridViewModel();

            me.Goal = "Goal Amount";
            me.Self = "Self Amount";
            me.SelfIsEdit = false;
            me.RMD = "RMD Amount";
            me.RMDIsEdit = false;
            me.RMDIsVisible = true;
            me.ML = "Approver1 Amount";
            me.MLIsEdit = false;
            me.MLIsVisible = true;
            me.SE = "SE Amount";
            me.SEIsEdit = false;
            me.SEIsVisible = true;
            me.LE = "Approver2 Amount";
            me.LEIsEdit = false;
            me.LEIsVisible = true;
            me.FL = "Approver3 Amount";
            me.FLIsEdit = true;
            me.FLIsVisible = true;

            list.Add(me);
            return list;
        }

}

Step 3: Now I defined the action method with a parameter as Role Name.
Based on the role, i will call pertaining method on DataExtractor class, and will return the model to View.
public class GridViewController : Controller
    {
        public ActionResult CommonView(string Role)
        {
            var model =new List();
            ModelExtractor ME = new ModelExtractor();
            
            switch (Role.ToUpper())
            {
                case "SELF":
                    model = ME.GetSelfData();
                    break;
                case "RMD":
                    model = ME.GetRMDData();
                    break;
                case "ML":
                    model = ME.GetMLData();
                    break;
                case "SE":
                    model = ME.GetSEData();
                    break;
                case "LE":
                    model = ME.GetLEData();
                    break;
                case "FL":
                    model = ME.GetFLData();
                    break;
                default:
                break;
            }
            return View(model);            
        }

    }

Step 4: All the required data is with view in form of model. Now, the view have to be created using HTML helper methods controlling the Controls displayed on the view based on Visibility Matrix defined in Model.
@model IEnumerable<MVCViewController.Models.GridViewModel>

@{
    ViewBag.Title = "CommonView";
}

<h2>CommonView</h2>

<p>
    
</p>
<table>
@foreach (var item in Model) {
    <tr>    
        <th>
            Goal
        </th>
        <th>
            Self
        </th>
      
        <th style="display:@(item.MLIsVisible==true?"block'":"none")">
            Approver1
        </th >       
        <th style="display:@(item.LEIsVisible==true?"block'":"none")">
           Approver2
        </th>
       
        <th style="display:@(item.FLIsVisible==true?"block'":"none")">
            Approver3

        </th>
        
        
    </tr>


    <tr>
        <td >
            @Html.DisplayFor(modelItem => item.Goal)
        </td>
       <td style="width:100PX" valign="middle">
        <div class="editor-label" style="display:@(item.SelfIsEdit==false?"block'":"none")">
            @Html.DisplayFor(modelItem => item.Self)
        </div>
        <div class="editor-field" style="display:@(item.SelfIsEdit==true?"block'":"none")" >
            @Html.EditorFor(modelItem => item.Self)
            @Html.ValidationMessageFor(modelItem => item.Self)
            
        </div>

      </td>
      <td style="width:100PX;display:@(item.MLIsVisible==true?"block'":"none")" valign="middle">

        <div class="editor-label" style="display:@(item.MLIsEdit==false?"block'":"none")">
            @Html.DisplayFor(modelItem => item.ML)
        </div>
        <div class="editor-field" style="display:@(item.MLIsEdit==true?"block'":"none")">
            @Html.EditorFor(modelItem => item.ML)
            @Html.ValidationMessageFor(modelItem => item.ML)
        </div>

       </td>
       <td style="width:100PX;display:@(item.LEIsVisible==true?"block'":"none")" valign="middle">
        <div class="editor-label" style="display:@(item.LEIsEdit==false?"block'":"none")">
            @Html.DisplayFor(modelItem => item.LE)
        </div>
        <div class="editor-field" style="display:@(item.LEIsEdit==true?"block'":"none")">
            @Html.EditorFor(modelItem => item.LE)
            @Html.ValidationMessageFor(modelItem => item.LE)
        </div>

      </td><td style="width:100PX;display:@(item.FLIsVisible==true?"block'":"none")" valign="middle">

        <div class="editor-label" style="display:@(item.FLIsEdit==false?"block'":"none")">
            @Html.DisplayFor(modelItem => item.FL)
        </div>
        <div class="editor-field" style="display:@(item.FLIsEdit==true?"block'":"none")">
            @Html.EditorFor(modelItem => item.FL)
            @Html.ValidationMessageFor(modelItem => item.FL)
        </div>

       </td>
    </tr>
}

</table>

Step 5: At the end of the View, i accommodated links using ActionLink() html helper method for changing the role viewing the Common View.

<ul id="menu">
    <li>@Html.ActionLink("Self View", "CommonView", "GridView",new{Role="SELF"},null)</li>
    <li>@Html.ActionLink("Approver1  View", "CommonView", "GridView", new { Role = "ML" },null)</li>
    <li>@Html.ActionLink("Approver2  View", "CommonView", "GridView", new { Role = "LE" },null)</li>
    <li>@Html.ActionLink("Approver3  View", "CommonView", "GridView", new { Role = "FL" },null)</li>
</ul>

Form the above code block, you can see how parameters can be sent to a action method.

"Self View"  - This is the text that should be displayed on Action Link.
"CommonView" - This is the name of the Action Method.
"GridView" - Name of the Controller.
"new{Role="Self"}" - Here Role is the Parameter to the action method.

Out Put:

"Self View"
"Approver1 View"















"Approver3 View"
This is how we can control a single view supporting display for different roles using View Controling Approach.

Is it helpful for you? Kindly let me know your comments / Questions.

No comments:

Post a Comment