views:

168

answers:

3

This is more of a architect question rather than one that requires code.

I have a page that requires me to display the status of a particular project. Let's say for the sake or brevity that there are two states, Open and Closed.

When the project is open I want to display a PartialView showing me one set of details. If the project is Closed I want to show a PartialView with different details.

Now I know I could do a check in the aspx and render one or the other but I'm trying to cut down on the number of decision points within the aspx code. I believe that there should be a minimum of actual code within the aspx.

Also, there are more then two states so the "if" statements would pile up and become messy.

Has anyone tackled something like this?

Should I create a Helper to do this? Can I, and I'm unsure how to do this, handle this in the ActionResult of the view? So for example, can I render the PartialViews in the action result and return that as part of the normal view?

+6  A: 

You could do the logic in the controller and define a ViewData value that contains the name of the partial to render... so in the controller,

if (Project.Status == "Open") {
    ViewData["StatusPartial"] = "OpenPartial";
} else {
    ViewData["StatusPartial"] = "ClosedPartial";
}

Then in the aspx just do

<%=Html.RenderPartial(ViewData["StatusPartial"]) %>
Chris Gutierrez
+1. I like that idea so far. Thanks.
griegs
Very simple and keeps the logic where it should be. I like it.
Jaco Pretorius
This is by far the simplest solution, but it has a couple of flaws: * "Magic strings" (well, maybe not that magic - but they're not strongly typed) * Redundant saving of the project status information in two places (`ViewData["StatusPartial"]` and in the property of the model object)
Tomas Lycken
+4  A: 

If you code your project's status as an Enum, you could actually just get the correct partial to be shown without any if clauses at any point, using this neat trick:

<% Html.RenderPartial(Enum.GetName(typeof(ProjStat), prj.Status) + 'Partial'); %>

In the above example I've assumed that the name of the Enum is ProjStat, and that you have a naming convention of your partial views corresponding to OpenPartial.ascx and ClosedPartial.ascx for the two status values Open and Closed.

Tomas Lycken
This is a pretty cool solution! Good idea!
Chris Gutierrez
+1, yeah that is actually pretty neat.
griegs
+3  A: 

I like @Chris Gutierrez's solution, but I would use a property on your ViewModel rather than a named entry in ViewData. You might combine that with a Map on the controller to to save a little code -- the sample assumes that Status.Open maps to 0, and Status.Closed maps to 1.

private readonly static string[] StatusViews
     = new string[] { "OpenPartial", "ClosedPartial" };

...
model.StatusView = StatusViews[(int)Project.Status];


<%= Html.RenderPartial( Model.StatusView ) %>
tvanfosson
+1. Right, and to make it extensible I could load in the values from a db or config.
griegs
This is a good modification of Chris's solution - however, it is likely that the view is already rendering other things about this project, and it seems redundant to have the status both as a property of the `Project` entity and as a separate property on the `ViewModel`.
Tomas Lycken
Grnated I've only being working with MVC for a little over a year, but the pattern I've gravitated towards is a separate View-only model per view. This view model usually wraps the business model with a few extra items for the view such as, in this case, which partial to choose if there are options. I'm not sure exactly how I would handle this one -- I'm not as reluctant to use logic in my views **and** choosing how to render something does seem to me to be a function of the view not the controller. Probably I'd just use an if/then/else construct in the view based on the model property.
tvanfosson