http://www.developer.com/

Back to article

Localizing, unit testing and using AJAX in ASP.NET MVC applications


May 26, 2009

Introduction

Many web developers using ASP.NET's traditional WebForms technology have shown keen interest to Microsoft's new, open-sourced ASP.NET extension, and for a good reason. This new extension is called ASP.NET MVC. From a software design perspective, the idea of separating your user interface (the views), operation logic (the controllers) and the data (the models) has many benefits.

For one thing, this separation, although it requires a little bit more work than usual, helps in keeping your applications maintainable. Another great benefit is the ability to better run unit tests against your code. The framework (and its Visual Studio integration package) helps you create unit test skeletons for example from controller methods; your task is to write the actual testing code. Since ASP.NET MVC 1.0 is only three months old, time is still required to create an industry-wide set of best practices. However, certain requirements will not change no matter whether you use traditional WebForms technologies or ASP.NET MVC: you need to test, localize and fine tune your user interfaces. In this article, you will learn about different possibilities to unit test your ASP.NET MVC applications, how to localize them to multiple languages, and finally, how to add an AJAX touch to your user interfaces - which are implemented using views in MVC projects.

Getting started with localization

Creating web application user interfaces in multiple languages is not a new problem. In fact, ASP.NET has had built-in support for localization from the earliest versions. For instance, you might have user local or global resources, and referenced them in your controls and/or .aspx files using the <%$ %> constructs. Since the views in ASP.NET MVC applications are often regular .aspx files, you can use the exactly same methods in your MVC applications (Figure 1).



Click here for larger image

Figure 1. The default look and feel of an ASP.NET MVC application.

In addition to this traditional method of localization, you can also add this logic to your controller classes. Because using the <%$ %> constructs is a working, but somewhat tedious method, you can use the controllers to return altogether different views from the controller based on the currently active language. This can be useful especially if the different language versions of the views do not need to be exactly similar. For instance, you might have an English version of your view that is more extensive than, say, the French version.

Let's see both of the options in action. Assume that you have started a plain ASP.NET MVC application, and haven't done any customizations yet. The default application skeleton Visual Studio creates for you contains the Home and Account controllers. For instance, if you needed to localize the Home/About text, you could do as follows.

First, you could use the traditional method of localization: using resources. For instance, to begin using global resources, you would add the App_GlobalResources folder to your solution. You can do this by right-clicking your project's node in Visual Studio's Solution Explorer, and choosing the Add/Add ASP.NET Folder/App_GlobalResources command. This will create the required folder for you.

The next step is to add the resource files. Again, in Solution Explorer, right-click the newly created folder, and choose the Add/New Item command from the popup menu. This will open the familiar Add New Item Dialog box, from which you should choose the Resources File icon. After you give a name to the resource file and click OK, Visual Studio will add it to your project. You can then start typing your resource strings into the displayed grid (Figure 2). When using resources, you need to have an identifier for each string you want to localize in your application.



Click here for larger image

Figure 2. Localization using resource strings works in ASP.NET MVC applications, too.

It's a good idea to give some thought to these identifiers before you start localizing your application, as you will need these identifiers when you refer to the strings in your view pages. Remember also, that while many strings are unique to each page, there probably are many strings that you can use on more than one view. You might want to reflect this fact on the identifier names. Referring to the localized strings is easy: you can use the <%$ Resources %> construct introduced in ASP.NET 2.0. For instance, if you had a resource identifier named HelloWorldText in a resource file called MyResources.resx, then the following code in the .aspx file would be converted to the correctly localized string depending on the user's preferred language:

  <asp:Literal ID="Literal1" runat="server"
  Text="<%$ Resources: MyResources, HelloWorldText %>" />

For ASP.NET MVC to find the correct localized version, the framework uses a special file naming convention. The resource file MyResources.resx contains the strings in a language that is considered the base language of the application. If the user's browser doesn't specify a language, or you don't specify one in code, then the strings from this base file are used. But if the user's chosen language is for instance German, then the language acronym "de" is appended to the resource file name: MyResources.de.resx. The same is repeated for other languages, for instance the file MyResources.es.resx would contain the Spanish strings.

For localization to work, you might also wish to add a special directive to the .aspx file's @Page tag. For instance, to allow automatic detection of user's browser language preference, add the UICulture="auto" attribute to the tag (the identifier after the colon specifies the default language):

  <%@ Page ... UICulture="auto:en-US" %>

The other option to localizing simple views is the possibility to return different views based on the user's language. This requires some logic in the controller, but the code is easy to write. For instance, you could use logic like this:

  public ActionResult Localized()
  {
    if (Request.UserLanguages.Length > 0)
    {
      string lang = Request.UserLanguages[0];
      if (lang.ToUpper().StartsWith("DE"))
      {
        return View("Localized-DE");
      }
      else return View("Localized-EN");
    }
    else return View("Localized-EN");
  } 

