I’m sure that some (if not many) of you know this little approach for posting data from a JSON POST action (through jQuery) to an MSMVC Controller. If you don’t, keep reading otherwise go read something more important :)

Note:

As Phil noted, what the title should read is Receiving JSON Data from An Action Method, so my apologies for being misleading on the title. To see how you can actually post JSON data, check out Phil's Sending JSON to an ASP.NET MVC Action Method Argumentpost.

What are you trying to do?

While working on MSMVC sites, I (like many of you) find myself doing a lot of user interaction with AJAX (via jQuery) on the client. At times, I will need to post several pieces of related data to an action and then get a response back from the server. If you’re doing some clever routing to create a moreRESTful resource, then this will not work for you since you’ll need to pass the information as dictated by your route. But if you have a controller action that takes a chunk of data, then this will work perfectly for you.

Again, the goal here is to keep things pretty simple and leverage as much as the runtime’s out of box wiring as possible.

How do we do it?

Take the following form (design and html):

Capture

123456789101112
<!-- Created via Html.EditorForModel extension method -->
<div class="editor-label">
<label for="Name">Name</label></div>
<div class="editor-field">
<input class="text-box single-line" id="Name" name="Name" type="text" value="" /> </div>
<div class="editor-label">
<label for="Age">Age</label></div>
<div class="editor-field">
<input class="text-box single-line" id="Age" name="Age" type="text" value="" /> </div>
<p><input type="submit" value="Save" id="personCreate" /></p>
 
<div><span id="resultMessage"></span></div>
view rawgistfile1.html hosted with ❤ by GitHub

The whole purpose of this form is to take the data, do some simple data validation and then POST the data to the server for processing.  This can be done in several ways, since we’re doing a POST action, we opt to use the jQuery.post() method. As the documentation states, this is nothing more than an explicit setting of the jQuery.ajax() API function which specifies POST as the action method.

One of the parameters that can be passed to the post API call is the actual data for the call. The type of this data parameter can be either a map (structure) or string since this will be passed as part of the request body. To get the most “bang for your buck” with this API, you’ll want to have the data parameter be a map (structure) and let the jQuery and MSMVC runtime do the heavy lifting for you.  Let’s examine the data that’s request by our controller for the above form.

All we need for this request to be valid is a nothing more than a simple input model to hold the “person” information as well as an action to receive it:

123456789101112131415161718192021222324252627
namespace JSONMvcSample.Models {
using System;
 
[Serializable]
public class PersonInputModel {
public string Name { get; set; }
public int Age { get; set; }
}
}
 
namespace JSONMvcSample.Controllers {
using System.Web.Mvc;
using Models;
 
[HandleError]
public class HomeController : Controller {
public ActionResult Index() {
return View();
}
 
[HttpPost]
public ActionResult Save(PersonInputModel inputModel) {
string message = string.Format("Created user '{0}' in the system.", inputModel.Name);
return Json(new PersonViewModel {Message = message});
}
}
}
view rawgistfile1.cs hosted with ❤ by GitHub

As you can see, there's nothing complicated about these pieces. Just a simple controller action that takes in an Input (View) Model and returns a JSON data structure back to the caller. The only thing that can be consider complicated about this action is the [HttpPost] restriction, since as we stated earlier, we're doing a jQuery post API call.

One of the nicest features of MSMVC is the concept of a IModelBinder, which performs a lot of heavy lifting for you when you transfer complex objects via a request.  Out of the box, the DefaultModelBinder will wire up primitive, (light) complex types and collections for you by pulling information from the request (request body, query string, form data, etc.)  In other words, if you provide the right information for a request, the DefaultModelBinder will do the rest for you.  Let’s go back and examine our jQuery POST code.

What we need to do here is simple,

  • Get the values out of the input elements
  • Perform (poor/simple) validation
  • POST the data to the server
  • Get the response and display the information

The previous list can be accomplished by the following:

1234567891011121314151617181920212223242526
$(function () {
$("#personCreate").click(function () {
var person = getPerson();
 
// poor man's validation
if (person == null) {
alert("Specify a name please!");
return;
}
 
// take the data and post it via json
$.post("home/save", person, function (data) {
// get the result and do some magic with it
var message = data.Message;
$("#resultMessage").html(message);
});
});
});
 
function getPerson() {
var name = $("#Name").val();
var age = $("#Age").val();
 
// poor man's validation
return (name == "") ? null : { Name: name, Age: age };
}
view rawgistfile1.js hosted with ❤ by GitHub

In the above sample, all the magic takes place with the aide of the "Person" structure that's passed as a parameter to the POST call.  If we examine the request body (with the aide of Firebug) we can see how the request is actually structured:

json_request_bodyThe outlined area show that the data within the request is passed as key-value pairs (application/x-www-form-urlencoded) to the server processing. Again, since MSMVC comes with the DefaultModelBinder, we get the mapping of the request data into our input (view) model for free:

controller_structure

 

From here, we can easily return JSON back to the client and allow it to do processing as it sees fit. In our case, we’ll just display the data to the user as a simple message:

resultPretty straight forward and simple, huh?  If you’re interested on the code, go here: http://github.com/jglozano/samples/tree/master/JSONMvc

Happy Coding!