Using AutoMapper for More JSON Serialization Flexibility

In my last post, I replaced the default MVC JavascriptSerializer with the JSON.NET JsonSerializer and mentioned how using JsonIgnore attribute can help resolve circular reference error during JSON serialization. That was good to some extent, but it may not be ideal or enough for all the cases in your application. In this post, I want to show an example of how using JsonIgnore does not work and how using AutoMapper can help.

Imagine I have two models, Order and OrderLineItem, and I have set them up to persist by using an ORM, in this case EF Code-First. I’m not going to go into how that works because that’s not important for the purpose of this post. You could also use NHibernate instead because they both provide bi-directional association.

public class Order
{
    public virtual int Id { get; set; }
    public virtual DateTime CreatedDate { get; set; }

    public virtual ICollection<OrderLineItem> LineItems { get; set; }
}

public class OrderLineItem
{
    public virtual int Id { get; set; }
    public virtual int OrderId { get; set; }

    [JsonIgnore]
    public virtual Order Order { get; set; }
}

There’s a one-to-many relationship between Order and OrderLineItem. And notice there’s a JsonIgnore attribute applied to the Order property in OrderLineItem to avoid the JSON serialization error.

Here is the OrderController with the Index action to return an Order by Id.

public class OrderController : BaseController
{
    private readonly SimpleContext _simpleContext = new SimpleContext();

    public ActionResult Index(int id)
    {
        Order order = _simpleContext.Orders.Find(id);

        return Json(order, JsonRequestBehavior.AllowGet);
    }
}

For the sake of simplicity, I’m instantiating the EF DbContext directly. OrderController extends BaseController from my last post to provide JSON.NET integration and have the ReferenceLoopHandling set to Error in BaseController.

Now press F5 and start the app. When I make a request from the browser to /Order/Index/2, here is what I get.

get-order-by-id-response

In the response, we can see that Order with Id 2 contains 3 line items. Since we applied JsonIgnore to Order property, the serialization didn’t fail and we don’t see Order within OrderLineItem JSON.

Imagine we now need to get a particular order line item and at the same time its Order. To do that, we can add a new action called LineItem in Order controller.

public ActionResult LineItem(int id)
{
    OrderLineItem lineItem = _simpleContext.OrderLineItems.Find(id);

    return Json(lineItem, JsonRequestBehavior.AllowGet);
}

Build the changes and now make a request to /Order/LineItem/1. Here is what I get.

get-line-item-by-id

In the response, we can see that Order is missing because of the JsonIgnore attribute. But our requirement is we also need Order of the line item. There are a couple ways to handle this if you do a search on Google for “entity framework JSON circular reference”. But the way I prefer includes using AutoMapper.

With AutoMapper, we define DTOs and it’ll automatically map the properties from the models to the DTOs by convention. You can also configure the mapping using its fluent API if you want more control.

Install AutoMapper with NuGet. Create a OrderLineItemDto with the order information in it.

public class OrderLineItemDto
{
    public int Id { get; set; }
    public int OrderId { get; set; }
    public DateTime OrderCreatedDate { get; set; }
}

OrderLineItemDto.OrderCreatedDate is a property that will be mapped from OrderLineItem.Order.CreatedDate.

Open Global.asax and add this line to Application_Start() to bootstrap the AutoMapper configuration.

AutoMapperConfig.RegisterMappings(Mapper.Configuration);

Create class AutoMapperConfig in App_Start folder.

public class AutoMapperConfig
{
    public static void RegisterMappings(IConfiguration configuration)
    {
        configuration.CreateMap<OrderLineItem, OrderLineItemDto>();
    }
}

Here I’m calling CreateMap directly for simplicity purpose. AutoMapper provides a Profile class if you want to organize your mapping logic in a more structured way.
In LineItem action of OrderController, update the code to use AutoMapper to map LineItem to its Dto.

public ActionResult LineItem(int id)
{
    OrderLineItem lineItem = _simpleContext.OrderLineItems.Find(id);

    var dto = this.Map<OrderLineItemDto>(lineItem);

    return Json(dto, JsonRequestBehavior.AllowGet);
}

And finally in BaseController, add the Map() function used in the OrderController.

protected T Map<T>(object target)
{
    return AutoMapper.Mapper.Map<T>(target);
}

