ASP.NET MVC, WCF, ASP.NET Webforms, and JQuery

The sole purpose of any API within the applications I build is to deal with business layer logic and the data related to it. Ideally speaking I would want my API to return structured data which is easily transformed into a format for the client application using the API (e.g. JSON). And all my UI for web applications must be handled with client-side scripts. Client side includes both static HTML, CSS and JavaScript, and in this instance I specifically refer to JavaScript and the handling of my API’s data using JSON, for which I use jQuery.


Before I get into it I would like to reiterate some of my personal development objectives of late:

1. Don't do ANY UI manipulation in any of my server side API's. The sole purpose of any API within the applications I build is to deal with business layer logic and the data related to it. Ideally speaking I would want my API to return structured data which is easily transformed into a format for the client application using the API (e.g. JSON). I have had experiences within another development team in the recent past where the API returned HTML with the data and to say that this is a mess is understating the obvious - if you think about it quickly then you can understand the impact of one style or layout change will have on this approach. It also blurs your application in terms of its concerns and makes testing a problem. So ideally I dont want any UI logic in any of my API's.

2. The second objective I have is that all my UI for web applications must be handled with client-side scripts. Client side includes both static HTML, CSS and JavaScript, and in this instance I specifically refer to JavaScript and the handling of my API's data using JSON, for which I use jQuery. The REST (:D) of this article is dedicated to the AJAX options available in an ASP.NET application.

Dealing with AJAX in an ASP.NET Application

Developing ASP.NET applications gives you two "frameworks" or "architectures" to work with:

  1. ASP.NET Webforms

  2. ASP.NET MVC

Notice that each architecture or framework uses the ASP.NET runtime which in turn runs on the .NET framework, and part of the .NET framework is the Common Language Runtime (CLR). People often think ASP.NET automatically refers to webforms. The difference between the architectures lies both in how it was designed and who it was designed for. Webforms was designed for Windows Forms developers working within the Visual Studio drag-and-drop environment and aimed to provide an abstraction of Windows Forms for the web. With webforms you could simply drag and drop controls onto a design surface and assign properties to the controls. The problem with webforms was that it required state management and to deal with the state management viewstate was created. Basically state management refers to a controls ability to retain its "value state" across postbacks. So if I created a simple label and set its text to "hello world" viewstate is used to retain that text value throughout the life of the rendered page. Webforms also introduced the concept of the Page Life Cycle, which exposed certain events at certain points of the page's rendering process. The problem with viewstate is that the viewstate is inserted into your HTML pages which causes the page to bloat - so there is no clean markup. Viewstate totally goes against the grain of how the web works - being stateless.

ASP.NET MVC addresses some of the issues associated with webforms by using a mature and well known architectural pattern - Model-View-Controller, as used in Ruby-On-Rails. ASP.NET MVC does not use the page lifecycle for a start and it embraces the web's statelessness instead of fighting it. The result is that you have no ViewState and this means that there is no HTML bloat and you also have complete control over your HTML.

There are a couple of ways to consume AJAX requests in ASP.NET but they fall into two categories:

  • SOAP

  • REST

With my latest development effort I started out by using Page Methods in an ASP.NET Webform application. Why ASP.NET webforms you may ask? Well I wanted to focus on the business value and I just started out with Webforms without concerning myself too much with the technical side of things. Page methods implement a REST-like architecture and simply requires that you add a WebMethod attribute in your code-behind's CS file like this:

[WebMethod]   
public static Dictionary<DATETIME, List<MonthReport>> GetLastSixMonthReport()

You could then access the web method through jQuery like this (notice the Default.aspx/GetImportsLastSixMonths):

$.ajax({   
    type: "POST",   
    url: "Default.aspx/GetImportsLastSixMonths",   
    data: "{}",   
    contentType: "application/json; charset=utf-8",   
    dataType: "json",   
    success: function (msg) {   
        var dict = msg.d;   
        var html = '';   
        $("#importsData").empty();   
        html += dict;   
        $("#importsData").append(html);   
    }   
});  

The main issue I have with this approach was that if I wanted to create a new web project I had to re-create the web methods - which is not ideal. So if I wanted to move this project over to a new MVC app I would have to recreate the methods. Based on this I decided to create a separate WCF project that could host all my methods and deliver them in a REST-JSON way. To get WCF to deliver JSON in a REST fashion you need to do two important things:

  1.  Configure it

  2.  Add the appropriate Interface attributes

Configuring a WCF service for JSON requires that you add an endpoint address to the service itself like this:

<ENDPOINT name="RESTEndpoint" contract="IMyInterface" binding="webHttpBinding" behaviorConfiguration=
"AjaxBehaviour" address="ajaxEndpoint" />  

You also need to add an endPointBehavior like this:

<BEHAVIOR name="AjaxBehaviour">  
    <WEBHTTP />  
</BEHAVIOR>  
/ENDPOINTBEHAVIORS> 

In your service behaviours you need to set httpGetEnabled to true as well. I added this in my service class:

[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)] 

In service contract I added the WebInvoke attribute to each method, like this:

[OperationContract]   
[WebInvoke(Method = "GET", BodyStyle = WebMessageBodyStyle.Wrapped, ResponseFormat = WebMessageFormat.Json)]   
ProductCollectionView[] GetProductCollectionViews();  

Once I set this up I could access the JSON-enabled endpoint: http://localhost/LRB2CServiceLayer_v1/LRB2c.svc/ajaxEndpoint/GetProductCollectionViews and I would see the JSON. Notice that the JSON comes with a MethodNameResult as opposed to the "d" from the page methods. Consuming it uses a similar approach to the jQuery for page methods, except that you use a GET (which is a little dodgy):

$.ajax({   
    type: "GET",   
    url: "http://localhost/LRB2CServiceLayer_v1/LRB2c.svc/ajaxEndpoint/GetProductCollectionViews",   
    data: "{}",   
    contentType: "application/json; charset=utf-8",   
    dataType: "json",   
    success: function (msg) {   
        var dict = msg["GetProductCollectionViewsResult"];   
        var html = '';   
        $("#importsData").empty();   
        html += dict;   
        $("#importsData").append(html);   
    }   
});  

I decided to convert the WCF service to a class library (DLL) instead because I had all kinds of issues with XSS because I ran the WCF service as a separate web application. The idea was that a WCF service was easily shared between web apps. I basically combined the class library with a MVC web app instead. A class library can just as easily be shared among multiple projects or web sites. The JSON that MVC returns is different to WCF and Webforms - it just returns the object, no indexer/key such as "d". Getting MVC to return JSON is pretty straight forward:

[HttpPost]   
public JsonResult GetGetProductCollectionViews()   
{   
}  

Of the three methods/technologies I described I like the ASP.NET MVC approach because:

  • Its RESTful

  • The JSON result only contains the object(s)