Friday 3 July 2009

Asynchronous Posting with ASP.NET, JQuery and Ajax

This is much easier in ASP.NET MVC (or at least I thought so), but I’m not currently working on an ASP.NET MVC site but a, dare I say it, classic ASP.NET site.  No I don’t want to discuss that web forms and ASP.NET is old, I merely mean that the site I’m working on is a more regular style ASP.NET site.  The site would have been well suited to ASP.NET MVC had it been available when it first came to life, but none the less it’s what I’m working with and it’s far from painful.

However with the web forms way of working many of the existing pages make postback calls to the server.  This is a very easy way to work, but it’s not pretty.  We also tend to avoid server side controls and in particular the whole server side Microsoft Ajax Toolkit (which I’m thankful for) even though it would make much of this form posting more “pretty”.  So I figure the easiest way to get an asynchronous post done on the client side was to use jQuery and Ajax.  I love jQuery.

I had thought this would be a fairly standard thing to do, and it might be, however I found it hard to find accurate and useful information.  There are many many ways to do this. 

You could use a web service and just make a call to the web service with jQuery, however this application doesn’t implement any services yet so that seemed like something I didn’t want to do.

You can make a "[WebMethod]” and call the web method using the $.ajax object in jQuery, but as the call I wanted to make was from a user control I wanted the method to be removed from the aspx pages.  So I settled on a web handler, an ashx file.  There were already some of these in the application, so it was a sensible choice. 

JQuery

First the jQuery part.  This is very simple really.

   1: $.ajax({
   2:     url: "ReviewHandler.ashx",
   3:     data: {
   4:         name: $("#ReviewerName").val(),
   5:         location: $("#ReviewerLocation").val()
   6:     },
   7:     processData: true,
   8:     type: "POST",
   9:     beforeSend: function() { startSubmit(); },
  10:     complete: function() { submitComplete(); },
  11:     error: function(xhr, statusText, errorThrown) { alert(errorThrown); },
  12:     success: function(data) { submitSuccess(data); }
  13: });

I’ve found a few sites that suggested how to do this.  The biggest area of difference was in the data section.  I think this depends on the data type you’re going for, but in my case I’m after the most simple implementation so I’ve not specified one.  This format will place the name/value pairs into the query string.

Most of the sites I found showed the jQuery side, very few of them showed the implementation on the C# side.  I’ve created a generic handler called ReviewHandler.ashx.  By default it creates a ProcessRequest method (with weirdly placed braces in the template), and you’ll use this to process any requests to the handler.  Here’s mine:

   1: /// <summary>
   2: /// Process the Ajax request from the web form.
   3: /// </summary>
   4: /// <param name="context"></param>
   5: public void ProcessRequest(HttpContext context) 
   6: {
   7:     if (context.Request.RequestType.Equals("POST"))
   8:     {
   9:         context.Response.ContentType = "text/plain";
  10:  
  11:         string name = context.Request["name"];
  12:         string location = context.Request["location"];
  13:         
  14:         // Process the data.
  15:  
  16:         context.Response.Write("My Output");
  17:     }
  18: }

Of course I want to be secure so I’m only handling post methods, any get methods are ignored by the handler.  You could also implement a client side captcha as well if you are concerned about bots using your service, but I’m not going to cover that here.  If anyone happens to read this and has any suggestions, please let me know.  While this works really well, it’s a bit awkward having to investigate the query string to get the parameters and I’m SURE there is a better way.

No comments: