Using JSONP in ASP.NET MVC

Introduction

For security reasons browsers don't allow cross-domain communication. However, in some legitimate situations cross-domain communication becomes necessary. A common work-around for this restriction is to use JSON with Padding or JSONP. Using JSONP, you return data to a caller embedded in a script. In this article you will learn how JSONP can be used in an ASP.NET MVC application.

Understanding JSONP

Before you actually go into the code level details of using JSONP in ASP.NET MVC, let's see how JSONP works. Consider that you have two domains, website1.com and website2.com. A page from website1.com wants to retrieve some data from a resource belonging to website2.com. If the page and the resource would have been part of the same web site, you could have easily make an Ajax request using $.ajax() or jQuery or XMLHttpRequest object. However, since the page and the resource belong to two different web sites, the browser won't allow such communication due to possible security threats.

Though browsers are reluctant to make cross-domain requests, they happily allow certain HTML tags to point to cross-domain resources. The HTML tags such as <script>, <img> and <iframe> can point to resources outside their current domain using the src attribute. So, you can point a <script> tag to a remote resource that processes and returns some data to your page. However, merely using the <script> tag to point to the remote resource is not of much use because even though the remote resource returns data, the data is merely embedded in the page. You cannot access this returned data for some meaningful purpose.

In JSONP, the remote resource doesn't return plain data to the caller. It returns the data by wrapping it in a JavaScript function call. The JavaScript function name is usually supplied by the caller. The page making the request contains that function. Just to make this concept clear, consider the following example.

Let's say you wish to return data from a remote resource in this form:

{"CustomerID" : "ALFKI", "Country" : "USA"}

The calling page from website1.com will initiate request to the remote resource like this:

http://www.website2.com/dataprocessor?callback=MyCallbackFunction

The remote resource (dataprocessor) will process the request and will return the data as follows:

MyCallbackFunction("{"CustomerID" : "ALFKI", "Country" : "USA"}");

The calling page will have MyCallbackFunction() defined somewhere that will be invoked by the browser.

function MyCallbackFunction(data)
{
  //process data further
}

As you can see from the above example, JSONP uses JSON data and pads it with some script to make it a function call.

Creating an ASP.NET MVC Application that Returns Data

Now, that you know what JSONP is and how it works, let's develop an ASP.NET MVC application that returns data to the caller. This application represents the remote resource and consists of a controller named Home. The Home controller contains an action method named GetData(). The GetData() method is shown below:

[HttpGet]
public JsonpResult GetData(string id)
{
    NorthwindEntities db = new NorthwindEntities();
    var data = from item in db.Customers
                select new { CustomerID=item.CustomerID,Country=item.Country };
    JsonpResult result = new JsonpResult(data.SingleOrDefault());
    return result;
}

The GetData() method accepts one string parameter - id - that represents a CustomerID. The return type, if GetData() method, is JsonpResult. The JsonpResult is a custom action result class derived from the inbuilt JsonResult class. You will develop the JsonpResult class shortly. Inside, the GetData() method retrieves a Customer from the Customers table of Northwind database. The Customers table contains many columns but the code returns only CustomerID and Country columns. The Customer data is converted into JSONP format using the JsonpResult class and then returned to the caller.

The JsonpResult class used in the above code is shown next.

public class JsonpResult : JsonResult
{
    object data = null;

    public JsonpResult()
    {
    }

    public JsonpResult(object data)
    {
        this.data = data;
    }

    public override void ExecuteResult(ControllerContext controllerContext)
    {
        if (controllerContext != null)
        {
            HttpResponseBase Response = controllerContext.HttpContext.Response;
            HttpRequestBase Request = controllerContext.HttpContext.Request;

            string callbackfunction = Request["callback"];

            if (string.IsNullOrEmpty(callbackfunction))
            {
                throw new Exception("Callback function name must be provided in the request!");
            }
            Response.ContentType = "application/x-javascript";
            if (data != null)
            {
                JavaScriptSerializer serializer = new JavaScriptSerializer();
                Response.Write(string.Format("{0}({1});", callbackfunction, serializer.Serialize(data)));
            }
        }
    }
}

The JsonpResult class inherits from JsonResult. The JsonResult class is an inbuilt class provided by ASP.NET MVC and represents the data in JSON format. The parameterized constructor of the jsonpResult class accepts an object that represents the data to be wrapped in JSONP form. The ExecuteResult() method is where all the main logic goes. Notice the code marked in bold letters. The code first grabs a query string parameter named callback. This parameter will hold the name of the JavaScript function acting as a callback. Though you can use any name for the query string parameter, the commonly used parameter names are callback and jsoncallback.

The next "if" condition checks if the callback function name is supplied. If it's not then an exception is thrown since callback function is necessary for JSONP to work. The code then sets the ContentType property of the Response object to application/x-javascript because it returns a JSONP string as explained earlier. An instance of the JavaScriptSerializer is then created. The Serialize() method of the JavaScriptSerializer class serializes the supplied data after converting it to JSON format. Notice how the string format is provided while sending the JSON data back. The string.Format() method uses two placeholders and the resultant string will be a function call.