Build and make the same line item request, we will now see the OrderCreatedDate in the response.

get-line-item-by-id-dto

This may seem like a lot of code just to return Order information along with an line item. But most of the code is boilerplate code that just gets set up once and can be re-used by all other controllers. More importantly, we don’t see manually mapping logic in the controller action and we don’t need to disable any sort of ORM lazy loading functionality.

Here I’m just showing a little bit of AutoMapper functionality. For all the features that it provide, please refer to its wiki page.

With AutoMapper and JsonIgnore, hopefully they provide you with all the flexibility you need to return JSON data from MVC to your client.

Have fun coding!!

Replacing MVC JavascriptSerializer with JSON.NET JsonSerializer

In ASP.NET MVC, the default JSON serializer is JavascriptSerializer. It is used when we return JsonResult by calling Controller#Json() or simply instantiate a JsonResult directly. It is also used during model binding by the JsonValueProviderFactory for deserializing request body to action parameter. Today I’m going to replace the JavascriptSerializer for serializing outgoing data.

There are a couple reasons why we want to replace the JavascriptSerializer. The most common one is the date format. It serializes DateTime into a proprietary format while browsers and other 3rd party serializers have adopted the ISO 8601 standard.

Another reason is this serializer cannot handle circular reference. Circular reference is quite common when using ORM such as Entity Framework and NHibernate. To handle that, one could disable proxy, disable lazy loading or apply ScriptIgnore attribute. To me, disabling proxy and lazy loading is probably not ideal as this is the main reason to use ORM in the first place. Applying ScriptIgnore is a sensible solution but you are out of luck if you’re using .NET 4.0 or below because of this issue.

So we need a better JSON serializer. The most popular one in .NET now is probably JSON.NET. It has better date serialization and circular reference handling. On top of that, it has a lot more features such as working with WCF DataContract and DataMember attributes and if you’re working with EF generated classes, MetadataType attribute. You can see how its features compare to the JavascriptSerializer on the JSON.NET home page. One more reason to use JSON.NET is its the default JSON serializer for ASP.NET Web API. This just may make your upgrade in future a little easier.

To allow existing code to keep working after replacing the JSON serializer, I would create two classes, BaseController and JsonNetResult. BaseController is an abstract class that sits between your controller and the MVC abstract Controller class. You may already have one since it’s likely you have some project-specific methods or properties common in all your controllers. If you don’t, then just create one and have the existing controllers extend from it.

Now we’ll override the Json method used by other Json overrides in the MVC Controller class to return JsonNetResult.

public abstract class BaseController : Controller
{
    protected override JsonResult Json(object data, string contentType,
        Encoding contentEncoding, JsonRequestBehavior behavior)
    {
        return new JsonNetResult
                   {
                       Data = data,
                       ContentType = contentType,
                       ContentEncoding = contentEncoding,
                       JsonRequestBehavior = behavior
                   };
    }
}

Here is the JsonNetResult class.

public class JsonNetResult : JsonResult
{
    public JsonNetResult()
    {
        Settings = new JsonSerializerSettings
                       {
                           ReferenceLoopHandling = ReferenceLoopHandling.Error
                       };
    }

    public JsonSerializerSettings Settings { get; private set; }

    public override void ExecuteResult(ControllerContext context)
    {
        if (context == null)
            throw new ArgumentNullException("context");
        if (this.JsonRequestBehavior == JsonRequestBehavior.DenyGet && string.Equals(context.HttpContext.Request.HttpMethod, "GET", StringComparison.OrdinalIgnoreCase))
            throw new InvalidOperationException("JSON GET is not allowed");

        HttpResponseBase response = context.HttpContext.Response;
        response.ContentType = string.IsNullOrEmpty(this.ContentType) ? "application/json" : this.ContentType;

        if (this.ContentEncoding != null)
            response.ContentEncoding = this.ContentEncoding;
        if (this.Data == null)
            return;

        var scriptSerializer = JsonSerializer.Create(this.Settings);

        using(var sw = new StringWriter())
        {
            scriptSerializer.Serialize(sw, this.Data);
            response.Write(sw.ToString());
        }
    }
}

JsonNetResult inherits JsonResult to satisfy the signature of the Controller#Json method. One drawback with this approach is both MaxJsonLength and RecursionLimit properties are not used in my implementation since there are no equivalent properties in JSON.NET. Also notice in the above implementation, I have ReferenceLoopHandling set to Error so that circular reference still results in error.

