Accessing ASP.NET Web Services with dojo.xhrGet
So I’ve been using the Dojo toolkit for a while now, but mainly for the Dijit and DojoX UI components. For the actual Ajax communication layer, I’ve been relying on the Microsoft Ajax framework because of it’s seamless integration with the ASP.NET Web Service model. Since I’ve got the whole mess of Dojo already being loaded into the browser, I figured I should drop the crutches, and work out how to work directly with the Dojo ajax framework.
The one downside of this is that you no longer get the client side proxies for your ASP.NET Web Services. Thus today’s article – how to directly access an ASP.NET JSON Web Service using dojo.xhrGet.
Part 1: Create a Web Service
This is pretty simple – just add a web service to your web site. I tend to put the code right in the asmx file, rather than in the code-behind in app_code, but that’s just personal preference.
<%@ WebService Language="C#" Class="ASPWebService" %> using System; using System.Web; using System.Web.Services; using System.Web.Services.Protocols; [WebService(Namespace = "http://tempuri.org/")] [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)] public class ASPWebService : System.Web.Services.WebService { [WebMethod] public string SayHello() { return "Hello to Dojo " + DateTime.Now.ToLongDateString(); } }
By default your web service will be configured to “speak” SOAP, which is fine if you are consuming it from another application, but for Ajax based browser apps, it’s much easier to work with JSON.
Part 2: JSON-ify the Web Service
This is actually really simple – just include System.Web.Script.Services, and the [ScriptService] attribute to the web service as shown below.
<%@ WebService Language="C#" Class="ASPWebService" %> using System; using System.Web; using System.Web.Services; using System.Web.Services.Protocols; using System.Web.Script.Services; [WebService(Namespace = "http://tempuri.org/")] [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)] [ScriptService] public class ASPWebService : System.Web.Services.WebService { [WebMethod] [ScriptMethod(ResponseFormat = ResponseFormat.Json, UseHttpGet=true)] public string SayHello() { return "Hello to Dojo " + DateTime.Now.ToLongDateString(); } }
We also add a [ScriptMethod] attribute to the WebMethod. We do this for two reasons – first, we want to specify that the response format should be JSON, and we also want to allow access to this method via http Get’s (this is disabled by default).
At this point you can hit the web service in your web browser, and get the standard Web Service browser. But if you also stick /js on the end of the url, you will get the client side Javascript that integrates with the MS Ajax Framework. But we’re trying to work with Dojo, so we’ll move on…
Part 3: Testing the Service in a Browser
Our simple “SayHello” web method does not take any arguments, so we should be able to just “GET” it via a browser.
The tricky bit that took me some time to sleuth down was that you also need to edit web.config to tell the web service to respond to all Gets and Posts. Add this section (just copy out the parts you are missing – do not paste this whole thing into your web.config or you will get an error!):
<system.web> <webServices> <protocols> <add name="HttpGet"/> <add name="HttpPost"/> </protocols> </webServices> </system.web>
Once you do this, you will get the response back. Despite the fact that we have used the [ScriptMethod] attribute to specify that the SayHello web method should return Json, this will only occur if you sent the request content-type to “application/json; charset=utf-8″. Without that, you’ll still get xml.
Part 4: Create a Simple Page
For this, I created about the simplest page I could – just a button and a div that will be updated. Here’s the whole page…
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title>Dojo to ASP.NET WebServices</title> <script type="text/javascript" src="http://o.aolcdn.com/dojo/1.1.1/dojo/dojo.xd.js" djConfig="parseOnLoad:true, isDebug:true"> </script> <script type="text/javascript"> function updateSampleOne(){ var contentNode = dojo.byId("sampleone"); dojo.xhrGet({ url: "./ASPWebService.asmx/SayHello", handleAs: "json", contentType: "application/json; charset=utf-8", load: function(data,args){contentNode.innerHTML = data.d;}, error: function(error,args){console.warn("error!",error);} }); }; </script> </head> <body> <h1>Using Dojo to Consume ASP.NET JSON WebServices</h1> <input id="btGetString" type="button" value="Update" onclick="updateSampleOne();" /> <div id="sampleone">This will update</div> </body> </html>
Breaking down the dojo code…
var contentNode = dojo.byId(“sampleone”);
This simply get’s a the div that we’ll be updating.
dojo.xhrGet({ url: "./ASPWebService.asmx/SayHello", handleAs: "json", contentType: "application/json; charset=utf-8", load: function(data,args){contentNode.innerHTML = data.d;}, error: function(error,args){console.warn("error!",error);} });
This is the actual ajax xhr request. Since we are using a GET, we are using dojo.xhrGet.
The Url of our web service is the asmx file followed by the name of the web method. Since it’s located in the same folder as this html file, we reference it as ./ASPWebService.asmx/SayHello.
The response will be json, so we set handleAs to json
We set the contentType to “application/json; charset=utf-8″ as per the ASP.NET security requirements.
When the response returns, we need to do something with it, this is where load comes in. Dojo uses anonymous functions a lot, and for a simple situation like this, it’s pretty easy to follow. The returned JSON is:
{“d”:”Hello to Dojo Tuesday, June 03, 2008″}.
So we set the contentNode.innerHTML is set to data.d
Should an error occur, the error function is called.
Summary:
So – while this is a little more convoluted than just using the MS Ajax client library and the Script Manager, it does save us from loading multiple client-side frameworks. Since I’m using Dojo for many other UI components, it seemed a waste to also drag along MS Ajax when this is a viable alternative.
One may ask why use the ASP.NET Web Services model? Well, from the server side it’s pretty easy to work with. Once a service is created you can access it via Json or SOAP. They are also easy to unit test.
I’ll likely extend this with some more complex examples – like submitting a form, or sending / receiving complex types, but I’ll leave it here for now.
aref said
this work fine. If i want to send an argument to web services page i get the status:500 error. Any thoughts. Thanks
chet said
When sending argument I get the 500 error too. Please share a solution if one is found.
Dave Bouwman said
Hey Dainghia – would you please not steal my content?
Everyone else – here’s the original article:
http://blog.davebouwman.com/index.php/2008/12/aspnet-mvc-and-dojo-dojoxhrpost-with-complex-objects/
Thanks
Dave