Creating an ASP.NET MVC Application that Consumes the Data

Now, let's create another ASP.NET MVC application that calls the GetData() action method developed earlier. The following code shows the Index view of the second application.

<script>
function MyCallback(data) {
    alert(data.CustomerID + " - " + data.Country);
  }
</script>

<script src="http://localhost:1044/home/GetData?id=ALFKI&callback=MyCallback"></script>

The above code contains a <script> block that defines a function named MyCallback(). This function acts as a callback for the JSONP request. The MyCallback() function simply displays the CustomerID and Country of the returned Customer object. Then a <script> tag is used to point to the GetData() action method developed earlier. The src attribute of the <script> tag points to the GetData action and passes two query string parameters viz. id and callback. The id query string parameter is supplied to the GetData() method whereas the callback parameter is used by the JsonpResult class discussed earlier.

If you run the Index view of the client application you will get an alert box as shown below:

Index view of the client application

Using jQuery for Making JSONP Requests

Though the technique of invoking a JSONP request as illustrated in the preceding section worked as expected, it was a bit raw way of making JSONP requests. Luckily, jQuery offers an inbuilt way to use JSONP in your script. The $.ajax() and $.getJSON() method can be used to make JSONP requests on remote resources. The following code shows how they are used:

$.ajax({
  url: "http://localhost:1044/home/GetData",
  data: { id: 'ALFKI' },
  type: "GET",
  dataType: "jsonp",
  jsonp:"callback",
  success: function (data) {
    alert(data.CustomerID + " - " + data.Country);
  }
});

$.getJSON("http://localhost:1044/home/GetData?id=ALFKI&callback=?", function (data) {
  alert(data.CustomerID + " - " + data.Country);
});

The first piece of code shown above uses $.ajax() technique whereas the second piece of code uses $.getJSON() technique. While using the $.ajax() method, the dataType is specified as jsonp and the callback query string parameter is specified as callback using the jsonp option. While using the above mentioned jQuery techniques you need not specify a callback function name while making a JSONP request. This is because jQuery automatically creates a random function and sends along with the request. The returned data is processed by the success handler function of the respective calls. So, the code that you put inside MyCallback() function now resides inside the success handler functions of $.ajax() and $.getJSON() methods.

If you run the Index view after adding this markup, you will get the same results as in the previous run.

Summary

Browsers don't let you make cross-domain requests due for security reasons. JSON with Padding or JSONP provides a work-around that allows you to make cross-domain requests and return script rather than data. While making a JSONP request you supply a callback function name in the query string. The remote resource then returns a script equivalent to the function call and passes the data to the function as a parameter. Using JSONP you can achieve cross-domain communication in legitimate scenarios.

 



Related Articles

Downloads

Comments

  • Simply Great

    Posted by naresh on 08/11/2014 01:52pm

    Awesome. Very very useful information.

    Reply
  • Awsome

    Posted by Ravi Gupta on 06/11/2014 06:22am

    Was banging my head from past few hours and then reached here. Thanks a lot.

    Reply
  • Works a treat!

    Posted by Damian on 05/08/2013 05:19am

    Fantastic tutorial, works a treat (even in Visual Studio 2010). Thanks for sharing

    Reply
  • Testing with Visual Studio

    Posted by Frank on 11/09/2012 05:49pm

    This code does not work in Visual Studio 2010.

    Reply
  • Testing with Visual Studio 2010

    Posted by Frank on 11/09/2012 05:48pm

    This code does not work in Visual Studio 2010.

    Reply
  • seo

    Posted by ali on 11/05/2012 04:22am

    It’s a really very informative information. It’s very useful and knowledgeable for me. i was stuck while coding this. I will bookmark this page for coding help. http://www.thesmsportal.com/

    Reply
  • INFORMATIVE POST

    Posted by Anky on 08/30/2012 12:35am

    Great work. I am highly obliged that you are sharing such info with us. I would appreciate if you will post on daily basis and that too with good typical info which i didn't get from anywhere. Being an ASP.net aspirant at http://www.wiziq.com/course/57-fresher-training-projects, I really appreciate your work

    Reply
Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • Live Event Date: October 29, 2014 @ 11:00 a.m. ET / 8:00 a.m. PT Are you interested in building a cognitive application using the power of IBM Watson? Need a platform that provides speed and ease for rapidly deploying this application? Join Chris Madison, Watson Solution Architect, as he walks through the process of building a Watson powered application on IBM Bluemix. Chris will talk about the new Watson Services just released on IBM bluemix, but more importantly he will do a step by step cognitive …

  • A modern mobile IT strategy is no longer an option, it is an absolute business necessity. Today's most productive employees are not tied to a desk, an office, or a location. They are mobile. And your company's IT strategy has to be ready to support them with easy, reliable, 24/7 access to the business information they need, from anywhere in the world, across a broad range of communication devices. Here's how some of the nation's most progressive corporations are meeting the many needs of their mobile workers …

Most Popular Programming Stories

More for Developers

Latest Developer Headlines

RSS Feeds