Thursday, November 6, 2014

Send and Receive JSON objects to Web Service Methods using jQuery AJAX in ASP.Net



In this article I will explain how to send and receive JavaScript JSON objects to Web Methods using jQuery AJAX in ASP.Net.
Custom Object Class
First I’ll create a simple property class of City which has two simple properties
1. Name – Name of the City
2. Population – Population of the City.
This class will act as the JSON object for sending and receiving date between the client and server.
C#
public class City
{
    private string name;
    public string Name
    {
        get
        {
            return name;
        }
        set
        {
            name = value;
        }
    }
 
    private int population;
    public int Population
    {
        get
        {
            return population;
        }
        set
        {
            population = value;
        }
    }
}
 

 
 
 
HTML Markup
<html xmlns="http://www.w3.org/1999/xhtml">
<head id="Head1" runat="server">
    <title></title>
    <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
   <script type="text/javascript" src="http://ajax.cdnjs.com/ajax/libs/json2/20110223/json2.js"></script>
    <script type="text/javascript">
        $("#btnCity").live("click"function () {
            var city = {};
            city.Name = "Mumbai";
            city.Population = 2000;
            $.ajax({
                type: 'POST',
                url: 'MyPage.aspx/GetCity',
                data: "{city:" + JSON.stringify(city) + "}",
                contentType: 'application/json; charset=utf-8',
                dataType: 'json',
                success: function (r) {
                    alert(r.d.Name);
                    alert(r.d.Population);
                }
            });
        });
    </script>
</head>
<body>
    <form id="form1" runat="server">
    <div>
        <input type="button" id = "btnCity" value="Get City" />
    </div>
    </form>
</body>
</html>
 
Above you will notice that on the click event of the HTML button btnCity I am making a jQuery AJAX call to the ASP.Net WebMethod GetCity which accepts a custom JSON object City with 2 properties (Name and Population). This function also returns a JSON object of type City with the same 2 properties (Name and Population).
 
Server side code
Below I have described the Web Methods that will process the requests received by the jQuery AJAX call.
C#
[System.Web.Services.WebMethod]
public static City GetCity(City city)
{
    return city;
}
 
The above Web Methods simply accept the object of class City and simply return it back to the client.
  1: [WebMethod]
   2: public void SendName(string firstName, string lastName)
   3: {
   4:     
   5: }

 1: $.ajax({
   2:   type: "POST",
   3:   url: "WebService.asmx/SendName",
   4:   data: "{'firstName':'Chris','lastName':'Brandsma'}",
   5:   contentType: "application/json; charset=utf-8",
   6:   dataType: "json",
   7:   success: function(msg) {
   8:   }
   9: });

[WebMethod] 
   2: public void SendValues(List<string> list)
   3: {
   4:     
   5: }
 1: var list = ["a", "b", "c", "d"];
   2: var jsonText = JSON.stringify({ list: list });
   3:  
   4: $.ajax({
   5:   type: "POST",
   6:   url: "WebService1.asmx/SendValues",
   7:   data: jsonText,
   8:   contentType: "application/json; charset=utf-8",
   9:   dataType: "json",
  10:   success: function() { alert("it worked"); },
  11:   failure: function() { alert("Uh oh"); }
  12: });

Handling Generic JSON objects in your WebMethods

