Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What's the recommended pattern for handling control display logic in ASP.NET MVC?

I'm going through some of the MVC3 tutorials, namely the Pluralsight videos, and I'm thinking of how our existing application would function if it were overhauled to ASP.NET MVC (not the plan, but it gives me a frame of reference). We have quite a bit of code that looks something like this in our aspx code-behinds:

if (SomeBooleanCheck){SomeControl.Visible = true;}else {SomeControl.Visible = false;}

Granted that example is greatly simplified, but assuming the boolean logic is fairly complex and assuming multiple things need to happen as part of making the control visible (maybe changing color, size, text, etc.) what's the pattern for doing this in ASP.NET MVC? It seems like you'd have to do that same boolean checking in the view itself, which to me seems kind of ugly. Seems like there has to be a better way and this surely came up on MS's use case list, I'm just not seeing the answer.

like image 389
Shawn Hubbard Avatar asked May 21 '11 11:05

Shawn Hubbard


2 Answers

The approach you may take will vary greatly depending on the specific scenario. A few options incude:

  • Doing as you say and adding the conditional in the view
  • Abstracting the conditional (if it is complex) into your view model so that the lines in the view are still simple (just accessing a preset boolean value on your view model).
  • Doing this conditional at the route or controller level and calling a different overall view (which may share a layout (razor) or master view (webforms mvc))

You don't mention explicitly how you would render the controls in the conditional. I assume you would be doing a RenderPartial. So the lines themselves in the view would be quite 'small'.

if(myViewModel.ComplexBoolean) // Boolean set in generation of view model
    Html.RenderPartial('firstPartial')
else
    Html.RenderPartial('secondPartial')

EDIT: If the item you are setting as 'visible' is simply a single control you may just output the control directly e.g.

if(myViewModel.ComplexBoolean) {
    Html.DropDownListFor(m => m.Type, Model.Types /* An IEnumerable<SelectListItem>*/, new { @class = "myList" });
}

Additionally if you didn't want to set that 'Model.Types' property (to save a db hit for example) then the conditional could be in the location you create your view model (either the controller or some service/view model repo). The view could then just check for the properties existance instead:

if(Model.Types != null) {
    Html.DropDownListFor(m => m.Type, Model.Types /* An IEnumerable<SelectListItem>*/, new { @class = "myList" });
}
like image 158
Cargowire Avatar answered Oct 13 '22 10:10

Cargowire


If your controls does not use the data found in your View's ViewModel, you can also use Html.RenderAction to call Child Actions. For example, suppose you want to display a different menu to users with different roles. You can call @{Html.RenderAction("Menu", "Account");} in your View, which will call the "Menu" Action in your "Account" controller. Your complex Boolean logic and the logic to formulate your controllers’ settings will reside in the "Account" controller's "Menu" action. The "Menu" action will decide what Partial View/Controller to display.

// This goes in your View (clean single line!)

@{Html.RenderAction("Menu", "Account");}


// This goes in your controller

[ChildActionOnly]
public ActionResult Menu()
{
    bool isAdmin = false;

    // Your complex boolean logic goes here

    // Set your controller settings here

    string controllerSettings = ""; // Use class or array for multiple settings

    if (isAdmin)
    {
        return PartialView("~/Views/Account/_AdminMenu.cshtml", controllerSettings);
    }
    else
    {
        return PartialView("~/Views/Account/_StandardMenu.cshtml", controllerSettings);
    }
}
like image 22
Ryan Leyesa Avatar answered Oct 13 '22 10:10

Ryan Leyesa