Remember that you could also encapsulate this code into a (utility) method. Should you require a combination of these two main options, it's good to know that you can freely mix and match. As this is the case, localizing your ASP.NET MVC applications shouldn't be limited by the available technology.

Unit testing MVC applications

One of the great benefits of ASP.NET MVC applications is the ability to better test your code with unit tests. Although it is possible to test regular ASP.NET WebForms applications, this is often considerably more difficult as the application model leads you into mixing user interfaces, data access and logic into same code files and classes. On the other hand, ASP.NET MVC application structure helps creating more natural boundaries for unit tests.

Often, controller classes are the best place to start testing. Since the controller methods do not require any user interface and thus no interactive use to function, they are good candidates for tests. When you start an ASP.NET MVC project, Visual Studio asks whether you want to add a unit testing project to your solution. If you added one, then your solution should look like the one in Figure 3.



Click here for larger image

Figure 3. The default solution structure of an ASP.NET MVC application.

The default template suggests creating one unit test for each controller method, but there is no limit to the number of tests you can write. If you have at least Visual Studio 2008 Professional, then you can use the Test/Run/All Tests in Solution menu command to run all available tests in your solution (Figure 4).



Click here for larger image

Figure 4. Unit test results in Visual Studio.

Writing your tests for ASP.NET MVC applications is similar to writing them for other .NET application types. You can use the Assert class (defined in the Microsoft.VisualStudio.TestTools.UnitTesting namespace) to let Visual Studio know about the results of your tests. For instance, your test might check whether the controller method Customers returns correct data in the ViewData object:

  [TestMethod]
  public void Customers()
  {
    HomeController controller = new HomeController();
    ViewResult result = controller.Customers()
      as ViewResult;
  
    ViewDataDictionary viewData = result.ViewData;
    string tableName = "Customers";
    Assert.AreEqual(tableName, viewData["tableName"]);
  }

When your tests are fast in their execution, running even hundreds of tests goes swiftly. However, since many ASP.NET MVC applications use SQL databases, testing those access routines can take time. Of course, you should test your data access classes (perhaps the models) as well, but often it's more convenient to simulate database access in testing routines with in-memory static data.

One option to implement this is to create a data access interface, which is then implemented by a one class doing the real database access, and another only simulating such access. This simulating class would return static data from memory instead of accessing a real database. With these two implementations, you could use the real one in your application, and the simulating one in your unit tests. For controller tests, this kind of simulated data access is usually enough, and additionally much faster to test.

In fact, such simulating classes are often called mock objects. Mock objects can be used in place of real objects, and thus help in writing your unit tests. Database access is one place where such mock objects are useful, but there are other situations as well. For database access, it is often useful to write your own mock objects, but for other testing tasks, such as those requiring authentication, you might want to use ready-made mock object libraries.

There are several libraries available for .NET, three quite common ones being EasyMock.NET, Moq and Rhino Mocks. All these are open-source solutions, and can be found from the web addresses shown in the Links section. Using mocks depends on the library, but commonly they require you to initialize the framework, after which you can use the mock objects to substitute the real ones.

For instance, if your views are protected so that only authorized users can access them (specified using the Authorize attribute in the controller), then your unit tests might need to construct the proper authentication objects to make the tests succeed. Specifically, this would mean the User and Identity objects. Here is an example of using the Moq library to set up a mock object to help testing views that require authentication:

  using Moq;
  using System.Web;
  using System.Security.Principal;
  ...
  HomeController controller = new HomeController();
  
  var context = new Mock<ControllerContext>();
  var user = new Mock<IPrincipal>();
  var identity = new Mock<IIdentity>();
  context.Setup(
      ctx => ctx.HttpContext.User).Returns(
          user.Object);
  user.Setup(ctx => ctx.Identity).Returns(
      identity.Object);
  identity.Setup(
      id => id.IsAuthenticated).Returns(true);
  identity.Setup(
      id => id.Name).Returns("John Doe");
  
  controller.ControllerContext = context.Object; 

The Moq library relies heavily on C# lambda expressions, giving a modern touch to your unit tests. The framework is also quite simple to learn, provided that you already are at least somewhat familiar with the said lambda expressions.

Note that if you download a testing framework as only binary files, you might run into security issues. This can happen if you simply copy the DLL file(s) into your solution folder and then try to use the framework using a reference. In such a situation, you might notice that Visual Studio reports "Not Executed" while running your tests. If the error details say something like, "Test Run deployment issue: The location of the file or directory 'library.dll' is not trusted", then it is a security issue.

The easiest way to solve this is to go to the DLL file's properties window in Windows Explorer (Alt + double click), and then click the Unblock button. The other option is to add full trust to the assembly with the CasPol utility.

