Monday, October 20, 2008

Update to JSON Service Provider using ASP.NET MVC Beta as well as testing Dates with Microsoft AJAX Client Templating


Recently Microsoft has updated the ASP.NET MVC to Beta status, and along with that came code changes. One of the code changes to the IModelBinder and how it interacts with the Parameter bindings broke what I wrote on the last post (utilizing ASP.NET MVC as a JSON Service Provider, and coding the entire web site on the client side).

Upon loading the Beta bits, I realized my AJAX Parameter function was infinite looping. The reason is that the Model Binder defaults to trying to bind Complex Types in the Action Parameter to the form values being passed back, however, since I am not doing a form postback, it could not bind that to the complex type, and could not run the ActionExecuting on the AjaxParameterAttribute I had set.

So to fix this, I thought I would use the IModelBinder and re-do that section of my code using the new bits. Here is the result:
 image

As you can see, I updated the example to be more real world with caching out the original server side object to do compares against the modified version:

image 
image

I also added 2 new Javascript helpers to test Dates with the Client Side AJAX Templating engine:
image

And the HTML Code to test Live Binding Dates with the MVC Beta:
image image 

Before I change the Live Binding Date using the Microsoft AJAX Client Template:
image

After I merely type a different date, no post back, it auto converted the string back to the Javascript Date property on my Model Object (notice how the convert and convertBack Live Templates handle the display and changing the javascript object – I have complete control over it):

image

After post back, testing the IModelBinder to serialize the Javascript Object in JSON to a C# object:

image

This is just cool. Anyway you slice this, ASP.NET MVC with Microsoft AJAX Client Templating engine is just simple, effective, and elegant. I am falling in love with these frameworks the more and more I play with them.

Also, in my opinion, using the IModelBinder is a cleaner approach to the original solution I used earlier. It just feels more separated out.

Updated Source Code

Questions, comments, opinions?

kick it on DotNetKicks.com

Thursday, October 9, 2008

Using the ASP.NET MVC Framework as a JSON Service Provider for Richer Web Applications with MS Ajax Templates and jQuery


Wow, that’s a really long title, but that is what this post is actually about, and why I think it is a great way to handle many web applications today.

I have recently been doing a lot more Javascript Client side applications and working a lot closer with JSON objects to build complex web pages. The problem I typically run into is getting my C# POCO objects to translate to a JSON Object on the client side so I can work with it and change it and then post it back to the server to handle it appropriately.

The basics of what I wanted was to seamlessly work with my Model data and it automatically handle converting to JSON or C# Objects at the correct layer.

I have used ADO.NET Data Services and Entity Framework (with the EF POCO Adapter project by Jaroslaw Kowalski @ here - which by the way is a preview of how POCO will work in Entity Framework 2.0, and has absolutely changed my mindset on Entity Framework).

First, Some Background

Using ADO.NET Data Services allowed me to utilize jQuery as the controller and presentation layer, and the ADO.NET Data Service and Entity Framework as the model. However, if I wanted to split up my Domain specific logic from my individual application business logic on the server side, I would have some work to do. Suppose that you already have a Service(Business) layer on the server side that setup your POCO objects and handled application specific logic before pushing it down to the Data-Layer (in my instance the EFPocoAdapter) or handled loading data in a very specific way, that would not be easy to do using ADO.NET Data Services.

I can push Domain specific rules by tying into the Adapter from EFPOCOAdapter using the following way:
clip_image002

Example of such a POCO Object tied into EFPocoAdapter:clip_image004

As you can see, my User model object represents a user in my system. I am tying that entity to IDomainEntity to specify that it requires Domain Validation, and when my Adapter in my Domain Layer saves this Model, it will run validation rules against it to verify it is correct.

However, if I had Business Logic I wanted to impose in my Service layer that does not belong in my Domain Data Layer, I cannot easily use ADO.NET Data Services without some additional work.

So in essence I want a to structure my Layers as such:
Model Layer => Domain Data-Layer (EFPocoAdapter) => Service Layer (Business)

The above would represent my Model for the MVC Framework. By doing this, I can cleanly separate out each concern in its respective layers and maintain reusability and simplicity.

However, if ADO.NET Data Services cannot get me there easily, what do I do? I could use WCF and that has worked fine for me in the past, however, since I fell in love with the MVC Framework, I wanted to see how I can utilize that.

Alright, so what is this post really about?

With that bit of history out of the way, what is my intent here? I essentially want to utilize ASP.NET MVC to make a Web Service Provider that returns to me my C# model objects in JSON Format, and allow me to post that Javascript object back to the server and it automatically convert it back to a C# object to process on the server.

So in essence, architecturally speaking, the Javascript logic becomes the Presenter that calls to the Server-Side Controller, that will call the Service Layer to get the Model Data from the Domain Layer.

