Geeks With Blogs
Amit's Blog Sharing Thoughts and Learning

Few days back one of my of ex-colleague called me to know what is the best platform of Ajax to work in VS2003 Project, One of his client wants to implement some Ajax features in his existing application . Is it Ajax.net, Prototype, jQuery or Dojo? When I replied him Asp.net Ajax 1.0, he seems bit confused.  Yes we can also use Asp.net Ajax for the older version of VS. However, we will not get the full set of features in those older environment. Let me list those features, which will not be available:

  • Cannot use Server Side Controls such as ScriptManager, UpdatePanel, UpdateProgress, AjaxControlToolkit etc.
  • Application Service such as Authentication, Profile will not be available.
  • PageMethod will not be available.
  • There will be no Client Side Proxy for the WebServices.
  • The Data will be always transmitted in Xml not in JSON.

Even those missing features we will still able to use rich set of API which includes:

  • Base Type Extension
  • Able to Send Request and consume Response to any http endpoint which we see will in later section.
  • Able to use Client Side Components, Extenders and Controls.
  • All other Client Side Library API except Sys.WebForms

Let us see how to consume a VS2003 Web Service in Asp Ajax Framework. First download the Microsoft AJAX Library which only contains the JavaScript files. Once downloaded add the MicrosoftAjax.js in your Web Project and then your pages where you want to implement Ajax. Next add a Web Service in your Web Project. For shake of the simplicity I will create some basic functions. First create a WebMethod which returns the Server DateTime like the following:

[WebMethod]
public string GetCurrentTime()
{
    return DateTime.Now.ToString();
}

Now lets see how to call this WebMethod from the JavaScript.

function getServerTime()
{
    var request = new Sys.Net.WebRequest();

    request.set_url('SimpleWebService.asmx/GetCurrentTime');
    request.set_httpVerb('POST');
    request.add_completed(onGetServerTimeComplete);
    request.invoke()

    $get('divTime').innerHTML = '';
}

function onGetServerTimeComplete(executor, eventArgs)
{
    if (executor.get_responseAvailable())
    {
        $get('divTime').innerHTML = executor.get_xml().documentElement.firstChild.nodeValue;
    }
}

First we are creating a Sys.WebRequest object and then we are setting the required properties and events such as the end point (The convention is WebServiceUrl/WebMethod), Http Method Post/Get and finally we are binding onComplete Handler. In the onComplete Handler we are getting the response from the WebRequest's Executor xml Property. The Executer is passed in the onComplete Handler and the xml property represents an XML DOM Document. You can get more info on WebRequest and Executor from these links WebRequest and Executor.

In this section we will see how to pass parameters in the WebRequest object when calling a WebMethod, For example if your WebMethod is like this:

[WebMethod]
public bool IsValidEmails(string emails)
{
    string[] emailArray = emails.Split(',');

    for (int i = 0; i < emailArray.Length; i++)
    {
        if ((!emailArray[i].Contains("@")) || (!emailArray[i].Contains(".")))
        {
            return false;
        }
    }

    return true;
}

You can call it in JavaScript like the following:

function isValidEmail()
{
    var requestBody = 'emails=' + $get('txtEmails').value;
    var request = new Sys.Net.WebRequest();

    request.set_url('SimpleWebService.asmx/IsValidEmails');
    request.set_httpVerb('POST');
    request.set_body(requestBody);
    request.get_headers()['Content-Length'] = requestBody.length;
    request.add_completed(onIsValidEmailComplete);
    request.invoke()

    $get('divResult').innerHTML = 'Loading';
}

function onIsValidEmailComplete(executor, eventArgs)
{
    if (executor.get_responseAvailable())
    {
        $get('divResult').innerHTML = executor.get_xml().documentElement.firstChild.nodeValue;
    }
}

The only difference this time comparing to first example is we are setting the body of the request where we are are passing the comma separated email addresses. If you have mulitple parameter then append it with & (Ampersand) character in the request body for example param1=value1&param2=value2 etc.

So far we have seen only intrinsic data type transfer, now lets check how to send and receive complex data types. Lets create a dummy WebMethod which returns an array of Employee object like this:

[WebMethod]
public Employee[] GetEmployees()
{
    ArrayList list = new ArrayList();

    for (int i = 1; i < 6; i++)
    {
        Employee emp = new Employee();

        emp.Name = string.Format("Employee Name #{0}", i);
        emp.Address = string.Format("Employee Address #{0}", i);
        emp.Salary = i * 10000;

        list.Add(emp);
    }

    return (Employee[])list.ToArray(typeof(Employee));
}

Now call this WebMethod from JavaScript like this:

function getEmployeeList()
{
    var request = new Sys.Net.WebRequest();

    request.set_url('SimpleWebService.asmx/GetEmployees');
    request.set_httpVerb('POST');
    request.add_completed(getEmployeeListComplete);
    request.invoke()

    $get('divList').innerHTML = 'Loading...';
}

function getEmployeeListComplete(executor, eventArgs)
{
    if (executor.get_responseAvailable())
    {
        var xndEmployees = executor.get_xml().documentElement.getElementsByTagName('Employee');

        if (xndEmployees)
        {
            var output = '';

            if (xndEmployees.length > 0)
            {
                for(var i = 0; i < xndEmployees.length;i++)
                {
                    var emp = new Employee(xndEmployees[i]);
                    output += emp.Name + ':' + emp.Address + ':' + emp.Salary + '<br/>'
                }
            }

            $get('divList').innerHTML = output;
        }
    }
}

