AJAX with jQuery and web services

In this post I will show you how you can use jQuery to call ASP.NET web services (.asmx). Some people prefer to use page methods, but I find it nicer to group all my AJAX-related calls in one web service. That service then serves as a fa├žade to the inner workings of the application. Web services normally output data as XML, but I’m going to use JSON because it plays nicely with JavaScript and is also more compact and thus performs better. I’ll walk you through these two basic steps and I’ll show you an example:

  1. Setup and configure the .asmx-web service.
  2. Setup a client function to call the web service.

But before I do all that I will just add a simple class that we can use as an example:

Public Class Person
    Public Property ID As Integer
    Public Property FirstName As String
    Public Property LastName As String
End Class

I haven’t included any data storage. For the moment let’s just assume we will be passing instances of this class and they get stored (somewhere).

1. Setup and configure the web service

First, go to your web app and add a new web service to your web application.

1. Adding a new web service called “ajaxservices.asmx”

As I mentioned earlier, we will be using JSON. In order to do so, we’ll have to modify our web service a little bit. I have removed the Hello world bit and added a method that will get me a person with a specific ID. The two lines are marked in yellow:

<System.Web.Script.Services.ScriptService()> _
<WebService(Namespace:="http://tempuri.org/")> _
<WebServiceBinding(ConformsTo:=WsiProfiles.BasicProfile1_1)> _
<Global.Microsoft.VisualBasic.CompilerServices.DesignerGenerated()> _
Public Class ajaxservices
    Inherits System.Web.Services.WebService

    <WebMethod()> _
    <Script.Services.ScriptMethod(ResponseFormat:=Script.Services.ResponseFormat.Json)> _
    Public Function LoadPerson(ID As Integer) As Person
        Dim p As New Person With {.ID = ID, .FirstName = "Kenneth"}
        Return p
    End Function
End Class

 

The first line tells the web service that it should allow the service to be called from script.

The second line tells the method that, instead of outputting XML it should format the response as JSON. Before sending the object back to the client, it will run it through the JavascriptSerializer.

2. Setup a client function to call the web service

When we are calling our web service there a few things we need:

  • Correctly set the content-type to JSON
  • Do a POST-request
  • Include data (This is necessary because jQuery doesn’t correctly set the content-type if we don’t send data)
  • The data is return as JSON, but it’s wrapped in an object. The reason for this is a security vulnerability. Phil Haack wrote a post about this: http://haacked.com/archive/2009/06/25/json-hijacking.aspx Anyway, we need to get our object out of there and parse it to an object. For some reason Microsoft decided to wrap it in a property called “d”.

To sum it up, here’s the method you will have to use which does all that:

$.ajax({type: "POST",
        url: "ajaxlientservices.asmx/GetPersonList,
        data: "{'ID': 1}",
        contentType: "application/json; charset=utf-8",
        dataType: "json",
        success: function (response) {
            var list = response.d;
            alert("got it!");
        },
        error: function (msg) {
            alert("Oops, something went horribly wrong");
        }
    });

There are some problems with this:

  • I have to pass in my data as a String.
  • I don’t want to type all of this every time I want to call a service.
  • I don’t want to do the parsing of object every time.

Let’s refactor this method so that it’s easy to call this. I will add this as an extension to jQuery.

First, let’s solve the “data as a String”-problem. In the second post of this series I added the json2.js file. This is where it comes in. json2 is a library for converting JSON-objects to strings. I have attached it to jQuery like this:

jQuery.stringify = JSON.stringify; // Connect JSON2 to jQuery

 

We can now use this to pass in JSON-objects and convert them automatically to Strings. Now let’s wrap all this in a nice function and attach it to jQuery as an extension. In my previous post I skipped the function “callAsmx” of extensions.js and here it is:

jQuery.callAsmx = function (method, data, onSuccess, onError) {
   var url = ASMX + method;
   return $.ajax({
        type: "POST",
        url: url,
        data: $.stringify(data),
        contentType: "application/json; charset=utf-8",
        dataType: "json",
        success: function (response) {
            if (typeof onSuccess == "function") {
                onSuccess(response.d);
            }
        },
        error: function (msg) {
            if (msg.status != 0) {
                if (typeof onGlobalError == "function") {
                    onGlobalError([msg], 
"Error while calling " + url, ERRORTYPE.error); } if (typeof onError == "function") { onError(msg); } } } }); };

Let’s go over a few things that I have added in this method:

  • Abstracting the URL. (Yellow)
    Since I’m grouping all of my AJAX into one web service, I have taken out .asmx-part and set it in a global variable (ASMX). Now you can just pass in the name of the method.
  • Automatic conversion of the data-parameter (Green)
    Using the json2 functionality (which I attached to jQuery) I convert the incoming JSON-object to a String before sending it to the web service
  • Response parsing (Orange)
    Before calling the success-method, I first parse the response and send only the wrapped object back to the success-method.
  • Error handling (Gray)
    Because we don’t want to handle all the generic error handling on a per-call basis, I have added some basic global error handling. Whenever a call fails we will check whether there’s a global error handler and if so we’ll call it. Also the passed in error and success methods are checked and called appropriately.

All right, now we are set up to call our first asmx web service.

3. Example

The nice thing about this setup is that the transition between .NET objects and JSON-object is completely transparent. This small little snippet show you how easy it is to call a web service.

 <script type="text/javascript">
$(document).ready(function () { $("#btnCall").click(onBtnCallClicked); }); function onBtnCallClicked() { $.callAsmx("LoadPerson", { ID: 1 }, onPersonLoaded); } function onPersonLoaded(Person) { alert("Loaded person " + Person.ID + " called " + Person.FirstName); } </script> <input type="button" id="btnCall" value="Call service" />

With the configuration setup it’s now very easy to seamlessly integrate jQuery and ASP.NET web services. Why would you still want to do a full POST when you are staying on the same page?

You can now hookup a pure HTML button, gather the data from the DOM and send it to .NET, the response comes back as a nice JSON-object and you update the DOM accordingly. In my opinion we’re using the correct technologies to do the correct things. JavaScript and jQuery are built to access the DOM and manipulate it. .NET is a powerful server-side language which can do all the business logic. Let’s use them both to their full strength.

Comments are closed.