Now by having your controllers inheriting from BaseController, they will start using JSON.NET to do JSON serialization. Here are the two ways to make use of the new serializer in a controller.

// calling overridden Json() method
return Json(data, JsonRequestBehavior.AllowGet);

// instantiating JsonNetResult
var result = new JsonNetResult
                 {
                     Data = data,
                     JsonRequestBehavior = JsonRequestBehavior.AllowGet,
                     Settings = { ReferenceLoopHandling = ReferenceLoopHandling.Ignore }
                 };
return result;

Notice the second way include setting ReferenceLoopHandling to Ignore. With this, the serializer will skip any circular reference. This is one option to handle circular reference by simply ignoring it. This does not work exactly the same as the ScriptIgnore attribute so JSON.NET provides the equivalent JsonIgnore attribute.

If you want more flexibility, you can update MemberSerialization of JsonSerializerSettings to OptIn to serialize only marked members.

Have fun coding!!

Bower Errors on Windows

I started playing with Bower and right out of the gate, there are a couple errors I encountered while using it on Windows. So I want to do a quick post on what I do to resolve the errors.

Let’s use installing twitter bootstrap as an example. I ran the following command:

bower install bootstrap

Right away I received the following error.

bower cloning git://github.com/twitter/bootstrap.git
bower cached git://github.com/twitter/bootstrap.git
bower fetching bootstrap
bower error status code of git: 127

Do some Googling a bit and it seems like the solution to the problem was put git in my PATH. That’s weird. It is in my PATH. Running “git –version” in command prompt clearly shows I have msysgit installed and running “where git” shows me it points to “C:\RailsInstaller\Git\cmd\git.cmd”. Okay, even though I didn’t literally install msysgit myself, it was installed as part of the RailsInstaller.

As a last resort, I’ll just take a quick peek into the bower source code at least to see where it throws that error. So I found package.js. How Bower works in my case is it will construct a git URL using some naming convention and uses git on my machine to run some commands using spawn from child_process. From my past memory, spawn actually was not able to run .bat and .cmd files, but it was able to run .exe files. So this may be the problem since my git points to git.cmd. I then updated my PATH variable to include the path to git.exe directly. Remember to add it after the RailsInstaller path since order matters.

Run “bower install bootstrap”. Error again.

bower cloning git://github.com/twitter/bootstrap.git
bower cached git://github.com/twitter/bootstrap.git
bower fetching bootstrap
bower error status code of git: 128

There where errors, here's a summary of them:
- status code of git: 128
fatal: Not a git repository (or any of the parent directories): .git

There is a status code 128 error. It’s a different error. At least it seems like a progress. Googling more and it may have something to do with the bower cache. I assume Bower works somewhat like npm. So let’s just open C:\Users\<Username>\AppData\Roaming and there I see both bower\cache and bower-cache. At this point, I know I’m very close and I don’t want to investigate further on which to delete. I’ll just delete both.

Run “bower install bootstrap” again. tada! Here is the message for success.

bower cloning git://github.com/twitter/bootstrap.git
bower caching git://github.com/twitter/bootstrap.git
bower fetching bootstrap
bower checking out bootstrap#v2.2.1
bower copying C:\Users\YourUsername\AppData\Roaming\bower\cache\bootstrap\c1ee45ee19795a66de4a0c45758fe0b1
bower cloning git://github.com/components/jquery.git
bower caching git://github.com/components/jquery.git
bower fetching jquery
bower checking out jquery#1.8.3
bower copying C:\Users\YourUsername\AppData\Roaming\bower\cache\jquery\cf68c4c4e7507c8d20fee7b5f26709d9
bower installing bootstrap#2.2.1
bower installing jquery#1.8.3

Since yeoman uses Bower internally, yeoman now also works and you can run “yeoman install bootstrap” to install twitter bootstrap for your yeoman project, given that you have yeoman set up for Windows of course.

Happy coding!!!

Deserialize Error in JSON for jQuery Ajax

When using jQuery to make ajax calls, if the request fails on the server side, jQuery does not deserialize the response content regardless if the content is in JSON or not.

