Monday, 26 December 2011

Asynchronous MVC controllers end to end example

=== PREAMBLE ===

My intended audience:

1) You are a programmer or articial being understanding code (probably the former)
2) You work with ASP.NET MVC
3) You must take in use asynchronous processing to handle a slow and time consuming
MVC action and want to learn how to implement an AsyncController.


If this is the case, please read on!

== PREAMBLE ===


I guess many of you know how to create an ordinary MVC controller inheriting from System.Web.Mvc.Controller class, but what about creating an Asynchronous MVC controller?

It is possible to opt-in asynchronous controllers in MVC out of the box of the MVC framework. This will be a code sample of how this is possible. The goal of the asynchronous controller will be to provide better scalability, especially for complex calculations that take long which are accessed by many simultaneous users. Beware though, the standard synchronous design is easier to relate to and will be suitable in many standard scenarios. Asynchronous controllers should only be applied where there is a good reason to expect bottlenecks to be present in the code and in a real production environment.

Moving on to the asynchronous controller. Instead of inheriting from the controller class, inherit from the System.Web.Mvc.AsyncController class in MVC. The following code shows how to create an asynchronous controller.

Code sample follows:



using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Threading;

namespace SubstitutePartInCompositionContainer.Controllers
{
public class TestAsyncController : AsyncController
{


[AsyncTimeout(60000)]
public ActionResult IndexAsync()
{
AsyncManager.OutstandingOperations.Increment();
ThreadPool.QueueUserWorkItem((s) =>
{
ServiceReference1.NewsServiceClient client =
new ServiceReference1.NewsServiceClient();

TempData["news"] = client.GetSomeNews("Steinkjer");
AsyncManager.OutstandingOperations.Decrement();
}, null);

return View();
}

public ActionResult IndexCompleted()
{
ViewBag.DateStamp = DateTime.Now;
ViewBag.News = TempData["news"] as string;
return View();
}

}
}



The class in this example is called TestAsyncController. It inherits from the AsyncController class. The class contains two action methods which is called IndexAsync and IndexCompleted. In general, for every asynchronoous MVC action, there must be two method suffixed with Async and Completed, just like every controller must be suffixed with Controller (part of the design by contract conventions in MVC).

I put the attribute [AsyncTimeout(60000)] here, it is possible to specify in milliseconds how long an async timeout should be allowed to execute before timing out. It is also possible to use the attribute [NoAsynctimeout] instead.

Further on, I use the static method ThreadPool.QueueUserWorkItem to add an asynchronous call in the current Thread Pool. I use the AsyncManager.OutstandingOperations.Increment() and corresponding Decrement() methods to keep track of the pending asynchronous calls. AsyncManager is part of System.Web.Mvc.Async namespace. This book keeping is required for correctly arriving at the Complete method that will receive the asynchronous result. For convenience, I move the result to the TempData dictionary. This will be available for me in the Complete method in my controller. Since the data I get is a string, I just copy it to the ViewBag (dynamic object) and this is then just displayed in the MVC view Index.cshtml in the folder TestAsync.

Here is the service contract for the NewsService used (WCF service):


using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;

namespace TestServices
{

[ServiceContract]
public interface INewsService
{

[OperationContract(AsyncPattern=true)]
IAsyncResult BeginGetSomeNews(string city, AsyncCallback callback,
object asyncState);

string EndGetSomeNews(IAsyncResult result);

}

}



As you can see, the WCF service tags the operation BeginGetSomeNews with the AsyncPattern equals set to true to allow asynchronous execution. Not only will the IIS service not receive a blocking call, the service itself is also run asynchronous in this case. The WCF service also got a pair of methods this time prefixed with Begin and End. Only the Begin method is attributed with [AsyncPattern=true], the end method is not even attributed with OperationItem attribute without any overloads. This is because the end method is just a callback for the Begin method. As in asynchronous programming, the Begin method starts by receiving its parameters, followed by AsyncCallback callback, object asyncState paramteters. The End method returns string in this case and also receives such an object.