function Employee(xndEmployee)
{
    this.Name = xndEmployee.getElementsByTagName('Name')[0].firstChild.nodeValue;
    this.Address = xndEmployee.getElementsByTagName('Address')[0].firstChild.nodeValue;
    this.Salary = parseFloat(xndEmployee.getElementsByTagName('Salary')[0].firstChild.nodeValue);
}

The real difference between handling the complex object is that we have to roll our own logic converting to custom object from the xml response like the above.

In this section we will check how to send a complex object in Asp.net Ajax. Lets create another dummy method which takes an employee object and returns a new id for that employee, like this:

[WebMethod]
public int CreateEmployee(Employee employee)
{
    //Store it in DB
    int id = (new Random()).Next(1000, 10000);
    return id;
}

Now lets see how to call this method in JavaScript:

function createEmployee()
{
    var requestBody =   '<?xml version=\"1.0\" encoding=\"utf-8\"?>' +
                        '<soap:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">' +
                          '<soap:Body>' +
                            '<CreateEmployee xmlns=\"http://tempuri.org/\">' +
                              '<employee>' +
                                '<Name>' + 'Joe Doe' + '</Name>' +
                                '<Address>' + 'Nowhere' + '</Address>' +
                                '<Salary>' + '25000' + '</Salary>' +
                              '</employee>' +
                            '</CreateEmployee>' +
                          '</soap:Body>' +
                        '</soap:Envelope>';

    var request = new Sys.Net.WebRequest();

    request.set_url('SimpleWebService.asmx');
    request.set_httpVerb('POST');
    request.set_body(requestBody);
    request.get_headers()['Content-Length'] = requestBody.length;
    request.get_headers()['SOAPAction'] = 'http://tempuri.org/CreateEmployee';
    request.get_headers()['Content-Type'] = 'text/xml; charset=utf-8';
    request.add_completed(onCreateEmployeeComplete);
    request.invoke()

    $get('divID').innerHTML = 'Loading..';
}

function onCreateEmployeeComplete(executor, eventArgs)
{
    if (executor.get_responseAvailable())
    {
        var xndResult = executor.get_xml().documentElement.getElementsByTagName('CreateEmployeeResult');

        $get('divID').innerHTML = xndResult[0].firstChild.nodeValue;
    }
}

As you can see there are quite bit of difference in this case, first we are constructing a Soap Message, next in the url we are not specifying the WebMethod name instead we are specifying the WebMethod name by adding a new header SOAPAction, we are also adding a new header for the request content type which is text/xml.

In conclusion, I would like to say that main advantage of implementing Asp.net Ajax Library in older VS projects is that we can easily employ our existing knowledge of Asp.net Ajax, no need to learn any new framework and later on If we decide to upgrade our project in VS2005 or maybe VS2008 we can easily do that without breaking a single line of code.

Download: Complete Code

kick it on DotNetKicks.com

Posted on Saturday, July 21, 2007 1:07 PM Asp.net Ajax , Visual Studio | Back to top


Comments on this post: Asp.net Ajax and VS2003

# re: Asp.net Ajax and VS2003
Requesting Gravatar...
One that wasn't mentioned is Magic Ajax, which I used extensively in the 1.1 world. Well worth checking out:

http://www.magicajax.net/

Travis
Left by Travis Laborde on Jul 23, 2007 5:03 PM

# re: Asp.net Ajax and VS2003
Requesting Gravatar...
Yes there are few other frameworks which I should mention such as Anthem.NET, MagicAjax, FastPage, ZumiPage etc.
Left by Kazi Manzur Rashid on Jul 23, 2007 5:19 PM

# re: Asp.net Ajax and VS2003
Requesting Gravatar...
I would like to know better solution from you. Actually the process of application should running on the client side

I have collected a bulk of data in the client side with array. is it possible to update in one shot. but i don't know how can i send the array to server side (c#). can explain me. I have 1000 of rows processed and collected in the client side (using javascript).

Now the data need to update in to the database in one shot. is it possible ?

i hope you , give me best solution !!

Regards
thittai.
Left by thittai on Sep 03, 2007 7:53 AM

# re: Asp.net Ajax and VS2003
Requesting Gravatar...
Good stuff,
Do you know how to get directly the JSON output instead of the xml doc ?
Left by Marco on Nov 19, 2007 3:21 AM

# re: Asp.net Ajax and VS2003
Requesting Gravatar...
The first example works fine when run as localhost but when deployed to a server or run from another workstation on the intranet, then executor is null.

when deployed to a web server, how does the client know where: request.set_url('WSLocations.asmx/GetLocationsXMLByID');
is located?

request.set_url('WSLocations.asmx/GetLocationsXMLByID');
request.set_httpVerb('POST');
request.set_body(requestBody);
request.get_headers()['Content-Length'] = requestBody.length;
request.add_completed(onGetLocationsXMLByIDComplete);
request.invoke()
Left by Ron on Dec 19, 2007 10:12 PM

Your comment:
 (will show your gravatar)


Copyright © Kazi Manzur Rashid | Powered by: GeeksWithBlogs.net | Join free