Assume I have this code to make an ajax request and the server returns HTTP 500 error for the purpose of this post.

$.ajax('/Home/AjaxErrorTest').fail(function (jqxhr) {
    console.log(jqxhr.responseText);
    console.log(jqxhr.getResponseHeader('Content-Type'));
    console.log(jqxhr);
});

Here is the response error in Chrome inspector.

We can see that the response content type is application/json and the responseText is also valid json, but in order to retrieve the error message or any other data sent back from the server, we have to parse the response text.

$.ajax('/Home/AjaxErrorTest').fail(function (jqxhr) {
    if (/application\/json/.test(jqxhr.getResponseHeader('Content-Type'))) {
        try {
            var error = JSON.parse(jqxhr.responseText);
            console.log(error.message);
        } catch(e) {
        }
    }
});

To avoid having this same boilerplate code everywhere I make an ajax request, I decided to replace the jQuery ajax with my implementation and attach an error object from the deserialized form of the responseText to jqXHR. The reason being my existing code would still work unchanged and new code can start using the error object.

(function ($) {

    $.oldAjax = $.ajax;

    $.ajax = function () {
        var args = Array.prototype.slice.call(arguments);

        var jqxhr = $.oldAjax.apply(this, args);

        jqxhr.fail(function () {
            if (/application\/json/.test(jqxhr.getResponseHeader('Content-Type'))) {
                try {
                    jqxhr.appError = JSON.parse(jqxhr.responseText);
                } catch(e) {
                }
            }
        });

        return jqxhr;
    };

})(window.jQuery);

In the code, I first store the existing $.ajax to $.oldAjax and then set $.ajax to my implementation. When my implementation is called, I use the $.oldAjax to make the ajax call and get the jqXHR object. Before returning the jqXHR object, I hook up to the fail event so that I get to attach my appError object to jqXHR. So now in my code, I could just use it like the following.

$.ajax('/Home/AjaxErrorTest').fail(function (jqxhr) {
    if (jqxhr.appError) {
        console.log(appError.message);
    }
});

The current implementation is not bullet-proof. It works when the error handler is attached to the jqXHR object. It does not work with the case when the error handler is attached using the error property of the object passed to $.ajax. In my case, this is fine because I prefer using deferred/promise pattern.

Have fun coding!!

Structuring LESS CSS in ASP.NET MVC 4

Recently I’ve been using LESS to style my views in ASP.NET MVC 4. There is an approach that I follow to structure the LESS files that I feel it’s more organized and more discoverable for other developers on the team. Setting up LESS including bundling and minification can be a whole topic which I don’t plan to cover here. There’re many ways to do that and examples I found are here, here and here. In this post, I’m going to show how the approach I mentioned works.

Assume I have an Index.cshtml and inside, it uses _PartialView1 once and _PartialView2 twice.

<div class="header">
    <h2>This is the Header of this page</h2>
</div>
<div class="content">
    <div class="first-partial-view">
        <p>Render partial view 1</p>
        @Html.Partial("_PartialView1")
    </div>

    <div class="second-partial-view">
        <p>Render partial view 2</p>
        @Html.Partial("_PartialView2")
    </div>

    <div class="third-partial-view">
        <p>Render another partial view 2</p>
        @Html.Partial("_PartialView2")
    </div>
</div>

This is how the page looks before styling.

This is the result that I want to achieve after styling.

The way I start applying the styling is by first creating one .less file for each .cshtml file, regardless if it’s a view or a partial view. So for this page, I created Index.less, _PartialView1.less and _PartialView2.less. Here is the folder structure for the LESS files.

And here are the side-by-side looks of the skeleton LESS files and the views they are for.

Notice the LESS files start out with a very similar structure to its cshtml counterpart. This is important because I can tell exactly which LESS rules apply to which element.

Let’s add some rules to make the view look more like the final result that I showed earlier. Since _PartialView1.cshtml and _PartialView2.cshtml have their styles in separate LESS files, they need to be imported to Index.less. Here are the LESS files for all 3 views.

Index.less

@import "_PartialView1";
@import "_PartialView2";

.header {
  h2 {
    font-size: 18pt;
  }
}
.content {
  > div {
      margin: 5px;
    border: solid 1px gray;

    > p {
      color: blue;
    }
  }
  .first-partial-view {
    > p {
    }
  }
  .second-partial-view {
    > p {
    }
  }
  .third-partial-view {
    > p {
      color: red;
    }
  }
}