The service implementation looks like this:



using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;
using System.Threading;

namespace TestServices
{

public class NewsService : INewsService
{

public IAsyncResult BeginGetSomeNews(string city, AsyncCallback callback,
object asyncState)
{
Thread.Sleep(3000); //simulate some sleep
return new
CompletedAsyncResult("Here are some news for " + city);
}

public string EndGetSomeNews(IAsyncResult result)
{
var resultFromAsync = result as CompletedAsyncResult;
return resultFromAsync.Data;
}

}

}



I use a class called CompletedAsyncResult, this looks like this (MSDN is the source):

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;

namespace TestServices
{

public class CompletedAsyncResult : IAsyncResult
{
T data;

public CompletedAsyncResult(T data)
{ this.data = data; }

public T Data
{ get { return data; } }

#region IAsyncResult Members
public object AsyncState
{ get { return (object)data; } }

public WaitHandle AsyncWaitHandle
{ get { throw new Exception("The method or operation is not implemented."); } }

public bool CompletedSynchronously
{ get { return true; } }

public bool IsCompleted
{ get { return true; } }
#endregion
}
}


Then, I just added a Service Reference to the WCF class library containing my service to generate a proxy or service agent to access my WCF service in my controller, as seen in the first code.

Important GOTCHAS about asynchronous MVC controllers:


  • There is no explicit call between the Async and Completed method in the MVC controller inheriting from AsyncController. This is code by design or contract.

  • We must "help" MVC keep track of the outstandingoperations for the AsyncManager in our code. When the counter turns to zero again, the async operation decrementing the value last will call its Complete method.. Use AsyncManager throughout.

  • Google blogger does not handle generic arguments well, but the CompletedAsyncResult object takes string as a generic type argument in my demo code here. It could be a complex type such as a data contract.

  • There are many more methods of achieving this, this is just one example.

Saturday, 17 September 2011

Simple access of embedded resources in DLLs in MVC views

I was working with embedded views in a DLL in a MVC Razor 3 project today and I had to be able to refer to embedded Javascript .js files, images (jpg and png) and css files in the precompiled views. To make this work I tagged the files as Embedded Resource in my project, compiled the project into a dll and in the other mvc project which used the dll I could get it to fetch the embedded resources easily adding a new MVC controller action.

The mvc controller action looks like this:

The code below goes into the Home controller, ContentFile action method, which
returns a FileStreamResult below.



public FileStreamResult ContentFile(string id)
{
string resourceName = Assembly.GetExecutingAssembly().GetManifestResourceNames().ToList().FirstOrDefault(f => f.EndsWith(id));
return new FileStreamResult(Assembly.GetExecutingAssembly().GetManifestResourceStream(resourceName), GetMIMEType(id));
}

private string GetMIMEType(string fileId)
{
if (fileId.EndsWith(".js"))
{
return "text/javascript";
}
else if (fileId.EndsWith(".css"))
{
return "text/stylesheet";
}
else if (fileId.EndsWith(".jpg"))
{
return "image/jpeg";
}
return "text";
}


To use this in the views, write this:



<script type="text/javascript" src="/Home/ContentFile/test.js">
</script>

<link rel="Stylesheet" href="/Home/ContentFile/blue.css">

<img src="/Home/ContentFile/forest.jpg" />



To load up an embedded resource we look into the executing dll, which instead should perhaps load a specified assembly if necessary, and then GetManifestResourceStream and retrieving the matching resource name passed in. The MIME type must be set and is resolved by looking at the resource name passed in.

So the morale is that if you want to load a content file from a DLL in a MVC view, use a controller action and return a FileStreamResult and then load up the content file by writing the route to the ContentFile action.

Monday, 12 September 2011

Testing out the WatiN unit testing