Adding an AJAX touch to your application

Although using the latest XHTML and CSS features can get you far, using some JavaScript on the browser can bring richness to your web application. Luckily, AJAX scripts enjoy a built-in support on ASP.NET MVC, and thus more versatile user interfaces are easy to get started with.

The first thing in adding AJAX support to your ASP.NET MVC applications is to reference the proper scripts in your view pages. When you create the default ASP.NET MVC project in Visual Studio, the template creates a Scripts folder for you, with all the necessary JavaScript files already copied to the correct place. In Visual Studio's Solution Explorer, you should see several script files in this folder (Figure 5).



Click here for larger image

Figure 5. AJAX support is baked into ASP.NET MVC applications.

Although you can add custom scripts to this folder, the ones that ship with the ASP.NET MVC installation provide a convenient starting point. To get started with them, you need to reference them in your .aspx files like this:

    <script src="/Scripts/MicrosoftAjax.js"
      type="text/javascript"></script>
    <script src="/Scripts/MicrosoftMvcAjax.js"
      type="text/javascript"></script> 
  

Note how the Scripts folder contains the debug versions of these libraries. The difference is basically in the commenting, formatting and spacing of the code. Tighter spacing leads to smaller files sizes, and thus faster application loading.

With the references in place, you can use the built-in Ajax helper object to create action links that point to your controller actions, and then return data back. You can then update the user interface with this data:

  <div id="hello-world-element"></div>
<%= Ajax.ActionLink("Show Ajax Message",
  "AjaxMessage", new { Name = "TestUser" },
  new AjaxOptions {
      UpdateTargetId = "hello-world-element"
  })%> 

This code would generate a script-based link that contacts the AjaxMessage action in the Home controller. In AJAX implementations, you don't need to write any special code in the controllers: regular code that returns for instance HTML code snippets will do just fine. However, should you want to return for example objects to be manipulated with JavaScript, you could return them in JSON encoded format. ASP.NET MVC makes it easy to return such objects with the JSON helper method, accessible from the controller classes. Here is an example of such action method implementation:

  public JsonResult JsonTest()
  {
    var quickObject = new
    {
      Name = "John Doe",
      Age = 37,
      City = "Salt Lake City"
    };
    return Json(quickObject);
  }

To help writing your JavaScript code in the view pages, you can also utilize the popular jQuery library. jQuery is an open-source library (like the mock object libraries), and can be directly used from your ASP.NET MVC applications. In fact, version 1.3.2 of jQuery ships with ASP.NET MVC, and can be referenced simply by pointing to the correct .js file:

  <script type="text/javascript" src="/Scripts/jquery-1.3.2.js"></script> 

Again, after adding this reference, you can start using the library. For example, if you wanted to add some animation to your labels, you could call the fadeOut method that jQuery supports. This method takes in a timeout value in milliseconds, and then changes an HTML element's (such as one defined with the DIV tag) appearance. Here is an example:

  <script type="text/javascript">
    function FadeTextOut() {
        $("#my-id").fadeOut(1500, null);
    }
  </script>  

<a href="#" onclick="javascript:FadeTextOut();">Click me</a>
<p>
<div id="my-id" style="font-size: x-large;">Hello, World!</div>
</p>

If you are not yet familiar with jQuery, then the tutorials available at jQuery's official web site (see again the Links section) or here on Developer.com are great places to start. jQuery fans have also created nice little cheat sheets to help tackling the short function names. You might wish to grab one of these and then start exploring.

Conclusion

In this article, you learned about three different, but very common requirements for almost any ASP.NET MVC application: localization, unit testing and AJAX support. While other articles have been written about these topics before in the context of regular ASP.NET WebForms applications, ASP.NET MVC requires you to update your techniques.

For instance, localization can be done in multiple ways in ASP.NET MVC applications: just as you use resource strings, you could just as efficiently return a different view for each language. Similarly, as ASP.NET MVC applications tend not to use ScriptManager components, you need to change your tactics when writing AJAX applications.

In the end, ASP.NET MVC is a great addition to the selection of available web techniques on the Microsoft .NET platform. Although ASP.NET MVC might not be the optimal solution for every web application you build, having good skills in ASP.NET MVC will get you far.

Good luck with your development work!

Links

ASP.NET MVC 1.0 download page:
ASP.NET MVC Source Code download page:
EasyMock.NET:
Moq mock library:
Rhino Mocks:
jQuery start page:

About the Author

Jani Järvinen is a software development trainer and consultant in Finland. He is a Microsoft C# MVP and a frequent author and has published three books about software development. He is the group leader of a Finnish software development expert group at ITpro.fi. His blog can be found at http://www .saunalahti.fi/janij/. You can send him mail by clicking on his name at the top of the article.

Sitemap | Contact Us

Thanks for your registration, follow us on our social networks to keep up-to-date