_PartialView1.less

.partial-view-1 {
  > p {
    font-size: 11pt;
    background-color: yellow;
  }
}

_PartialView2.less

.partial-view-2 {
  > p {
    font-size: 11pt;
    font-style: italic;
    background-color: lightgreen;
  }
}

The current page looks like this.

The page now looks fairly close to the final product that we want. However there’s a problem with the second _PartialView2. It needs to have a different font size and a different background color. To solve this, we want to be able to parametrize the styling for _PartialView2 and this is when mixins come in.

To do that, the idea I have is make the _PartialView2.less a mixin.

._PartialView2(@fontSize: 11pt, @backgroundColor: lightgreen) {
  .partial-view-2 {
    > p {
      font-size: @fontSize;
      font-style: italic;
      background-color: @backgroundColor;
    }
  }
}

In Index.less, I updated .second-partial-view and .third-partial-view to use the mixin.

@import "_PartialView1";
@import "_PartialView2";

.header {
  h2 {
    font-size: 18pt;
  }
}
.content {
  > div {
      margin: 5px;
    border: solid 1px gray;

    > p {
      color: blue;
    }
  }
  .first-partial-view {
    > p {
    }
  }
  .second-partial-view {
    > p {
    }
    ._PartialView2();
  }
  .third-partial-view {
    > p {
      color: red;
    }
    ._PartialView2(18pt, blue);
  }
}

The index page should now look the same as the final screenshot that we want.

Notice that I have not changed one line of cshtml in this post. And I really like the separation of html and css that LESS has given me. I have the LESS files folder structure organized the same way as the views folder structure. In addition, the rules within the LESS files are also modeled and structured the same way as the html in cshtml files.

Have fun coding!!

Triggering Mouse Events with jQuery Simulate When Testing in JavaScript

With jQuery, it’s very easy to trigger mouse event handlers by calling functions such as click, mousedown and trigger. They even propagate events so that event handlers registered higher up the DOM tree through delegate() and on() would get called as well. So in most of the cases I could just use them instead of triggering real browser events when writing tests. However recently, I had to write a couple components that need to listen to mouse events such as control click, shift click and mouse drag. Looking at the jQuery API, I couldn’t find any built in functions that could trigger mouse events but at the same time specify extra properties such as control or shift click.

Googling a bit on firing real browser events and thanks to the great documentation on MDN, first an event needs to be created, then initialized and lastly dispatched. The initMouseEvent sure makes me dizzy by  looking at it. On top of that, older IE browsers has a different API for doing the same thing. This got me thinking there gotta be a better way. What I wanted to do was just something other JavaScript UI projects must have had done. Then I took a look at the tests in jQuery UI project and sure enough, I found the jquery.simulate.js to simulate real browser events and it already handles the cross browser event creation. Now let’s see how it helps me create those events that I want.

jquery.simulate.js is just another jQuery plugin and its API is fairly simple. The first parameter of the plugin is the name of the event. Here you can use the names of the browser mouse events such as click, mousemove, mouseout, etc. For example, if we want to trigger a mouse click on elements with class name “target”. We can simply call this.

$('.target').simulate('click');

The plugin can also take a second argument to override the default event properties. These default properties include pretty much the same arguments required to call the browser native event initialization method, event.initEvent. Two of these properties are ctrlKey and shiftKey. With them, I can now easily test my event handlers for control click and shift click.

$('.target').simulate('click', { ctrlKey: true });
$('.target').simulate('click', { shiftKey: true });

To test mouse dragging, although “drag” is not a real browser event, the plugin comes with support to handle the case when the event name specified is “drag”. We just need to specify the name as drag and the change in x and y of the mouse position. Internally, the plugin will perform a series of events including mousedown, mousemove, mouseup and click to simulate mouse drag.

$('.target').simulate('drag', { dx: 200, dy: 100 });

Here is a sample page that shows how the plugin works.

