WCF, ASP.NET AJAX, and JavaScript Proxies

I spent this weekend tinkering around with the JSON messaging capabilities of WCF new in the .NET Framework 3.5 (Orcas). The object model is changing substantially between Beta1 and Beta2, and I think the changes make for an easier to use system.

To better understand the JSON messaging features of WCF, check out some of the general requirements they were built to:

1) Config-free deployment for JSON endpoints

2) ASP.NET AJAX developer experience consistent with ASMX endpoints

3) Give service developers the same WCF developer experience as WCF v1

I am sure there were more, but these were the big ones related to developer experience.

Now, lets look at some code. A good place to start is the contract.

The Service Contract

 [ServiceContract]
public interface IWCFAjaxService {
    [OperationContract]
    [WebInvoke(Method = "POST", UriTemplate = "ShowServerDate")]
    String ShowServerDate();
}

The only thing that is different in this contract from a WCF contract from WCF v1 is the presence of the WebInvoke attribute. Simply put (almost pun intended), this attribute indicates that the operation will be accessible via the HTTP verb indicated by the Method instance property. In this case, the HTTP verb is POST.

The Service Type

This is pretty straightforward, so I'll just show it for completeness:

 public class WCFAjaxService : IWCFAjaxService {
    public string ShowServerDate()    {
        return DateTime.Now.ToString();
    }
}

The SVC file

SVC files are an activation target for WCF services hosted in IIS. Since this example is showing a web page that calls a WCF service, IIS is the natural host. The svc file is simple:

 <%@ ServiceHost Language="C#" Debug="true" Service="WCFAjaxService" Factory="System.ServiceModel.Activation.WebScriptServiceHostFactory" %>

Notice the presence of the Factory part of the directive. This indicates that the ServiceHostFactory to be used is the WebScriptServiceHostFactory. This is a new type that ships with .NET Framework 3.5. It creates a ServiceHost that has the right endpoint (behaviors, binding, etc) that will work for AJAX integration.

The ASPX file

  1 <%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %>
 2 
 3 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 
 4                     Transitional//EN" 
 5                     "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
 6 <html xmlns="https://www.w3.org/1999/xhtml">
 7 <head id="Head1" runat="server">
 8     <title>WCF Ajax Demo</title>
 9 
10     <script type="text/javascript">
11     
12       function GetServerTime(){
13         var proxy = new tempuri.org.IWCFAjaxService();
14         proxy.ShowServerDate(OnSucceeded, null, null);
15       }
16   
17       function OnSucceeded(result)
18       {
19         var RsltElem = document.getElementById("Results");
20         RsltElem.innerHTML = result;
21       }
22     
23     </script>
24 
25 </head>
26 <body>
27     <form id="form1" runat="server">
28     <div>
29         <asp:ScriptManager ID="scriptManager" runat="server">
30             <Services>
31                 <asp:ServiceReference Path="~/Service.svc" />
32             </Services>
33         </asp:ScriptManager>
34         <h2>
35             Server Time</h2>
36         <p>
37             Calling a service that returns the current server time.</p>
38         <input id="DateButton" type="button" value="GetTime" 
39                    onclick="GetServerTime()" />
40     </div>
41     <div>
42         <br />
43         <span id="Results"></span>
44     </div>
45     </form>
46 </body>
47 </html>
48 

The important parts of this code snippet are lines 29-33 (ScriptManager) and lines 12-15 (proxy call). In you are new to AJAX development, I encourage you to visit https://www.asp.net for more info.

The ScriptManager is the main integration point for web services and ASP.NET AJAX. Adding a Service node in the Services collection will create a JavaScript proxy, and you can all that JavaScript proxy from other functions in your page.

See the JavaScript Proxy

When I first tackled this, I could not get the proxy to generate, and I could not seem to find out the name of the proxy. The trick is to navigate to the svc url, then add a JS to the URL.

If your starting URL is https://localhost/WCFAjaxService/Service.svc, then the JavaScript proxy URL is https://localhost/WCFAjaxService/Service.svc/js. When you download that file, you'll see that the name of the proxy follows the naming convention of your service contract's XML namespace (hence tempuri.org in lines 12-15)

 The complete sample is below.

WCFAjaxDemo.zip