Dynamic Views in ASP.NET MVC 2

One of the new features introduced in C# 4.0 is the dynamic keyword. So far I haven’t had much use for it, but lately I’ve discovered that it can be very useful when designing ASP.NET MVC views. It also has uses when interacting with COM APIs and other dynamic languages, but I’m going to focus on its use in MVC.

If you’re using .NET 4.0 and ASP.NET MVC 2, and go to add a new view that is not strongly typed, you might notice that the first line will look like this:

<%@ Page Language="C#" Inherits="System.Web.Mvc.ViewPage<dynamic>" %>

The thing to pay attention to here is that by default, non-strongly typed views now use a dynamic model by default. As with any use of dynamic you lose the compiler’s type checking in your view (if you’re not compiling your views I would recommend doing so), and your intellisense of course. That said, you do gain quite a bit of freedom when you only have to worry about the properties of the model, rather than the specific type.

Let’s use a very simple example to demonstrate a cool use of dynamic view models with a partial view. We will define a partial view that displays today’s date, and can take in a set of options about what aspects of the date to display. The options class is defined as:

public class DateDisplayOptions
{
    public bool ShowYear { get; set; }

    public bool ShowTime { get; set; }
}

Then we have the partial defined like this, using the options class as its view model:

<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<DynamicViewSample.Models.DateDisplayOptions>" %>

<%: DateTime.Now.ToString("MMMM d") %>

<% if (Model.ShowYear)
   { %>
    <%: DateTime.Now.ToString(", yyyy")%>

<% } %>

<% if (Model.ShowTime)
   { %>

    <%: DateTime.Now.ToShortTimeString() %>

<% } %>

That will use the options to format today’s date and time appropriately. Now let’s say that we wanted to make it so that if you don’t pass an options object to the partial, it uses some default values. First, we add a constructor to DateDisplayOptions to set default values:

public DateDisplayOptions()
{
    ShowYear = true;
    ShowTime = false;
}

Next, we have to tell the view to allow for receiving a null view model:

<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<DynamicViewSample.Models.DateDisplayOptions>" %>
<%@ Import Namespace="DynamicViewSample.Models" %>

<%
    DateDisplayOptions options = Model ?? new DateDisplayOptions();
%>

<%: DateTime.Now.ToString("MMMM d") %>

<% if (options.ShowYear)
   { %>

    <%: DateTime.Now.ToString(", yyyy")%>

<% } %>

<% if (options.ShowTime)
   { %>

    <%: DateTime.Now.ToShortTimeString() %>

<% } %>

Now passing in a null view model will display the year but not the time. However, this only gets us part of the way there. When using the RenderPartial method, not explicitly supplying a model to the partial will automatically send the model of the calling page. Obviously that will cause type casting problems when the calling page has a view model that is not DateDisplayOptions, so this is where the dynamic keyword comes to the rescue. We can change the partial to use the dynamic type, and then check for the type ourselves when casting:

<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<dynamic>" %>
<%@ Import Namespace="DynamicViewSample.Models" %>

<%
    DateDisplayOptions options = (Model as DateDisplayOptions) ?? new DateDisplayOptions();
%>

With that change, the partial will not care what type of model gets sent to it, but if it is not a DateDisplayOptions it will use a new instance with the default options instead.  Let’s throw together a quick view to test everything out:

<p>
    <% Html.RenderPartial("ShowToday"); %>
</p>
<p>
    <% Html.RenderPartial("ShowToday", new DateDisplayOptions { ShowTime = false, ShowYear = false }); %>
</p>
<p>
    <% Html.RenderPartial("ShowToday", new DateDisplayOptions { ShowTime = true, ShowYear = true }); %>
</p>

That gives us the following output, which behaves exactly like we wanted:

There are certainly a lot more uses out there for the dynamic keyword, but this is one example I stumbled upon where it came in very useful.

You can download a working sample project containing all of this code here.

Tags: , ,

9 Responses to “Dynamic Views in ASP.NET MVC 2”

  1. [...] This post was mentioned on Twitter by Greg Shackles. Greg Shackles said: New blog post: Dynamic Views in ASP.NET MVC 2 http://shackl.es/bZ2z4b #dotnet #aspdotnet #mvc #tech [...]

  2. Dynamic Views in ASP.NET MVC 2…

    Thank you for submitting this cool story – Trackback from DotNetShoutout…

  3. [...] Dynamic Views in ASP.NET MVC 2 – Greg Shackles takes a look at using the new C# dynamic keyword as the type for an ASP.NET MVC Model, allowing your view code to be completely dynamic. [...]

  4. Динамические представления в ASP.NET MVC 2…

    Thank you for submitting this cool story – Trackback from progg.ru…

  5. Thanigainathan

    Thanks for sharing this good article.

    Thanks,
    Thani

  6. Monolight

    Good Post!
    Thanks for sharing this cool action to explain it.
    Monolight

  7. Maybe instead spend that time improving the logic of encoding posts, huh?

    Totally unnecessary. Instead of typing this:

    [% Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl[DynamicViewSample.Models.DateDisplayOptions ]” %]

    you have to type this:

    [%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl[dynamic]” %]

    [%
    DateDisplayOptions options = (Model as DateDisplayOptions) ?? new DateDisplayOptions();
    %]

    not to mention that it’s more confusing now, and that we all have to go through at least one article to understand the new mapping (15+ min). What was achieved? Alternative approach. Time well spent. I’m sure hours spent on developing that could have been used for something more useful. Good job, Guthrie!

  8. There’s nothing forcing you to use a dynamic view. The point of this article was to showcase a specific use case of when a dynamic view can get you, and maybe help open the doors to finding some new ones. The first example used a partial with a strongly typed view, which seems to be what you wanted, so it’s certainly possible (and in most cases, what you’d want to do).

  9. I understand, but I’m just saying how that new way of passing data from the controller/action to the view brings nothing beneficial, except the definition changed a little bit, and you’re spared from defining the model object at the controller/action, while you now have to do it in the view.

    I’m frustrated a little because there are tons of problems with a lot of MS components: IE, VS, etc, etc – and instead of spending time fixing them, they invest 300 hours in writing that stupid feature that’s purely syntactic. I learned nothing expect wasting time going through it – while the find-replace box is broken in VS2010 (at least on 2 monitors) and closing individual document in the same IDE is less convinient. WTF?!

Leave a Reply