In my last post, I introduced this series in which I add Ajax to an ASP.NET MVC application as a progressive enhancement, allowing the site to function without requiring JavaScript, but creating a better user experience for users with JavaScript enabled. In this post, I will discuss the feature I am working on and introduce the base controller and view code as well as introduce a minor change to the initial controller code to add support for Ajax calls/return data without breaking the standard post-based behavior.
The Target Functionality
The functionality that we will be looking at for the purpose of these posts will be a simple content page that allows comments. The comment form will exist on the content page and will call a controller that will then insert a record in the database. Since the comments live on the page with the associated content, the controller will redirect to the view that the form was submitted from (showing the content again, along with the comments). The page will be reloaded, just as you would expect from a typical form submission that redirects following the submission. Once that works, we can update the code to make the form submit via Ajax, at which point we will need to update the page through client script.
The Initial Code
The initial code is a simple controller action which makes a call to a business object that will handle inserting the comment into the database. I will be displaying a code comment as a placeholder for that code since it has very little relevance to the topic at hand.
[AcceptVerbs("POST")]
public ActionResult AddComment(string commentBody, int articleID)
{
//Logic and Database insert code...
//redirect to re-load the page
return RedirectToRoute("Default",
new { controller = "Article",
action = "Show",
id = articleID });
}
At this point, since the View for our content will re-query and display all of the associated comments all that this code needs to do is redirect the user back to the content page and the new comment will be loaded along with the rest of the comments. The above code accomplishes this redirect in a single line of code.
Updating The Controller Action
Now that we have the form in the view successfully submitting its content to the controller action through a post, we need to update the action code to distinguish between a standard post and an ajax-based post in order to return JSON when needed. One of the goals was to make any controller changes minimal. We also want to make sure that none of the business logic changes due to the addition of Ajax. So let’s take a look at the code for the first step:
[AcceptVerbs("POST")]
public ActionResult AddComment(string commentBody, int articleID, string mode)
{
//Logic and Database insert code...
//redirect to re-load the page
return RedirectToRoute("Default",
new { controller = "Article",
action = "Show",
id = articleID });
}
The only change we have made at this point is to add an additional string argument to the method’s signature. This “mode” argument isn’t part of the original form post, and that’s ok. Our form doesn’t need to change. The only time (at this point) the mode value will be passed is when we are making the call from JavaScript. Now we will add a simple check to see if that string has been passed. If it hasn’t been passed, then we know it was a standard post and we will perform the redirect, just like we have been doing:
[AcceptVerbs("POST")]
public ActionResult AddComment(string commentBody, int articleID, string mode)
{
//Logic and Database insert code...
if (!string.IsNullOrEmpty(mode) && mode == "ajax")
{
//handle json result for ajax call
}
else
{
//redirect to re-load the page
return RedirectToRoute("Default",
new { controller = "Article",
action = "Show",
id = articleID });
}
}
Now all that’s left to do is return JSON formatted data if the mode has been passed. The final version of the controller action is listed below.
[AcceptVerbs("POST")]
public ActionResult AddComment(string commentBody, int articleID, string mode)
{
//Logic and Database insert code...
if (!string.IsNullOrEmpty(mode) && mode == "ajax")
{
//The comment object is returned after the data insert above
return this.Json(comment);
}
else
{
//redirect to re-load the page
return RedirectToRoute("Default",
new { controller = "Article",
action = "Show",
id = articleID });
}
}
This code includes a call to the Controller’s Json method (referenced as this.Json) which accepts your data object (in our case, a comment object that was returned from the omitted data insert code) and returns a JsonResult object that can be returned from the controller. The passed object is then made available to your JavaScript when it receives the Ajax result. We will take a closer look at the comment object in the next post, when we add the JavaScript that will trigger the JsonResult object being returned.
This controller action meets our goals of using the same logic regardless of the method that was used to post the form and I think the changes are fairly minimal (again, this is pretty subjective).
Coming Up
We still need to add the jQuery code required to make an Ajax call to the controller and ensure that there is a return value. After we have the code in place to make the call and run the controller code, there will be a couple more posts to explain how to handle the return data and add some other nice UX features for those with JavaScript enabled.
Andrew .NET, ASP.NET, Ajax, JavaScript, MVC, jQuery Ajax, ASP.NET, JavaScript, jQuery, MVC, Progressive Enhancement