<!doctype html>
<html>
    <head>
        <title></title>
        <script src="http://code.jquery.com/jquery-latest.js"></script>
        <script type="text/javascript" src="https://raw.github.com/jquery/jquery-ui/master/tests/jquery.simulate.js"></script>
        <script type="text/javascript">
            $(function() {
                $('.target').click(function(e) {
                    if (e.ctrlKey) {
                        console.log('control click');
                    } else if (e.shiftKey) {
                        console.log('shift click');
                    } else {
                        console.log('regular click');
                    }
                }).mousedown(function(e) {console.log('mousedown', e);})
                .mouseup(function(e) { console.log('mouseup', e); });

                $('button').click(function() {
                    if($(this).hasClass('drag')) {
                        $('.target').simulate('drag', {dx: 100, dy: 50});
                    } else if($(this).hasClass('ctrl')) {
                        $('.target').simulate('click', {ctrlKey: true});
                    } else if($(this).hasClass('shift')) {
                        $('.target').simulate('click', {shiftKey: true});
                    } else {
                        $('.target').simulate('click');
                    }
                });
            });
        </script>
    </head>
    <body>
        <div class="target" style="background-color: yellow; height: 300px; width: 500px">Test Target</div>
        <div>
            <button class="ctrl">Ctrl Click</button>
            <button class="shift">Shift Click</button>
            <button class="regular">Regular Click</button>
            <button class="drag">Drag</button>
        </div>
    </body>
</html>

There are other options that are supported in the plugin. For complete list of options, please refer to the plugin on GitHub.

Have fun coding!

Setting Up Jasmine with ASP.NET MVC and RequireJs

In my last post, I set up RequireJs inside an ASP.NET MVC project. In this post, I want to go over how to set up Jasmine to test JavaScript modules in a MVC project by using the example code and tests in the Jasmine bundle.

Here are the two goals I want to achieve when setting up the directory structure.

  • Have the test files in another project separate from the project that contains the JavaScript code to be tested
  • Be able to run the Jasmine tests locally without spinning up a web server

The reason to put the test files into a separate project is that I already use Visual Studio projects to organize test projects such as unit tests and integration tests. It makes sense to me to put Jasmine Tests into its own project as well. And for the reason to run Jasmine tests without a web server, I treat Jasmine tests as unit tests, so there shouldn’t be any need to make any real Ajax calls but instead, they should be mocked out by using Jasmine’s spy methods. It also gives me the convenience of simply dragging the runner html file to the browser to run all the tests.

First head to here to download the latest release version of Jasmine (1.2.0 at the time of this writing). Unzip it and open SpecRunner.html in the browser. Here is the successful screen we want to see at the end of this post.

Next let’s create or open an ASP.NET MVC project with RequireJs configured like I did in my last post. In the same solution, add a new Class Library project to store the Jasmine tests we’re going to add. Copy lib, spec and SpecRunner.html from the unzipped folder and add them to the Test project.

lib contains the Jasmine code to give you functions to do set up, tear down, asserts, spies, etc, in your tests; SpecRunner.html is the runner html file where all the test files are listed and it also displays the test results; spec is the folder that contains the test code or any helper code used in the tests.

In the src folder of the unzipped folder, copy both Player.js and Song.js to the /Scripts/App folder of the MVC project. Player.js and Song.js are the code that will be tested.

Now all the files are in place, we’ll need to update them to work with RequireJs. First open up both Player.js and Song.js. Add the define statement to make them AMD modules.

Let’s now update SpecRunner.html. Comment out all 4 script tags that reference the source files and spec files, and add the script tag to include RequireJs from the MVC project. Since I’ll be running SpecRunner.html using file path instead of URL, I’ll use relative path to reference require.js. Then configure the baseUrl and paths attributes of RequireJs. The baseUrl points to the Scripts/App directory of the MVC project because that’s also the same directory configured as baseUrl in the MVC project and used by the JavaScript source files. The spec attribute in the paths config is to tell RequireJs it needs to point to the spec folder in the Test project. It’s a relative path to the baseUrl.

One more change to the SpecRunner.html is that as we commented out the source files and spec files script tags, they won’t get loaded if we just open the runner in the browser. And the way I want to load them is by making them AMD module and use require to load them.

Next open PlayerSpec.js and make it a module. Since it uses Player and Song, the define statement will need to specify these dependencies. And it does not have a return statement as anything returned will not be used in this case.

We have made all the changes. And now if we open SpecRunner.html, we should see the same successful screen as before we integrate it with ASP.NET MVC and RequireJs.

Have fun coding!