Wouldn’t it be nice to call your AJAX method and just build a generic object to pass into the server side function, without having to create a bunch of complex server side objects?
So wouldn’t it be nice to call your AJAX method and just build a generic object to pass into the server side function, without having to create a bunch of complex server side objects? Something like:
cd.Methods.ListPeople({ limit: 100, sort: { field: 'age', order: 'asc'} }, OnResults);
or this:
cd.Methods.ListPeople({ limit: 100 }, OnResults);
So the implementation of ListPeople would be like so, notice I’m just passing the object to the server as astring. But I stringify’ed the generic object (don’t forget the single-quotes).
cd.Methods.ListPeople = function (opts, callback) {
    cd.Ajax.Method("ListPeople"
                 , "{'options': '" + JSON.stringify(opts) + "'}"
                 , callback);
};
The implementation of cd.Ajax.Method is just a simple wrapper around the jQuery AJAX call.
cd.Ajax.Method = function (m, d, c) {
    $.ajax({
           type: "POST"
           , url: "/WebServices/WebMethods.aspx/" + m
           , contentType: "application/json; charset=utf-8"
           , data: d
           , dataType: "json"
           , success: function (msg) { c(msg.d); }
           , error: function (msg) { cd.Ajax.AjaxFailed(msg); }
    });
};
The cd.Methods.ListPeople function will hit the ListPeople server function. Notice I take the options and pass it to my function JsonToDictionary. Then I try to pull the limit variable and the sort dictionary out of the resulting dictionary.
[WebMethod]
public static List<Person> ListPeople( string options )
{
   var opts = JsonToDictionary(options);
 
   var limit = (opts.ContainsKey("limit")) ? Convert.ToInt32(opts["limit"]) : 0;
   if(opts.ContainsKey("sort"))
   {
      var s = opts["sort"] as Dictionary<string, object>;
 
      if (s != null)
      {
         var field = (s.ContainsKey("field")) ? s["field"].ToString() : "name";
         var order = (s.ContainsKey("order")) ? s["order"].ToString() : "desc";
         return ListPeopleBll(limit, field, order);
      }
   }
 
   return  ListPeopleBll(limit);
}
Here is the implementation of JsonToDictionary. Yet again something that I have wasted so much time trying to figure out is actually quite simple. You have to add the using clause for theSystem.Web.Script.Serialization assembly to get JavaScriptSerializer. Notice that no matter what happens, I will pass a dictionary back and not null. This makes checking for key/value pairs in subsequent code much nicer!
private static Dictionary<string, object> JsonToDictionary(string json)
{
   try
   {
      var js = new JavaScriptSerializer();
      var d = js.Deserialize<Dictionary<string, object>>(json);
      if (d != null)
         return d;
      // I want to return an empty dictionary if the json results in null.
      return new Dictionary<string, object>();
       
   }
   catch
   {
       return new Dictionary<string, object>();
   }        
}

Passing JavaScript object to ASP.NET web service or web method

I recently came across a question on StackOverflow, where the author was having trouble calling a JSON based web service from his ASPX page using jQuery. He was passing a user defined JavaScript object. I decided that I would quickly put a project together describing how to do so, for my future reference, and for anyone else who needs help.  Here is my original answeron StackOverflow. I’ll be offering a higher level of explanation here in the post.
Below is the web method that we’ll be calling, in my ASPX page code behind. Note that a web method has to be declared as static,
1
2
3
4
5
6
7
    [System.Web.Services.WebMethod]
    public static Contact getContact(Contact cnt)
    {
        cnt.name = "Abijeet Patro";
        cnt.phone = "Blah Blah";
        return cnt;
    }
The user defined object that you pass through JavaScript has to have the same properties as the user defined object on the server. Say for example that you were passing the following from JavaScript -
1
var cnt = {name:'Hello',phone:'Hello'};
The object we defined in JavaScript has two properties, name and phone in lower case letters.
This is exactly similar to the class defined on the server -
1
2
3
4
5
public class Contact
{
    public string name { get; set; }
    public string phone { get; set; }
}
Note that the properties in the class have to be public
Now we’ll see how to call this web method from our ASPX page,
1
2
3
4
5
6
7
8
9
10
11
12
13
    $(document).ready(function () {
        var cnt = {name:'Hello',phone:'Hello'};
        $.ajax({
            type: "POST",
            url: "/Default.aspx/getContact",
            contentType: "application/json; charset=utf-8",
            dataType: "json",
            data: JSON.stringify({'cnt':cnt}), // Check this call.            success: function (data) {
                debugger;
            }
        });
    });
For an explanation of the options used here check jQuery ajax API documentation,
I’ll be discussing two noteworthy things,
  1. data and JSON.stringify:- Before we send the object to the web method, we have to ensure that we convert the object into a JSON format. We can do this by calling JSON.stringify.This javascript method is supported in all modern browsers*. The values that you pass toJSON.stringify have to be similar to what I have specified here. The name of the object we are passing to the server is named as 'cnt' in single or double quotes. This also has to be exactly same as the variable name being accepted by the web method.
    public static Contact getContact(Contact cnt)
  2. url:- The url specifies the web method or web service that we wish to call. If we were calling an ASP.NET based web service, we’d just have to change the url to/Default.asmx/getContact. Note that the name of the method that we wish to call is concatenated to the end of the web service path.
Now let’s see how to monitor our network traffic using a nifty tool called
Webservice
    public static Contact getContact(Contact cnt)
    {
        cnt.name = "Abijeet Patro";
        cnt.phone = "Blah Blah";
        return cnt;
    }
JavaScript/jQuery
    $(document).ready(function () {
        var cnt = {name:'Hello',phone:'Hello'};
        $.ajax({
            type: "POST",
            url: "/Default.aspx/getContact",
            contentType: "application/json; charset=utf-8",
            dataType: "json",
            data: JSON.stringify({'cnt':cnt}), // Check this call.
            success: function (data) {
                debugger;
            }
        });
    });
Class
public class Contact
{
    public string name { get; set; }
    public string phone { get; set; }
}

No comments:

Post a Comment