Back to the future! Exploring ASP.NET MVC Futures

Edit on GitHub

Back to the future!For those of you who did not know yet: next to the ASP.NET MVC 1.0 version and its source code, there’s also an interesting assembly available if you can not wait for next versions of the ASP.NET MVC framework: the MVC Futures assembly. In this blog post, I’ll provide you with a quick overview of what is available in this assembly and how you can already benefit from… “the future”.

kick it on DotNetKicks.com 

First things first: where to get this thing? You can download the assembly from the CodePlex releases page. Afterwards, reference this assembly in your ASP.NET MVC web application. Also add some things to the Web.config file of your application:

[code:c#]

<?xml version="1.0"?>
<configuration>
    <!-- ... -->
    <system.web>
        <!-- ... -->

        <pages>
            <controls>
                <!-- ... -->
                <add tagPrefix="mvc" namespace="Microsoft.Web.Mvc.Controls" assembly="Microsoft.Web.Mvc"/>
            </controls>
            <namespaces>
                <!-- ... -->
                <add namespace="Microsoft.Web.Mvc"/>
                <add namespace="Microsoft.Web.Mvc.Controls"/>
            </namespaces>
        </pages>

        <!-- ... -->
    </system.web>
    <!-- ... -->
</configuration>

[/code]

You are now ready to go! Buckle up and start your De Lorean DMC-12…

Donut caching (a.k.a. substitution)

If you have never heard of the term “donut caching” or “substitution”, now is a good time to read a previous blog post of mine. Afterwards, return here. If you don’t want to click that link: fine! Here’s in short: “With donut caching, most of the page is cached, except for some regions which are able to be substituted with other content.”

You’ll be needing an OutputCache-enabled action method in a controller:

[code:c#]

[OutputCache(Duration = 10, VaryByParam = "*")]
public ActionResult DonutCaching()
{
    ViewData["lastCached"] = DateTime.Now.ToString();

    return View();
}

[/code]

Next: a view. Add the following lines of code to a view:

[code:c#]

<p>
    This page was last cached on: <%=Html.Encode(ViewData["lastCached"])%><br />
    Here's some "donut content" that is uncached: <%=Html.Substitute( c => DateTime.Now.ToString() )%>
</p>

[/code]

There you go: when running this application, you will see one DateTime printed in a cached way (refreshed once a minute), and one DateTime printed on every page load thanks to the substitution HtmlHelper extension. This extension method accepts a HttpContext instance which you can also use to enhance the output.

Now before you run away and use his in your projects: PLEASE, do not do write lots of code in your View. Instead, put the real code somewhere else so your view does not get cluttered and your code is re-usable. In an ideal world, this donut caching would go hand in hand with our next topic…

Render action methods inside a view

You heard me! We will be rendering an action method in a view. Yes, that breaks the model-view-controller design pattern a bit, but it gives you a lot of added value while developing applications! Look at this like “partial controllers”, where you only had partial views in the past. If you have been following all ASP.NET MVC previews before, this feature already existed once but has been moved to the futures assembly.

Add some action methods to a Controller:

[code:c#]

public ActionResult SomeAction()
{
    return View();
}

public ActionResult CurrentTime()
{
    ViewData["currentTime"] = DateTime.Now.ToString();

    return View();
}

[/code]

This indeed is not much logic, but here’s the point: the SomeAction action method will render a view. That view will then render the CurrentTime action method, which will also render a (partial) view. Both views are combined and voila: a HTTP response which was generated by 2 action methods that were combined.

Here’s how you can render an action method from within a view:

[code:c#]

<% Html.RenderAction("CurrentTime"); %>

[/code]

There’s also lambdas to perform more complex actions!

[code:c#]

<% Html.RenderAction<HomeController>(c => c.CurrentTime()); %>

[/code]

What most people miss: controls

Lots of people are missing something when first working with the ASP.NET MVC framework: “Where are all the controls? Why don’t all ASP.NET Webforms controls work?” My answer would normally be: “You don’t need them.”, but I now also have an alternative: “Use the futures assembly!”

Here’s a sample controller action method:

[code:c#]

public ActionResult Controls()
{
    ViewData["someData"] = new[] {
        new {
            Id = 1,
            Name = "Maarten"
        },
        new {
            Id = 2,
            Name = "Bill"
        }
    };

    return View();
}

[/code]

The view:

[code:c#]

<p>
    TextBox: <mvc:TextBox Name="someTextBox" runat="server" /><br />
    Password: <mvc:Password Name="somePassword" runat="server" />
</p>
<p>
    Repeater:
    <ul>
    <mvc:Repeater Name="someData" runat="server">
        <EmptyDataTemplate>
            <li>No data is available.</li>
        </EmptyDataTemplate>
        <ItemTemplate>
            <li><%# Eval("Name") %></li>
        </ItemTemplate>
    </mvc:Repeater>
    </ul>
</p>

[/code]

As you can see: these controls all work quite easy. The "Name property accepts the key in the ViewData dictionary and will render the value from there. In the repeater control, you can even work with “good old” Eval: <%# Eval("Name") %>.

Extra HtmlHelper extension methods

Not going in too much detail here: there are lots of new HtmlHelper extension methods. The ones I especially like are those that allow you to create a hyperlink to an action method using lambdas:

[code:c#]

<%=Html.ActionLink<HomeController>(c => c.ShowProducts("Books"), "Show books")%>

[/code]

Here’s a list of new HtmlHelper extension methods:

  • ActionLink – with lambdas
  • RouteLink – with lambdas
  • Substitute (see earlier in this post)
  • JavaScriptStringEncode
  • HiddenFor, TextFor, DropDownListFor, … – like Hidden, Text, … but with lambdas
  • Button
  • SubmitButton
  • Image
  • Mailto
  • RadioButtonList

More model binders

Another thing I will only cover briefly: there are lots of new ModelBinders included! Model binders actually allow you to easily map input from a HTML form to parameters in an action method. That being said, here are the new kids on the block:

  • FileCollectionModelBinder – useful for HTTP posts that contain uploaded files
  • LinqBinaryModelBinder
  • ByteArrayModelBinder

When you want to use these, do not forget to register them with ModelBinders.Binders in your Global.asax.

More ActionFilters and ResultFilters

Action filters and result filters are used to intercept calls to an action method or view rendering, providing a hook right before and after that occurs. This way, you can still modify some variables in the request or response prior to, for example, executing an action method. Here’s what is new:

  • AcceptAjaxAttribute – The action method is only valid for AJAX requests. It allows you to have different action methods for regular requests and AJAX requests.
  • ContentTypeAttribute – Sets the content type of the HTTP response
  • RequireSslAttribute – Requires SSL for the action method to execute. Allows you to have a different action method for non-SSL and SSL requests.
  • SkipBindingAttribute – Skips executing model binders for an action method.

Asynchronous controllers

This is a big one, but it is described perfectly in a Word document that can be found on the MVC Futures assembly release page. In short:

The AsyncController is an experimental class to allow developers to write asynchronous action methods. The usage scenario for this is for action methods that have to make long-running requests, such as going out over the network or to a database, and don’t want to block the web server from performing useful work while the request is ongoing.

In general, the pattern is that the web server schedules Thread A to handle some incoming request, and Thread A is responsible for everything up to launching the action method, then Thread A goes back to the available pool to service another request. When the asynchronous operation has completed, the web server retrieves a Thread B (which might be the same as Thread A) from the thread pool to process the remainder of the request, including rendering the response. The diagram below illustrates this point.

Asynchronous controllers

Sweet! Should speed up your ASP.NET MVC web application when it has to handle much requests.

Conclusion

I hope you now know what the future for ASP.NET MVC holds. It’s not sure all of this will ever make it into a release, but you are able to use all this stuff from the futures assembly. If you are too tired to scroll to the top of this post after reading it, here’s the link to the futures assembly again: MVC Futures assembly

kick it on DotNetKicks.com

This is an imported post. It was imported from my old blog using an automated tool and may contain formatting errors and/or broken images.

Leave a Comment

avatar

0 responses