Breakdown:

Client Request For Data
Html View with Template Binding
||
Javascript Presenter (Request JSON Data)
||
Server-Side Controller (gets C# Model Data and sends as JSON Data)
||
Service Layer (Business logic to call to the Domain Layer)
||
Domain Layer (Entity Framework POCO Adapter Preview)
||
Model POCO Objects (simple C# objects that represent Model Data)

Client Post Javascript Object Model Data
Html View with Template Binding
(2-way binding updates JSON object as changes made)
||
Javascript Presenter (Posts JSON Data)
||
Server-Side Controller (auto serializes JSON to C# Model Parameter)
||
Service Layer (Business logic update to the Domain Layer)
||
Domain Layer (Entity Framework POCO Adapter Preview)
||
Model POCO Objects (simple C# objects that represent Model Data)

In a way, I want to seamlessly convert between C# objects to Javascript objects without me doing any additional work than is necessary and utilize some new features such as Templating to get a two-way binding to that Javascript object so, again, I have little work to do.

So how did I do it? Well, with the help of Scott Hanselman in this post (here) and Omar AL Zabir in this post (here) I had enough tools to accomplish what I needed.

How did I do it?

First I needed a way to convert a C# model object to a Javascript object from MVC. I created the following ActionResult class to accomplish this:clip_image006
Notice that depending on the content type, it will return JSON or XML. The standard JsonResult type in ASP.NET MVC requires that I know I want JSON. Utilizing a known mechanism in HTTP to specify what you want: the content type. There is no need to re-invent the wheel here, content type is the requested type you are expecting.

Next I needed a way to convert a Javascript object back to a C# object in the parameter of a MVC Action. I created the following ActionFilterAttribute to accomplish this:
clip_image008

I then set-up a test Controller to test this setup:
clip_image010

Notice that I am returning on GetUserList Action a list of Users that is a C# Domain Object and depending on the content type from the client, will return XML or JSON.

Next notice that I am marking up the “POST” action UploadUser to convert the parameter User[] from a JSON Format to a C# Domain Object so that I can then use my Service layer to save it or whatever I want to do with it. I then return back a JSON response back to the client, along with a possibly changed Model object for the client to rebind to.

Now, I need a client side script to help me handle calling and tying everything together. For this, I included the following Javascript Libraries:

  • MicrosoftAjax.js
  • MicrosoftAjaxTemplates.js (you can find this at CodePlex under ASP.NET)
  • jQuery
  • JSON2 *the version changed by Rick Strahl* (you can use whatever you want, I just like this one)
  • A custom Helper jQuery Plugin to help make everything simpler :
    clip_image012clip_image014

This custom Javascript library will allow me to make my Javascript Client code less terse, and easier to maintain.

Next, let’s setup a View to test this scenario:
clip_image016
clip_image018
There is a lot going on here, but to put it simply, I am using MVC to route the user to this Test View that will load up the User data via a JSON Endpoint request and once that C# Model object is transformed to a Javascript object, I use Microsoft Templating to two-way bind that to my controls. As the user changes values, it is automatically updating the Javascript object, just as it would in WPF. Once the user is finished, they can click the save button, and the client side code will make a Javascript call passing that Javascript object back to the server MVC endpoint (Controller Action). That action will automatically convert that JSON object to its equivalent C# Model object, so that my controller can now save it or whatever it wants, and then respond back to that AJAX request with any errors or messages, as well as a possibly modified Model Javascript object for my View to rebind to.

Phew, that may seem complicated, but it’s really very simple, and requires very little to accomplish once all of your code is in place.

Enough about what it is doing behind the scenes, show us results!

Upon browsing to my http://localhost/home I am greeted with the following:
clip_image020

As I change the values in the text box, notice that the Javascript object on the client is changing also (I have not posted back yet!):
clip_image022

After I post back:

clip_image024

I am testing to see that if some of my Domain logic or application logic fails, that I can get that information back to the client to fix. To test this, the success of the AJAX post will be considered a failure (as you can see from the Test Controller code) if any value has the word “fail” in it. This will allow me to change my C# Model object slightly from the controller and push it back to the client as a Javascript object to rebind the controls to. This will allow the user to fix any issues they may have and repost if necessary.

Here is the Debug against the post so you can see how the Javascript object is transformed into a C# object:

clip_image026

As you can see, once setup with the AjaxResult, AjaxParameterAttribute, and the custom jQuery Plug-in Client-side helper, it is a snap to build out AJAX driven pages and not have to worry about going from server side objects to client side objects. This to me brings us much closer to a Silverlight/Flash type application, especially when considering the speed increases in Javascript on all major browsers coming.

Source Code

Questions, comments, ideas?


kick it on DotNetKicks.com