Thursday, February 10, 2011

Mocking the jQuery Ajax Call in ASP.NET MVC 3 Music Store

Sometimes the front-end and back-end of your application progress at different speeds. In order for each layer to progress independently it is optimal if the front-end piece can mock the results of the back-end.

I have grabbed the AJAX section from the recently updated ASP.NET MVC 3 Music Store and I slightly tweaked it below.

$(".RemoveLink").click(function() {
  var recordToDelete = $(this).attr("data-id");

  if (recordToDelete) {
    $.post("/ShoppingCart/RemoveFromCart", {
      "id": recordToDelete
    }, function(data) {
      if (data.ItemCount === 0) {
        $('#row-' + data.DeleteId).fadeOut('slow');
      } else {
        $('#item-count-' + data.DeleteId)
          .text(data.ItemCount);
      }

      $('#cart-total').text(data.CartTotal);
      $('#update-message').text(data.Message);
      $('#cart-status')
        .text('Cart (' + data.CartCount + ')');
    });
  }
});    

Let's say for example, that the controller action wasn't yet implemented, but the front-end developer still wanted to progress in their code. To do this we are going to introduce a new tool called Mockjax to simulate a response from a jQuery ajax call.

The following code mocks any call to the /ShoopingCart/RemoveFromCart URL and will respond with the following object literal.

$.mockjax({
  url: "/ShoppingCart/RemoveFromCart",
  responseTime: 750,
  responseText: {         
    ItemCount: 5,
    DeleteId: 1,
    CartTotal: 112.45,
    Message: "Your cart has been updated!",
    CartCount: 16
  }
});

The great thing about the above technique is that you are guaranteed the same response will be returned no matter what request you made to the ajax call. For example, this approach can be very good for Unit Testing. However, if you are trying to demonstrate the code to a client or just want to play around with the behavior then you might want something a little more flexible and dynamic.

Fortunately, Mockjax not only allows you to return a static set of responseText or repsonseXML, but it also lets you dynamically decide what content you want returned, which is what we are going to demonstrate below.
Note: Mockjax offers much more control than what I am showing in this example. I encourage you to check out all of it's features.
$.mockjax({
  url: "/ShoppingCart/RemoveFromCart",
  responseTime: 750,
  response: function(settings) {
    var row = $("#row-" + settings.data.id),
      itemCount = +row.find("td").eq(2)
        .text(function(index, text) {
          return +$.trim(text) - 1;
        }).text(),
      cartTotal = 0, cartCount = 0;
        
    $("table tr").each(function(index, element) {
      var row = $(element),
        price = +row.find("td").eq(1).text(),
        quantity = +row.find("td").eq(2).text();

      if (price && quantity) {
        cartCount += quantity;
        cartTotal += price * quantity;
      }
    });

    this.responseText = {         
      ItemCount: itemCount,
      DeleteId: settings.data.id,
      CartTotal: cartTotal.toFixed(2),
      Message: "Your cart has been updated!",
      CartCount: cartCount
    };
  }
});

This might seem like excessive front-end code, but the intent is to simulate what the back-end might return in order for the front-end to respond in an appropriate manner. The code is doing some basic calculations to determine what the Shopping Cart quantity and values might be after deleting an item.
Note: The mockjax response code above could have been simplified somewhat if I had modified the MVC 3 View rendering the HTML, but as in many projects you don't always have access to change the existing output. I decided to go with that approach instead of changing the MVC 3 View code in this blog post.

Once the back-end code is complete, then you can remove the $.mockjax call from your code-base and it will be hitting your back-end resource instead of the mocked response.

I captured the HTML, CSS, and JavaScript from the MVC 3 Music Store and put it in the following jsFiddle for you to execute and play around with. The main piece that I added was the mockjax code to simulate the AJAX request and response from the server.


Note: You might also consider mockjax to be a great Unit Testing tool as you are developing your front-end code and the back-end isn't yet implemented.


No comments:

Post a Comment