WatiN, or "Web application testing in .Net", is based on a similar package for Ruby on Rails called WatiR. This is a browser automation package that gives the ability to run say a MsTest where you open up an url in Internet Explorer 6,7,8 or 9 or Firefox 2 or 3, then locate a gui element in a web page by its id and write in some text, if it is textbox and click a button. This is making it possible easily write GUI tests for web applications running in an IE or FireFox environment, covering most users. WatiN also gives logging options and makes it possible to create screenshots and so on.

Lets start with a equivalent "Hello world" unit test using WatiN.

First off, create a new Mvc 3 Web Application, select Internet Application as the template, choose to add a unit test. Check that you got Nuget insstalled.

Then write in the Nuget console:


Install-Package WatiN


This will download the necessary DLL files to the unit test project and add to its references. These DLL files are:



  • Interop.SHDocVw - Mark in the references this DLL and choose Embed Interop Types to false.


  • WatiN.Core


  • WatinUnitTest



Now add a unit test or basic unit test and then write the following test method
inside your test class:



[TestMethod]
public void TestLogInToMrs()
{
string targetServer = "http://mrx.hex.no";
using (var browser = new IE(targetServer))
{

LogintoCerebralParese(targetServer, browser);
}
}

private static void LogintoCerebralParese(string targetServer, IE browser)
{
browser.ShowWindow(WatiN.Core.Native.Windows.NativeMethods.WindowShowStyle.ShowMaximized);
browser.Link(l => l.Url == targetServer + "/CerebralPareseRegister").Click();
browser.TextField(t => t.Name == "ctl00$ContentPlaceHolderMain$RoleComboBox").SetAttributeValue("readonly", "");
browser.TextField(t => t.Name == "ctl00$ContentPlaceHolderMain$RoleComboBox").TypeText("Registeransvarlig");
browser.Button("ContentPlaceHolderMain_LoginButton").Click();
}



In this example, an instance of an IE object is instantiated inside the using block. The url specified in the constructor argument is requested. Then the unit test
maximizes the window, then it will search on the login page for a Link object (basically searching for the A tags) by url matching CerebralPareseRegister.
It will then look for a TextField, again using a lambda overload (Linq is supported in WatIN, which is written in C#), overriding its readonly html property using the SetAttributeValue method and setting readonly to empty string, unlocking the readonly textbox. Then it writes in "Registeransvarlig" (a role in my test scenario) in the textfield, using the TypeText method with the argument passed into the text box. The last line looks for a button, i.e. an input tag element with id equal to the passed in argument and invokes the click method which will click the button.

The test then will check that it is possible to login to this registry. Without giving out to much details to our global audience, we got web registries which there will be about 50 registries later and this single test will test logging into a single registry (CerebralPareseRegistry). We would then probably test all 50 registries and verify that we can log in to the different registries. The Internet Explorer browser is not thread safe and therefore there is a risk that unit tests running in parallel will crash the IE browser. The good thing then, is that when using the IE browser in these parallel tests, they will run in STA (Single thread apartment) and therefore it will avoid the possible crash. An optimization is in the TestInitialize method use the same IE object and then dispose it in the TestComplete method. Instead, use a single IE object per test to keep thread safety. This will increase the test time. The good thing is that these automated web gui tests can be run in automatic mode and for example runned every night in the nightly build. The WatiN framework makes it therefore possible to do full integration unit tests using browser automation so that you can verify that the web application is working for the end user for its core functionality, such as log in to a web application, perform a search and so on.

The WatiN tests should be testing the core end-user functionality. The different parts of your web application, for example a MVC 3 application, should also have unit tests of their own.

As I have suggested in previous posts, the MvcContrib TestHelper should be used when testing Controllers and their actions in MVC 3. Unit tests in javascript can use the helper class of Stephen Walther. The views can also use the Razor Single File Generator to tests their views. Finally testing the DAL layer Entity Framework supports testing POCO objects using the Seed function if you use Entity Framework Objects.

WatiN supports a multitude of functionality and this blogpost just wanted to mention it.

Check out the http://watin.org website to see the documentation of WatiN and download the package, if you do not want to use Nuget. WatiN is open source and therefore fully customizable.