Home / AJAX

How Do I Retrieve Data from a Controller Action?

RSS
Modified on 2010/07/20 04:32 by James Chambers Categorized as Uncategorized

Problem

I want to respond to some kind of user input and I am using Ajax to load data from my controller. How do I retrieve it in such a way that I can process the results with jQuery?

Solution

The ASP.NET MVC Framework includes the JsonResult class and the Controller.Json helper method to serialize your .NET classes and return the data from your controller.

Using JsonResult

The JSON serialization of data is supported in ASP.NET MVC and it works with jQuery out-of-the box. The data you're working with - be it an instace of a simple class or a collection of complex objects - can be expressed in the proper notation and passed back to the requesting script for processing.

Though I wouldn't expect it to ever get a lot of hits, let's suppose I created a web page that allows users to view some of the older things in my house.

Image

The page is pretty straightforward, a title, some instructions and a painfully obvious button to click. Our script might look something like the following:
// set up a click handler for the button to get the list of old things
$("#get-oldthings").click(function () {
    $.post('<%= Url.Action("GetOldThings") %>', { minAge: 10 }, ParseThingList);
});

In the code above we are posting an integer value to an action named GetOldThings. The parameter name (in this case, minAge) must match the name in the controller's action. The method ParseThingList will be called on a successful return.

Our controller action would look similar to the following:
[HttpPost]
public ActionResult GetOldThings(int minAge)
{
    IOldThingRepository repository = new OldThingRepository();
    return Json(repository.GetOldThings(minAge));
}

Essentially, we're taking the value the user has passed in, looking up some data in our repository, and returning the results. The Controller.Json helper method takes care of building the JsonResult object for us, which will ultimately serialize our data. The end result is that a JSON formatted string is returned to the client. If you examine the HTTP response, you would see my old things represented as such: JSON formatted data returned from an MVC controller

A request is made, we perform a lookup based on the parameters provided and the controller returns the data for processing by the ParseThingList function we wrote in JavaScript.

Try Me!

If you are familiar with JsonResult in ASP.NET MVC, you might find the HttpPost attribute above somewhat redundant as GETs are not allowed by default. By adding the HttpPost attribute, however, you ensure that the method is not even available from GET requests (the controller doesn't expose the method to GET requests). Without the attribute the response to a GET will indeed by default fail, but any code up until your return statement would still be executed.

We've made a bit of a statement here about POST vs. GET, so let's talk security for a moment.

GETting your Data to the Client

Regardless of the platform, regardless of the browser, and regardless of the frameworks you are leveraging to build your site you should avoid using GET when working with sensitive data.

There are inherit risks you take when using GET, such as enabling "confused deputy" attacks, exposing parameters to your methods and leaving data behind in the browser cache.

In recognizing this, Microsoft set the default behaviour of a JsonResult to respond only to the HTTP POST verb.

Now, this is not to say that it makes it any more difficult to respond to GET verbs, in fact it is quite trivial to allow GET requests. So, if you are aware of the risks, you understand the implications of using GET or are otherwise required to use GET due to environmental factors and would like to request the data with a GET, you'll need to modify the above code slightly to get where you're going.

First, remove the HttpPost attribute so that GET calls will be available through the controller. Second, specify the AllowGet behaviour for the JsonResult. The revised code would look as follows:
public JsonResult GetOldThings(int minAge)
{
    IOldThingRepository repository = new OldThingRepository();
    return Json(repository.GetOldThings(minAge), JsonRequestBehavior.AllowGet);
}

For more information on some of the risks associated with Ajax GETs to fetch or modify data review this post by Phil Haack.

Using the JSON Serialized Data

We've made our request, processed the data based on the parameters provided by the request and returned the data in JSON notation. What do we do with it now?

In the code above we told jQuery that a function named ParseThingList would need to be called if the request was successful. Here's how that code would look:
// a method to parse the results of our JSON data
function ProcessListOfThings(data) {

$.each(data, function (i, item) { // build the text we want to see var displayString = item.ItemName + ' (' + item.YearsOld + ' years old)';

// add a new li to the ul on our page $("<li/>").html(displayString).appendTo("#old-thing-list"); });

// display the container of things $("#old-thing-container").slideDown(); };

We use the $.each method to iterate through the list of items that come back, passing each item into an anonymous method. We use the property names from our .NET object (such as YearsOld) to build a display string, which we add to our list.

Adding the item to the list uses a little bit of syntactic sugar, so let's break that line of code down: Image
  1. We create a new LI element
  2. We set the text of the LI to the display string we've created
  3. We add the LI to the list with an ID of "old-thing-list"

Finally, our function slides the list into view so that the user can see the results. Image

Try Me!

Wrapping Up

JSON notation provides a standard way to describe data in a terse format that is not tied to any particular library. Data served up by developers who use ASP.NET MVC can properly deliver that data, and jQuery provides a mechanism to request and process it on the client.

About the Author

James Chambers is a Senior Software Developer in Canada, where he tirelessly attempts to disprove the "no two snowflakes are alike" theory. His development passions are fueled by new tech, new tools and mentoring others. Follow his coding adventures at Mister James.