navigation
 Thursday, July 17, 2008

.NET 3.5 includes new abilities to easily leverage web services and Windows Communication Foundation (WCF) services from AJAX enabled web applications. For example, here is a new "ASP.NET Web Service Application" with a single GetMessage() method:

namespace WebServiceAjax { [WebService(Namespace = "http://Falafel.com/")] [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)] [ToolboxItem(false)] // To allow this Web Service to be called from script, // using ASP.NET AJAX, uncomment the following line. [System.Web.Script.Services.ScriptService] public class Service1 : System.Web.Services.WebService { [WebMethod] public string GetMessage() { return "Howdy"; } } }

Notice the attribute System.Web.Script.Services.ScriptService that allows the web service to be called from script. If you run the service itself as the startup page you get the usual service description banner page as expected.

   ws1

For extra fun, add "/js" to the url. Now you see a proxy written in JavaScript that knows how to talk with your web service. Note: You can also substitute "/jsdebug" for similar output that includes comments describing the available parameters.

ws2

How is this proxy used in your AJAX enabled web application? Microsoft AJAX applications have a ScriptManager component that include the basic infrastructure. In the ScriptManager Services collection, add a ServiceReference to your web service. In this example, the web page that acts as the client and the web service are in the same project, so the path to the web service is local.

<asp:ScriptManager ID="ScriptManager1" runat="server" > <Services> <asp:ServiceReference Path="Service1.asmx" /> </Services> </asp:ScriptManager>

Watch out: Don't add a reference to the ScriptManager Scripts collection. The reference to the service implicitly calls the web service with the /js to send the proxy to your application. You would receive an error due to the same objects being instantiated twice.

You also need a JavaScript function that uses the proxy. In our example a standard HTML button has an onClick event handler. The markup inside the form tags so far looks like this:

<asp:ScriptManager ID="ScriptManager1" runat="server"> <Services> <asp:ServiceReference Path="service1.svc" /> </Services> </asp:ScriptManager> <input id="Button1" type="button" value="button" onclick="JavaScript:clientClick();" />

Finally, the JavaScript function uses the proxy to make the web service call. Minimally, you need a reference to a function that gets called if the web service is successful. The next two optional parameters are the function to be called on failure and a user context parameter that can contain any arbitrary data you care to put in it.

<script type="text/javascript">

 
function clientClick()
  {
  
var service= new WebServiceAjax.Service1();
    service.GetMessage(onSuccess, onFailure,
"some context");
  }

 
function onSuccess(result, context){
    alert(result);
  
if (context!= null)
    {
      alert(context);
    }
  }
 
function onFailure()
  {
    alert(
"What we have here is failure to communicate.");
  }

</script>

When running the AJAX enabled web application in FireBug you can see that "jsdebug" is sent to the browser and that it contains our JavaScript proxy code. You may notice that our proxy will extend the Sys.Net.WebServiceProxy class. WebServiceProxy has some basic behaviors that allow a web service to be invoked, to define the web service path, success and failure callback properties, timeout and user context.

ws3

When you click the HTML button in the AJAX enabled web app, the alert box pops up with our "Howdy" message. Looking again at the FireBug "Net" tab, the "GetMessage" response shows up in JavaScript Object Notation (JSON) format. JSON, the default serialization format, is handy to work with and can be easily evaluated as a JavaScript object.

ws4

What if we have multiple parameters, how does the proxy signature change? If we change GetMessage() so the web method looks like this...

[WebMethod]
public string GetMessage(string name, int number)
{
  return "Name: " + name + "  Number: " + number.ToString();
}
 

...the proxy output with /jsdebug for the method changes to prepend the new parameters:

 

WebServiceAjax.Service1.GetMessage= function(name,number,onSuccess,onFailed,userContext) { /// <param name="name" type="String">System.String</param> /// <param name="number" type="Number">System.Int32</param> /// <param name="succeededCallback" type="Function" optional="true" mayBeNull="true"></param> /// <param name="failedCallback" type="Function" optional="true" mayBeNull="true"></param> /// <param name="userContext" optional="true" mayBeNull="true"></param> WebServiceAjax.Service1._staticInstance.GetMessage(name,number,onSuccess,onFailed,userContext); }
 

Call the new method signature from JavaScript simply by adding the parameters to the start of the parameter list:

 

function clientClick() { var service = new WebServiceAjax.Service1(); service.GetMessage("Falafel", 5, onSuccess, onFailure, "some context"); }
Calling WCF services follows a similar pattern, but there are a few twists to cover in another blog.
Name
E-mail
Home page

Comment (Some html is allowed: a@href@title, i, strike, u) where the @ means "attribute." For example, you can use <a href="" title=""> or <blockquote cite="Scott">.  

Enter the code shown (prevents robots):

Live Comment Preview