Maarten Balliauw {blog}

Web development, NuGet, Microsoft Azure, PHP, ...

NAVIGATION - SEARCH

Using the ASP.NET MVC Futures AsyncController

Last week, I blogged about all stuff that is included in the ASP.NET MVC Futures assembly, which is an assembly available on CodePlex and contains possible future features (tonguetwister!) for the ASP.NET MVC framework. One of the comments asked for more information on the AsyncController that is introduced in the MVC Futures. So here goes!

kick it on DotNetKicks.com

Asynchronous pages

The AsyncController is an experimental class to allow developers to write asynchronous action methods. But… why? And… what? I feel a little confusion there. Let’s first start with something completely different: how does ASP.NET handle requests? ASP.NET has 25 threads(*) by default to service all the incoming requests that it receives from IIS. This means that, if you have a page that requires to work 1 minute before returning a response, only 25 simultaneous users can access your web site. In most situations, this occupied thread will just be waiting on other resources such as databases or webservice, meaning it is actualy waiting without any use while it should be picking up new incoming requests.

(* actually depending on number of CPU’s and some more stuff, but this is just to state an example…)

In ASP.NET Webforms, the above limitation can be worked around by using the little-known feature of “asynchronous pages”. That <%@ Page Async="true" ... %> directive you can set in your page is not something that had to do with AJAX: it enables the asynchronous page processing feature of ASP.NET Webforms. More on how to use this in this article from MSDN magazine. Anyway, what basically happens when working with async pages, is that the ASP.NET worker thread fires up a new thread, assigns it the job to handle the long-running page stuff and tells it to yell when it’s done so that the worker thread can return a response to the user. Let me rephrase that in an image:

Asynchronous page flow 

I hope you see that this pattern really enables your web server to handle more requests simultaneously without having to tweak standard ASP.NET settings (which may be another performance tuning thing, but we will not be doing that in this post).

AsyncController

The ASP.NET MVC Futures assembly contains an AsyncController class, which actually mimics the pattern described above. It’s still experimental and subject to change (or to disappearing), but at the moment you can use it in your application. In general, the web server schedules a worker thread to handle an incoming request. This worker thread will start a new thread and call the action method on there. The worker thread is now immediately available to handle a new incoming request. Sound a bit the same as above, no? Here’s an image of the AsyncController flow:

AsyncController thread flow

Now you know the theory, let’s have a look at how to implement the AsyncController pattern…

Preparing your project…

Before you can use the AsyncController, some changes to the standard “File > New > MVC Web Application” are required. Since everything I’m talking about is in the MVC Futures assembly, first grab the Microsoft.Web.Mvc.dll at CodePlex. Next, edit Global.asax.cs and change the calls to MapRoute into MapAsyncRoute, like this:

[code:c#]

routes.MapAsyncRoute(
    "Default",
    "{controller}/{action}/{id}",
    new { controller = "Home", action = "Index", id = "" }
);

[/code]

No need to worry: all existing synchronous controllers in your project will keep on working. The MapAsyncRoute automatically falls back to MapRoute when needed.

Next, fire up a search-and-replace on your Web.config file, replacing

[code:c#]

<add verb="*" path="*.mvc" validate="false" type="System.Web.Mvc.MvcHttpHandler, System.Web.Mvc, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>

<add name="MvcHttpHandler" preCondition="integratedMode" verb="*" path="*.mvc" type="System.Web.Mvc.MvcHttpHandler, System.Web.Mvc, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>

[/code]

with:

[code:c#]

<add verb="*" path="*.mvc" validate="false" type="Microsoft.Web.Mvc.MvcHttpAsyncHandler, Microsoft.Web.Mvc"/>

<add name="MvcHttpHandler" preCondition="integratedMode" verb="*" path="*.mvc" type="Microsoft.Web.Mvc.MvcHttpAsyncHandler, Microsoft.Web.Mvc"/>

[/code]

If you now inherit all your controllers from AsyncController instead of Controller, you are officially ready to begin some asynchronous ASP.NET MVC development.

Asynchronous patterns

Ok, that was a lie. We are not ready yet to start asynchronous ASP.NET MVC development. There’s a choice to make: which asynchronous pattern are we going to implement?

The AsyncController offers 3 distinct patterns to implement asynchronous action methods.. These patterns can be mixed within a single AsyncController, so you actually pick the one that is appropriate for your situation. I’m going trough all patterns in this blog post, starting with…

The IAsyncResult pattern

The IAsyncResult pattern is a well-known pattern in the .NET Framework and is well documened on MSDN. To implement this pattern, you should create two methods in your controller:

[code:c#]

public IAsyncResult BeginIndexIAsync(AsyncCallback callback, object state) { }
public ActionResult EndIndexIAsync(IAsyncResult asyncResult) { }

[/code]

Let’s implement these methods. In the BeginIndexIAsync method, we start reading a file on a separate thread:

[code:c#]

public IAsyncResult BeginIndexIAsync(AsyncCallback callback, object state) {
    // Do some lengthy I/O processing... Can be a DB call, file I/O, custom, ...
    FileStream fs = new FileStream(@"C:\Windows\Installing.bmp",
        FileMode.Open, FileAccess.Read, FileShare.None, 1, true);
    byte[] data = new byte[1024]; // buffer

    return fs.BeginRead(data, 0, data.Length, callback, fs);
}

[/code]

Now, in the EndIndexIAsync action method, we can fetch the results of that operation and return a view based on that:

[code:c#]

public ActionResult EndIndexIAsync(IAsyncResult asyncResult)
{
    // Fetch the result of the lengthy operation
    FileStream fs = asyncResult.AsyncState as FileStream;
    int bytesRead = fs.EndRead(asyncResult);
    fs.Close();

    // ... do something with the file contents ...

    // Return the view
    ViewData["Message"] = "Welcome to ASP.NET MVC!";
    ViewData["MethodDescription"] = "This page has been rendered using an asynchronous action method (IAsyncResult pattern).";
    return View("Index");
}

[/code]

Note that standard model binding takes place for the normal parameters of the BeginIndexIAsync method. Only filter attributes placed on the BeginIndexIAsync method are honored: placing these on the EndIndexIAsync method is of no use.

The event pattern

The event pattern is a different beast. It also consists of two methods that should be added to your controller:

[code:c#]

public void IndexEvent() { }
public ActionResult IndexEventCompleted() { }

[/code]

Let’s implement these and have a look at the details. Here’s the IndexEvent method:

[code:c#]

public void IndexEvent() {
    // Eventually pass parameters to the IndexEventCompleted action method
    // ... AsyncManager.Parameters["contact"] = new Contact();

    // Add an asynchronous operation
    AsyncManager.OutstandingOperations.Increment();
    ThreadPool.QueueUserWorkItem(o =>
    {
        Thread.Sleep(2000);
        AsyncManager.OutstandingOperations.Decrement();
    }, null);
}

[/code]

We’ve just seen how you can pass a parameter to the IndexEventCompleted action method. The next thing to do is tell the AsyncManager how many outstanding operations there are. If this count becomes zero, the IndexEventCompleted  action method is called.

Next, we can consume the results just like we could do in a regular, synchronous controller:

[code:c#]

public ActionResult IndexEventCompleted() {
    // Return the view
    ViewData["Message"] = "Welcome to ASP.NET MVC!";
    ViewData["MethodDescription"] = "This page has been rendered using an asynchronous action method (Event pattern).";
    return View("Index");
}

[/code]

I really think this is the easiest-to-implement asynchronous pattern available in the AsyncController.

The delegate pattern

The delegate pattern is the only pattern that requires only one method in the controller. It basically is a simplified version of the IAsyncResult pattern. Here’s a sample action method, no further comments:

[code:c#]

public ActionResult IndexDelegate()
{
    // Perform asynchronous stuff
    AsyncManager.RegisterTask(
        callback => ...,
        asyncResult =>
        {
            ...
        });

    // Return the view
    ViewData["Message"] = "Welcome to ASP.NET MVC!";
    ViewData["MethodDescription"] = "This page has been rendered using an asynchronous action method (Delegate pattern).";
    return View("Index");
}

[/code]

Conclusion

First of all, you can download the sample code I have used here: MvcAsyncControllersExample.zip (64.24 kb)

Next, I think this is really a feature that should be included in the next ASP.NET MVC release. It can really increase the number of simultaneous requests that can be processed by your web application if it requires some longer running I/O code that otherwise would block the ASP.NET worker thread. Development is a little bit more complex due to the nature of multithreading: you’ll have to do locking where needed, work with IAsyncResult or delegates, …

In my opinion, the “event pattern” is the way to go for the ASP.NET MVC team, because it is the most readable. Also, there’s no need to implement IAsyncResult classes for your own long-running methods.

Hope this clarified AsyncControllers a bit. Till next time!

kick it on DotNetKicks.com

Speaking at DevDays 2009, The Hague (and more)

DevDays09, The NetherlandsSome Great news (at least: I think this is great :-)): Kevin Dockx and I will be giving a session on PHP and Silverlight at the Netherlands DevDays09. This event, aimed totally at developers, will take place on May 28 and 29th in The Hague (Den Haag). It’s the first time the DevDays are hosting sessions related to PHP, and it’s also the first time I’ll be speaking at an event of this size.

Our session will cover the basics of Silverlight and show you how you can create rich web applications using the best of 2 worlds: Silverlight and PHP.

dpc09_speakerNext to this event, we’ll be doing this very same session at the Dutch PHP Conference in Amsterdam, which will take place June 11 – June 13th. Yes, we are evil, doing a presentation on Microsoft technologies at a PHP event.

And now that I’m announcing upcoming sessions anyway… I’ll be doing a session on mocking at VISUG (Visual Studio User Group Belgium). Come visit us at May 7th! This session will show you the basics of unit testing without having to rely on external dependencies like databases, WCF services, ... and will show you how you can reproduce behaviour in a unit test that might be otherwide difficult to test.

Oh, and another one: MSDN Belgium is hosting some virtual events. I’ll be doing a session on the ASP.NET MVC framework (in Dutch) on April 23 at 14:00. Check the MSDN pages for more info (yet to come). Here’s the abstract of that session:

"Join us for this 90 min session and get a developer-focused overview on ASP.NET MVC (Model-View-Controller), a new approach in building ASP.NET applications. Learn how the new ASP.NET MVC framework differs and can be an alternative to the current ASP.NET Web Forms framework. This session will help you to learn how to take advantage of ASP.NET MVC to build loosely coupled, highly testable, agile applications. You will see how ASP.NET MVC provides you with fine-grained control over both HTML and JavaScript."

Back to the future! Exploring ASP.NET MVC Futures

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

New CodePlex project: MvcSiteMap &ndash; ASP.NET MVC sitemap provider

NavigationIf you have been using the ASP.NET MVC framework, you possibly have been searching for something like the classic ASP.NET sitemap. After you've played with it, you even found it useful! But not really flexible and easy to map to routes and controllers. To tackle that, last year, somewhere in August, I released a proof-of-concept sitemap provider for the ASP.NET MVC framework on my blog.

The blog post on sitemap provider I released back then has received numerous comments, suggestions, code snippets, … Together with Patrice Calve, we’ve released a new version of the sitemap provider on CodePlex: MvcSiteMap.

This time I’ll not dive into implementation details, but provide you with some of the features our sitemap provider erm… provides.

First things first: registering the provider

After downloading (and compiling) MvcSiteMap, you will have to add a reference to the assembly in your project. Also, you will have to register the provider in your Web.config file. Add the following code somewhere in the <system.web> section:

[code:c#]

<siteMap defaultProvider="MvcSiteMap">
    <providers>
        <add name="MvcSiteMap"
             type="MvcSiteMap.Core.MvcSiteMapProvider" 
             siteMapFile="~/Web.Sitemap"
             securityTrimmingEnabled="true"
             cacheDuration="10"/>
    </providers>
</siteMap>

[/code]

We’ve just told ASP.NET to use the MvcSiteMap sitemap provider, read sitemap nodes from the Web.sitemap file, use secrity trimming and cache the nodes for 10 minutes.

Defining sitemap nodes

Defining sitemap nodes is quite easy: add a Web.sitemap file to your project and popukate it with some nodes. Here’s an example:

[code:c#]

<?xml version="1.0" encoding="utf-8" ?>
<siteMap>
  <mvcSiteMapNode title="Home" controller="Home" action="Index" isDynamic="true" dynamicParameters="*">
    <mvcSiteMapNode title="About Us" controller="Home" action="About" />

    <mvcSiteMapNode title="Products" controller="Products">
      <mvcSiteMapNode title="Will be replaced in controller"
                      controller="Products" action="List"
                      isDynamic="true" dynamicParameters="id"
                      key="ProductsListCategory"/>
    </mvcSiteMapNode>
    <mvcSiteMapNode title="Account" controller="Account">
      <mvcSiteMapNode title="Login" controller="Account" action="LogOn" />
      <mvcSiteMapNode title="Account Creation" controller="Account" action="Register" />
      <mvcSiteMapNode title="Change Password" controller="Account" action="ChangePassword" />
      <mvcSiteMapNode title="Logout" controller="Account" action="LogOff" />
    </mvcSiteMapNode>
  </mvcSiteMapNode>
</siteMap>

[/code]

Too much info? Let’s break it down. The sitemap consists of several nodes, defined by using a <mvcSiteMapNode> element. Each node can contain other nodes, as you can see in the above example. A node should also define some attributes: title and controller. Title is used by all sitemap controls of ASP.NET, controller is used to determine the controller to link to. Here’s a list of possible attributes:

Attribute Required? Description
title Yes Title of the node.
controller Yes Controller the node should link to.
action Optional Action method of the specified controller the node should link to.
key Optional A key used to identify the node. Can be specified but is generated by the MvcSiteMap sitemap provider when left blank.
isDynamic Optional Specifies if this is a dynamic node (explained later)
dynamicParameters When isDynamic is set to true. Specifies which parameters are dynamic. Multiple can be specified using a comma (,) as separator.
visibility Optional When visibility is set to InSiteMapPathOnly, the node will not be rendered in the menu.
* Optional Any other parameter will be considered to be an action method parameter.

Regarding the wildcard (*), here’s a sample sitemap node:

[code:c#]

<mvcSiteMapNode title="Contact Maarten" controller="About" action="Contact" who=”Maarten” />

[/code]

This node will map to the URL http://…./About/Contact/Maarten.

Using the sitemap

We can, for example, add breadcrumbs to our master page. Here’s how:

[code:c#]

<asp:SiteMapPath ID="SiteMapPath" runat="server"></asp:SiteMapPath>

[/code]

Looks exactly like ASP.NET Webforms, no?

Dynamic parameters

You got to click it, before you kick it. In the table mentioned above, you may have seen the isDynamic and dynamicParameters attributes. This may sound a bit fuzzy, but it’s actually quite a powerful feature. Consider the following sitemap node:

[code:c#]

<mvcSiteMapNode title="Product details" controller="Product" action="Details" isDynamic=”true” dynamicParameters=”id” />

[/code]

This node will actually be used by the sitemap controls when any URL refering /Products/Details/… is called:

  • http://…./Products/Details/1234
  • http://…./Products/Details/5678
  • http://…./Products/Details/9012

No need for separate sitemap nodes for each of the above URLs! One node is enough to provide your users with a consistent breadcrumb showing their location in your web application.

The MvcSiteMapNode attribute

Who said sitemaps should always be completely defined in XML? Why not use the MvcSiteMapNode attribute we created:

[code:c#]

[MvcSiteMapNode(ParentKey="ProductsListCategory", Title="Product details", IsDynamic=true, DynamicParameters="id")]
public ActionResult Details(string id)
{
    // ...
}

[/code]

We are simply telling the MvcSiteMap sitemap provider to add a child node to the node with key “ProductsListCategory” which should have the title “Product details”. Controller and action are simply determined by the sitemap provider, based on the action method this attribute is declared on. Dynamic parameters also work here, by the way.

Do you have an example?

Yes! Simply navigate to the MvcSiteMap project page on CodePlex and grab the latest source code. The sitemap provider is included as well as an example website demonstrating all features.

kick it on DotNetKicks.com

Sample chapter from ASP.NET MVC 1.0 Quickly

image Here’s a shameless, commercial blogpost… With yesterday’s 1.0 release of the ASP.NET MVC framework, I’m sure the following sample chapter from my book ASP.NET MVC 1.0 Quickly will be of use for people starting ASP.NET MVC development: Your first ASP.NET MVC application.

When downloading and installing the ASP.NET MVC framework SDK, a new project template is installed in Visual Studio. This chapter describes how to use the ASP.NET MVC project template that is installed in Visual Studio. All ASP.NET MVC aspects are touched briefly by creating a new ASP.NET MVC web application based on this Visual Studio template. Besides view, controller, and model, new concepts including ViewData—a means of transferring data between controller and view, routing—the link between a web browser URL and a specific action method inside a controller, and unit testing of a controller are also illustrated here.

In this chapter, you will:

  • Have an overview of all the aspects of an ASP.NET MVC web application
  • Explore the ASP.NET MVC web application project template that is installed in Visual Studio 2008
  • Create a first action method and corresponding view
  • Create a strong-typed view
  • Learn how a controller action method can pass strong-typed ViewData to the view
  • Learn what unit testing is all about, and why it should be used
  • Learn how to create a unit test for an action method by using Visual Studio's unit test generation wizard and modifying the unit test code by hand

Download the free sample chapter here. Or order the full book, here. That’s a better option ;-)

By the way, if you are interested in the book writing process itself, check my previous blog post on that.

kick it on DotNetKicks.com

ASP.NET MVC 1.0 has been released!

ASP.NET MVC 1.0 QuicklyTo keep up with a good tradition (see here and here), I have some great news on ASP.NET MVC: we are at version 1.0! This means production ready, supported, stable, …! Grab the download at Microsoft.com.

I’m expecting an epic blog post by the Gu, but here’s some stuff you may want to have a look at: all my posts on ASP.NET MVC.

Another thing you can do: order my book on ASP.NET MVC :-) We’ve released the print version yesterday, meaning you are now completely set to start developing with ASP.NET MVC.

Edit: Looks like Simone was equally fast :-) And Kris.
Edit: More from MIX: Silverlight 3 SDK Beta 1 is already up! http://tinyurl.com/crfogs

kick it on DotNetKicks.com

CRUD with ASP.NET MVC (screencast)

A new screencast has just been uploaded to the MSDN Belgium Chopsticks page. Don't forget to rate the video!

CRUD with ASP.NET MVC (screencast)

Abstract: "In this video, the new tooling for Visual Studio included in ASP.NET MVC release candidate is demonstrated to create a create, read, update and delete user interface within 15 minutes."

kick it on DotNetKicks.com

Creating an ASP.NET MVC application with Google Gears

Offline web applications… This term really sounds like 2 different things: offline, no network, and web application, online. Maarten, you speak in riddles man! Let me explain the term…

You probably have been working with Gmail or Google Docs. One of the features with those web applications is that they provide an “offline mode”, which allows you to access your e-mail and documents locally, when an Internet connection is not available. When a connection is available, those items are synchronized between your PC and the application server. This offline functionality is built using JavaScript and a Google product called Google Gears.

In this blog post, I will be building a simple notebook application using the ASP.NET MVC framework, and afterwards make it available to be used offline.

What is this Gears-thingy?

According to the Google Gears website: Gears is an open source project that enables more powerful web applications, by adding new features to your web browser:

  • Let web applications interact naturally with your desktop
  • Store data locally in a fully-searchable database
  • Run JavaScript in the background to improve performance

Sounds like a good thing. I always wanted to make a web application that I could use offline, too. After reading the tutorial on Google Gears, I learned some things. Google Gears consists of an offline JavaScript extension framework, installed on your PC, together with a SQLite database. Second, there are some different components built on this client side installation:

  • Factory – An object which enables access to all of the following bullets.
  • Blob – Blob storage, the ability to store anything on the client PC.
  • Database – Yes, a database! Running on the local PC and supporting SQL syntax. Cool!
  • Desktop – Interaction with the client PC’s desktop: you can add a shortcut to your application to the desktop and start menu.
  • Geolocation – Locate the physical position of the client’s PC, based on either GPS, Wifi, GSM or IP address location.
  • HttpRequest – Can be used to simulate AJAX calls to the local client PC.
  • LocalServer – A local web server, which can be used to cache certain pages and make them available offline.
  • Timer – A timer.
  • WorkerPool – A class that can be used to execute asynchronous tasks. Think "threading for JavaScript".

Picking some components to work with…

Choices for Google Gears and ASP.NET MVC Have a look at the list of components for Google Gears I listed… Those are a lot of options! I can make an ASP.NET MVC notebook application, and make things available offline in several manners:

  • Read-only offline access: I can use the LocalServer to simply cache all rendered pages for my notes and display these cached pages locally.
  • Synchronized offline access: I can use the Database component of Google Gears to create a local database containing notes and which I can synchronize with the ASP.NET MVC web application.

Note: Also check the architecture page on Google Gears documentation. It covers some strategies on the latter option.

Choices… But which to choose? Let’s not decide yet and first build the “online only” version of the application.

Building the ASP.NET MVC application

Not too many details, the application is pretty straightforward. It’s a simple ASP.NET MVC web application built on top of a SQL Server database using LINQ to SQL. I’ve used a repository pattern to access this data using a defined interface, so I can easily mock my data context when writing tests (which I will NOT for this blog post, but you know you should).

The data model is easy: ASP.NET membership tables (aspnet_Users) linked to a table Note, containing title, body and timestamp of last change.

On the ASP.NET MVC side, I’ve used this repository pattern and LINQ to SQL generated classes using the Add view… menu a lot (check ScottGu’s post on this to see the magic…). Here’s a screenshot of the application:

image

Feel free to download the source code of the ASP.NET MVC – only application: GearsForMvcDemo - MVC only.zip (4.12 mb)

Next steps: deciding the road to follow and implementing it in the ASP.NET MVC application…

Adding Google Gears support (“go offline”) – Read-only offline access

Refer to the choices I listed: “I can use the LocalServer to simply cache all rendered pages for my notes and display these cached pages locally.” Let’s try this one!

The tutorial on Google Gears’ LocalServer states we need a manifest.json file, containing all info related to which pages should be made available offline. Great, but I don’t really want to maintain this. On top of that, offline access will need different files for each user since every user has different notes and so on. Let’s create some helper logic for that!

Autogenerating the manifest.json class

Let’s add a new Controller: the GearsController. We will generate a list of urls to cache in here and disguise it as a manifest.json file. Here’s the disguise (to be added in your route table):

[code:c#]

routes.MapRoute(
    "GearsManifest",
    "manifest.json",
    new { controller = "Gears", action = "Index" }
);

[/code]

And here’s (a real short snippet of) the controller, automatically adding a lot of URL’s that I want to be accessible offline. Make sure to download the example code (see further in this post) to view the complete GearsController class.

[code:c#]

List<object> urls = new List<object>();

// … add urls …

// Create manifest
return Json(new
{
    betaManifestVersion = 1,
    version = "GearsForMvcDemo_0_1_0",
    entries = urls
});

[/code]

The goodness of ASP.NET MVC! A manifest is built using JSON, and ASP.NET MVC plays along returning that from an object tree.

Going offline…

Next step: going offline! The tutorial I mentioned before contains some example files on how to do this. We need gears_init.js to set up the Google Gears environment. Check! We also need a JavaScript file setting up the local instance, caching data. Some development and… here it is: demo_offline.js.

This demo_offline.js script is built using jQuery and Google Gears code. Let’s step trough a small part, make sure to download the example code (see further in this post) to view the complete file contents.

[code:c#]

// Bootstrapper (page load)
$(function() {
    // Check for Google Gears. If it is not present,
    // remove the "Go offline" link.
    if (!window.google || !google.gears) {
        // Google Gears not present...
        $("#goOffline").hide();
    } else {
        // Initialize Google Gears
        if (google.gears.factory.hasPermission)
            initGears();

        // Offline cache available?
        if (!google.gears.factory.hasPermission || (store != null && !store.currentVersion)) {
            // Wire up Google Gears
            $("#goOffline").click(function(e) {
                // Create store
                initGears();
                createStore();

                // Prevent default behaviour
                e.preventDefault();
            });
        } else {
            // Check if we are online...
            checkOnline(function(isOnline) {
                if (isOnline) {
                    // Refresh data!
                    updateStore();
                } else {
                    // Make sure "Edit" and "Create" are disabled
                    $("a").each(function(index, item) {
                        if ($(item).text() == "Edit" || $(item).text() == "Create New") {
                            $(item).attr('disabled', true);
                            $(item).click(function(e) {
                                e.preventDefault();
                            });
                        }
                    });
                }
            });

            // Provide "Clear cache" function
            $("#goOffline").text("Clear offline cache...").click(function(e) {
                // Remove store
                removeStore();
                window.location.reload();

                // Prevent default behaviour
                e.preventDefault();
            });
        }
    }
});

[/code]

What we are doing here is checking if Google gears has permisison to store data from this site on the local PC. If so, it is initialized. Next, we check if we already have something cached. If not, we wire up some code for the “Go offline” link, which will trigger the creation of a local cache on click. If we already have a cache, let’s do things different…

First, we call a simple method on the GearsController class (abstarcted in the checkOnline JavaScript function), checking if we can reach the server. If so, we assume we are online and ask Google Gears to check for updated contents. We always want the latest notes available! However, if this function says we are offline, we look for al links stating “Edit” or “Create New” on the current page and disable them. Read-only we said, so we are not caching “Edit” pages anyway. This is just cosmetics to make sure users will not see browser errors when clicking “Edit”.

 Going offline!

Conlusion for this approach

This approach is quite easy. It’s actually instructing Google Gears to cache some stuff periodically, backed up by an “is online” checker in the ASP.NET MVC application. This approach does feel cheap… I’m just creating local copies of all my rendered pages, probably consuming too much disk space and probably putting too much load on the server in the update checks.

Want to download and play? Here it is: GearsForMvcDemo - Offline copy.zip (4.11 mb)

Adding Google Gears support (“go offline”) – Synchronized offline access

In the first approach, I concluded that I was consuming too much resources, both on client and server, to check for updates. Not good! Let’s try the second approach: “I can use the Database component of Google Gears to create a local database containing notes and which I can synchronize with the ASP.NET MVC web application.”

What needs to be done:

  • Keep the approach described above: we will still have to download some files to the local client PC. The UI will have to be available. Not that we will have to download all note details pages, but we want the UI to be available locally.
  • Add some more JavaScript: we should be able to access all data using JSON (as an extra alternative to just providing web-based views that the user can work with).
  • The above JavaScript should be extended: we need offline copies of that data, preferably stored in the Google Gears local database.
  • And yet: more JavaScript: a synchronization should occur between the local database and the data on the application server.

Ideally, this should look like the following, having a JavaScript based data layer available:

Google Gears Reference Architecture

Due to a lack of time, I will not be implementing this version currently. But hey, here's a nice blog post that should help you with this option: .NET on Gears: A Tutorial

Conlusion for this approach

The concept of this approach is still easy, but requires you to write a lot of JavaScript. However, due to the fact that you are only synchronizing some basic UI stuff and JSON data, local and server resources are utilized far less than in the first approach I took.

Conclusion

The concept of Google Gears is great! But I seriously think this kind of stuff should be available in EVERY browser, natively, and with the same API across different browsers. Storing data locally may bring more speed to your application, due to more advanced caching of UI elements as well as data. The fact that it also enables you to access your application offline makes it ideal for building web applications where connectivity is not always guaranteed. Think mobile workers, sales people, ..., all traveling with a local web application. Not to forget: Gears is currently also available for Windows Mobile 5 and 6, which means that ultra-mobile people can run your web application offline on their handheld device! No need for specific software for them!

By the way, also check this: .NET on Gears: A Tutorial. Interested in Silverlight on Gears? It has been done!

kick it on DotNetKicks.com

Announcing my book: ASP.NET MVC 1.0 Quickly

ASP.NET MVC 1.0 Quickly It’s been quite a job, but there it is: Packt just announced my very first book on their site. It is titled “ASP.NET MVC 1.0 Quickly”, covering all aspects ASP.NET MVC offers in a to-the-point manner with hands-on examples. The book walks through the main concepts of the MVC framework to help existing ASP.NET developers to move on to a higher level. It includes clear instructions and lots of code examples. It takes a simple approach, thereby allowing you to work with all facets of web application development. Some keywords: Model-view-controller, ASP.NET MVC architecture and components, unit testing, mocking, AJAX using MS Ajax and jQuery, reference application and resources.

That’s it for the marketing part: let’s do a retrospective on the writing process itself. Oh and yes, those are my glasses on the cover. Photo was taken on the beach near Bray-Dunes (France).

When did you have the idea of writing a book?

I'm not sure about that. I've been blogging a lot on ASP.NET MVC last year, wrote an article for .NET magazine, did some presentations, ... It occurred to me that I had a lot of material which I could bundle. Together with that, my project manager jokingly said something like: "When will you write your first book? With all that blogging." So I did start bundling stories. First of all, I overlooked the whole ASP.NET MVC technology (preview 2 at that moment) and decided there were enough topics to talk about. A draft table of contents was built quite quick, but I gave up on writing. Too much information, not enough time, ...

A few weeks later, it must have been around the beginning of May, 2008, I did start writing a first chapter, thinking I'ld see how the writing itself would turn out, if it fit in my schedule, ... It worked out quite well, each 10-20 days gave me a new chapter. I also started looking for a publisher when I was finished with chapter 6 or so. Having reviewed some books for Packt, I contacted them with a proposal for my book.

After having a look at the other 6 upcoming books (here and here), we decided we could go for it, focusing on a hands-on book which rapidly guides you into the wonderful world of ASP.NET MVC.

How was your experience of writing your book?

Looking back, it was an interesting experience. I decided to write in English, which is not my native language. That was actually quite a hard one: writing in English is no problem, but writing a good, solid and interesting piece of text is just not that easy when writing longer texts than the average blog post. Another thing is that I tortured myself writing about a product that was not even beta yet! I started writing with ASP.NET MVC preview 3, updated it all to preview 4, 5, beta, release candidate, ... Lots of changes in the ASP.NET MVC API or concepts meant lots of changes to make in chapters I already wrote. Luckily, I survived :-)

I only contacted a publisher when I had finished 60% of my book. If you are considering writing: don't do this! Contact a publisher at a very early stage: they normally give you lots of advice upfront, which I only received after contacting them. Advice earlier along the way is always better, so that's something I would definately do different.

Speaking of advice: when writing was done, the book entered review phase. Different people received the draft version and could provide comments and suggestions. Thanks Stefan, Troy, Vivek, Jerry, Joydip and people at Packt for your time in reviewing my draft version! Reviewer comments really made the book better and required me to do some small rewrites, elaborate more on certain topics.

What tools did you use for writing?

There are some tools that you really need when writing a technical book. One of them is a text editor, in my case Microsoft Word 2007. Together with that, Visual Studio 2008 and regularly updated ASP.NET MVC versions were required. Being scared of losing data, I decided to also use a source control system for sample code ánd for my Word documents. All of these files were stored in a Subversion repository located on my server, being backed up every day to different locations. Doug Mahugh laughed at me when I said I was using Subversion, but it did a great job!

Other tools I used were Paint.NET and MwSnap, both for creating screenshots in my virtual PC running Windows Vista and Visual Studio 2008. I also used Achievo for time tracking purposes, since I was curious how much time this book writing would actually cost me.

How much time did you spend writing?

First of all, this is not going to be 100% accurate. I did track writing and development time during writing, but I already had a lot of material to work with. But here's an overview (numbers in hours):

image

That is right: writing a book consumes only a little more than 100 hours! But still, I already had lots of material. I'd say to double the number for an accurate timeframe.

Now I hear the next question coming... Here's the answer already: Yes, I have a girlfriend. We are working on our home (planning phase is done, searching a contractor at the moment), visiting family, doing daily stuff, blogging, work, ... It al worked out to fit together, but still: there have been some busy moments on evenings and weekends. Thanks, people around me, for being patient and caring during these busy moments!

Are you getting rich out of this?

Of course, I can grab a couple of beers (for a couple of times), but don't think writing a book will buy you a car... I just felt that I had lots of valuable information that I had to share, and writing a book seemed like the best option to do that. Creating a "to read"-list? Make sure to add ASP.NET MVC 1.0 Quickly to it.

kick it on DotNetKicks.com

Form validation with ASP.NET MVC release candidate

Last week, the ASP.NET MVC framework release candidate was released (check ScottGu’s post). Apart from some great new tooling support, form validation has never been easier. Here’s a quick introduction.

Employee from Northwind database Imagine we have a LINQ to SQL data model, containing an Employee from the Northwind database. As you may know, LINQ to SQL will generate this Employee class as a partial class, which we can use to extend this domain object’s behaviour. Let’s extend this class with an interface implementation for IDataErrorInfo.

[code:c#]

public partial class Employee : IDataErrorInfo
{
    #region IDataErrorInfo Members

    public string Error
    {
        get { throw new NotImplementedException(); }
    }

    public string this[string columnName]
    {
        get { throw new NotImplementedException(); }
    }

    #endregion
}

[/code]

IDataErrorInfo is an interface definition that is found in System.ComponentModel. It provides the functionality to offer custom error information that a user interface can bind to. Great, let’s do that! Assume we have a view which is used to edit this Employee object. The code for this will be quite easy: some HTML form stuff, Html.ValidationMessage calls, … Here’s a snippet:

[code:c#]

<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">

    <h2>Edit</h2>

    <%= Html.ValidationSummary() %>

    <% using (Html.BeginForm()) {%>
        <%= Html.Hidden("id", Model.EmployeeID) %>

        <fieldset>
            <legend>Fields</legend>
            <p>
                <label for="LastName">LastName:</label>
                <%= Html.TextBox("LastName") %>
                <%= Html.ValidationMessage("LastName", "*") %>
            </p>

            <!-- ... -->

        <fieldset>
    <% } %>

</asp:Content>

[/code]

The controller’s action method for this will look like the following:

[code:c#]

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Edit(int id, FormCollection collection)

    Employee employee = repository.RetrieveById(id);

    try
    {
        UpdateModel(employee, collection.ToValueProvider());
        repository.Save(employee);

        return RedirectToAction("Index");
    }
    catch
    {
        return View(employee);
    }
}

[/code]

Nothing fancy here: a call to UpdateModel (to populate the Employee instance with data fom the form) and a try-catch construction. How will this thing know what’s wrong? This is where the IDataErrorInfo interface comes useful. ASP.NET MVC’s UpdateModel method will look for this interface implementation and retrieve information from it. The Error property that is defined on IDataErrorInfo returns a string containing any error that is “global” for the Employee object. The this[string columnName] indexer that is defined on IDataErrorInfo is used to retrieve error messages for a specific property. Now let’s make sure FirstName and LastName are provided:

[code:c#]

public partial class Employee : IDataErrorInfo
{
    #region IDataErrorInfo Members

    public string Error
    {
        get { return ""; }
    }

    public string this[string columnName]
    {
        get
        {
            switch (columnName.ToUpperInvariant())
            {
                case "FIRSTNAME":
                    if (string.IsNullOrEmpty(FirstName))
                        return "Please provide a firstname.";
                    break;
                case "LASTNAME":
                    if (string.IsNullOrEmpty(LastName))
                        return "Please provide a lastname.";
                    break;
            }

            return "";
        }
    }

    #endregion
}

[/code]

Great, let’s try it out. If I omit the firstname or lastname when editing an Employee object, here’s what the view looks like:

ASP.NET MVC form validation

How easy was that! More on the new things in the ASP.NET MVC release candidate can be found in ScottGu’s blog post.

kick it on DotNetKicks.com