To read the article online, visit http://www.4GuysFromRolla.com/articles/111710-1.aspx

Accessing Server-Side Data from Client Script: Using WCF Services with jQuery and the ASP.NET Ajax Library

By Scott Mitchell


Introduction


Today's websites commonly exchange information between the browser and the web server using Ajax techniques - the browser executes JavaScript code typically in response to the page loading or some user action. This JavaScript makes an asynchronous HTTP request to the server. which then processes the request and, perhaps, returns data that the browser can then seamlessly integrate into the web page. Two earlier articles - Accessing JSON Data From an ASP.NET Page Using jQuery and Using Ajax Web Services, Script References, and jQuery, looked at using both jQuery and the ASP.NET Ajax Library on the browser to initiate an Ajax request and both ASP.NET pages and Ajax Web Services as the entities on the web server responsible for servicing such Ajax requests.

This article continues our examination of techniques for implementing lightweight Ajax scenarios in an ASP.NET website. Specifically, it examines how to use the Windows Communication Foundation, or WCF, to serve data from the web server and how to use both the ASP.NET Ajax Library and jQuery to consume such services from the client-side. Read on to learn more!

A Brief Primer on the Windows Communication Foundation


Throughout this article series we've been examining ways to access server-side data from client-side script. In Part 1 the server-side data - namely category and product information from the Northwind database - was exposed by an ASP.NET page. Specifically, the ASP.NET page's Page_Load event handler examined the requested URL to determine whether the requestor wanted category information or product information. It then returned the requested data as a JSON-formatted string. In Part 2 we exposed the server-side data using an Ajax Web Service. With the Ajax Web Service, we didn't need to write any code to parse the incoming URL or to format the outgoing markup into JSON - that was handled for us by the .NET Framework. Instead, we focused on writing the code to retrieve and return the data of interest.

The Windows Communication Foundation, or WCF, is a large collection of classes in the .NET Framework designed to assist developers in building connected, service-oriented applications, and was added to the .NET Framework in version 3.0. WCF is used to build services, which are programs that reside at a particular endpoint and can be invoked by a client application. Typically, the endpoint for a WCF service is a URL like http://www.yourserver.com/ServiceName.svc. Clients that wish to communicate with the service would send a properly formatted message to the endpoint. Upon receiving this message, the service would execute its code and, perhaps, return data back to the client.

WCF services are a lot like Ajax Web Services in the sense that they allow us, the developer, to focus on implementing the service; we are alleviated from having to parse the incoming request and from deseriealizing the incoming inputs and serializing the output into JSON. WCF is a much more powerful communications framework than ASP.NET's .asmx Web Services we examined in Part 2. For example, recall that the Ajax Web Service we created in Part 2 did not return a native JSON representation of the category or product data returned. Instead, it included the type name of each category or product returned and wrapped these results into an object with a property named d. This customized format was the format expected by the ASP.NET Ajax Library, but when calling the Ajax Web Service using jQuery we had to jump through a few hoops to get everything to work. As we'll see momentarily, with WCF services you can specify whether to return the native JSON or whether to return the customized JSON format expected by the ASP.NET Ajax Library.

This article shows how to create the same server-side functionality implemented in Parts 1 and 2, but using a WCF service instead of an ASP.NET page or Ajax Web Service. We'll see how to consume a WCF service from the browser using both the ASP.NET Ajax Library and jQuery.

Adding a WCF Service To Your Website To Be Consumed By The ASP.NET Ajax Library


To add a WCF service to your website add a new item of type "AJAX-enabled WCF Service" (see the screen show below). For the demo (available for download at the end of this article) I named this AJAX-enabled WCF Service NorthwindFormatted.svc, adding it to the Services folder.

Add a WCF Service named Northwind.svc to your website.

The name of your WCF service - NorthwindFormatted.svc in my example - is the endpoint for the service. Because it is located in the Services folder, clients will access it by visiting http://www.mysite.com/Services/NorthwindFormatted.svc. The actual NorthwindFormatted.svc file serves as a placeholder of sorts - it does not contain any code. Rather, the service's code is located in a separate file named NorthwindFormatted.vb or NorthwindFormatted.cs and is where we define the methods that make up our service. At this point the code file should have the following code:

[ServiceContract(Namespace = "")]
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
public class NorthwindFormatted
{
   // To use HTTP GET, add [WebGet] attribute. (Default ResponseFormat is WebMessageFormat.Json)
   // To create an operation that returns XML,
   // add [WebGet(ResponseFormat=WebMessageFormat.Xml)],
   // and include the following line in the operation body:
   // WebOperationContext.Current.OutgoingResponse.ContentType = "text/xml";
   [OperationContract]
   public void DoWork()
   {
      // Add your operation implementation here
      return;
   }

   // Add more operations here and mark them with [OperationContract]
}

There are a number of attributes in this class and on its methods. The ServiceContract attribute defined at the class level indicates that this class represents a service contract for a WCF service; the OperationContract attributes defined on the class's methods indicate what methods of the class can be invoked by a client. The AspNetCompatibilityRequirements attribute defined on the class indicates that the WCF service should be allowed to access ASP.NET information, such as session state and the ASP.NET intrinsic objects (Request, Response, Server, etc.).

For now, clear out the DoWork method and add the following GetCategories and GetProductsByCategory methods. The code in these two methods is identical to that code presented in Part 2 of this article series - Using Ajax Web Services, Script References, and jQuery. The only difference here is that instead of using the WebMethod attribute (as we did with the Ajax Web Service), we instead use the OperationContract attribute.

[ServiceContract(Namespace = "")]
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
public class NorthwindFormatted
{
   [OperationContract]
   public CategoryDTO[] GetCategories()
   {
      using (var dbContext = new NorthwindDataContext())
      {
         var results = from category in dbContext.Categories
                       orderby category.CategoryName
                       select new CategoryDTO()
                       {
                          CategoryID = category.CategoryID,
                          CategoryName = category.CategoryName,
                          Description = category.Description
                       };

         return results.ToArray();
      }
   }


   [OperationContract]
   public ProductDTO[] GetProductsByCategory(int categoryId)
   {
      using (var dbContext = new NorthwindDataContext())
      {
         var products = from product in dbContext.Products
                        where product.CategoryID == categoryId
                        orderby product.ProductName
                        select new ProductDTO()
                        {
                           ProductName = product.ProductName,
                           QuantityPerUnit = product.QuantityPerUnit,
                           UnitPrice = product.UnitPrice,
                           Discontinued = product.Discontinued
                        };

         return products.ToArray();
      }
   }
}

When you added the AJAX-enabled WCF Service to your website, Visual Studio added not only the NorthwindFormatted.svc and NorthwindFormatted.svc.cs (or NorthwindFormatted.svc.vb) files, but also modified your application's Web.config file, adding a <system.serviceModel> element with a mess of configuration information. You can optionally remove this configuration markup by adding a Factory attribute to the .svc file's <%@ ServiceHost %> directive. Personally, I prefer removing this configuration and using the Factory attribute and have done so in the demo application. To follow along on your application, open Web.config and remove the entire <system.serviceModel> element (which was just added by Visual Studio when adding the WCF service). Next, open the NorthwindFormatted.svc file and add the following Factory attribute to the <%@ ServiceHost %> directive like so:

<%@ ServiceHost Language="C#" Debug="true" Service="NorthwindFormatted"
                CodeBehind="~/App_Code/NorthwindFormatted.cs"
                Factory="System.ServiceModel.Activation.WebScriptServiceHostFactory" %>

Calling the WCF Service Using the ASP.NET Ajax Library


Part 2 of this article series examined how to call a server-side Ajax Web Service from a browser using the ASP.NET Ajax Library. In short, the ASP.NET Ajax Library creates a JavaScript proxy class that can be called from the script in the web page. Invoking the proxy class's methods sends an asynchronous HTTP request to the server and a specified function is executed once the response is received.

Calling a WCF service from the browser using the ASP.NET Ajax Library involves nearly the same steps as calling an Ajax Web Service. First, we need to create the proxy class. This is accomplished by adding a ScriptManager control to the web page and adding a script reference to the WCF service like so:

<asp:ScriptManager ID="ScriptManager1" runat="server">
   <Services>
      <asp:ServiceReference Path="pathToWCFService" />
   </Services>
</asp:ScriptManager>

Note: If you have a ScriptManager already defined in your master page you can either add the script references to that ScriptManager or, better yet, you can add a ScriptManagerProxy control to your ASP.NET page and define the services there.

This addition causes the ScriptManager to automatically generate a JavaScript proxy class and make it accessible to the page. To call the WCF service from JavaScript you simply enter the fully qualified type of the Web Service (such as NorthwindFormatting or, if you have placed the Web Service in a namespace, then Namespace.NorthwindFormatting), passing in any parameters. The proxy class calls the service asynchronously, meaning that you need to provide a JavaScript function that will be called once the WCF service call completes and returns a result. It is from this function that you'll update the page's display to incorporate the information returned by the service. (You can also specify a function to call if the service call resulted in an error.)

The JavaScript for populating the drop-down list with the set of categories follows. We start by calling the NorthwindFormatting.GetCategories method, specifying the function to execute when the response returns as the first parameter of this method. This "on success" function is passed the data returned by the WCF service, which we then enumerate using jQuery's $.each function, adding a new <option> element to the drop-down for each category returned by the service.

// Populate the categories DDL
NorthwindFormatted.GetCategories(
   function(data) {
      $.each(data, function (index, elem) {
         // Create a new <option>, set its text and value, and append it to the <select>
         $("<option />")
         .text(elem.CategoryName)
         .val(elem.CategoryID)
         .appendTo("#categories");
      });
   }
);

As you can see, the above script is nearly identical to the script used when calling an Ajax Web Service. The only difference is that the WCF service proxy class is named NorthwindFormatted, whereas the Ajax Web Service proxy class was named NorthwindService. Other than that minute difference, the scripts are identical.

If you use a tool like Fiddler you can inspect the information exchanged between the client and the server. When calling the NorthwindFormatted.GetCategories function from script, the browser sends the following HTTP request (some headers have been removed for brevity):

POST http://localhost:3028/AccessDataFromScript3/Services/NorthwindFormatted.svc/GetCategories HTTP/1.1
X-Requested-With: XMLHttpRequest
Content-Type: application/json; charset=utf-8

Note that the request was made to NorthwindFormatted.svc/GetProductsByCategory. When the request arrives at the server, ASP.NET parses this URL and knows to invoke the GetProductsByCategory method in the NorthwindFormatted WCF service. Also note that this HTTP request uses the POST verb and sets the Content-Type header to application/json. As discussed in Part 2, this is the manner by which the ASP.NET Ajax Library's proxy classes make requests to the server, namely as POSTs with an appropriately specified Content-Type.

The response sent back to the browser from the server contains the following (abbreviated and formatted) JSON:

{
   "d":
      [
         {
            "__type":"CategoryDTO:#",
            "CategoryID":1,
            "CategoryName":"Beverages",
            "Description":"Soft drinks, coffees, teas, beers, and ales"
         },
         {
            "__type":"CategoryDTO:#",
            "CategoryID":30,
            "CategoryName":"Biscuits",
            "Description":"Tasty, tasty biscuits!!"
         },
         ...
      ]
}

Note how the JSON data is not a native representation of the returned type (namely, an array of CategoryDTO objects), but instead is an object with a single property (d) that is assigned an array of objects. Each object in the d array contains the serialized properties of the CategoryDTO class along with a __type property. As discussed in Part 2, this is the JSON format used to return data from an Ajax Web Service and it the format expected by the ASP.NET Ajax Library on the client-side.

Because the WCF service accepts requests in the format the ASP.NET Ajax Library's proxy class sends it - as a POST request - and because it returns the results using the customized JSON serialization - namely, the single object with a property d that contains the actual results - the ASP.NET Ajax Library can seamlessly consume such a WCF service. But what about jQuery? In Part 2 we saw how to use jQuery to call an Ajax Web Service and those same steps could be applied here to call the WCF service we just created. However, as we'll see momentarily, it is possible to create a WCF service that formats the data returned by the service as native JSON (rather than using the custom format expected by the ASP.NET Ajax Library).

Adding a WCF Service To Your Website To Be Consumed By jQuery


The WCF service we just created - NorthwindFormatted.svc - parses the incoming information and formats its output in such a way as to facilitate it being called by a proxy class created by the ASP.NET Ajax Library. Other JavaScript libraries, such as jQuery, are not designed to handle this custom format natively. As we saw in Part 2, in order to invoke an Ajax Web Service from jQuery and parse the results we need to write a bit more script than when calling a service that does not apply this custom formatting.

The good news is that it's quite easy to create a WCF service that accepts GET HTTP requests and natively formats the returned object into JSON (rather than creating a new object with the d property). Such a service can be called without any fuss from jQuery. The demo project available at the end of this article includes an additional WCF service in the Services folder named NorthwindNative.svc. This service was created in the same fashion as NorthwindFormatted.svc - namely, I added a new AJAX-enabled WCF Service to my website. As before, adding this service prompts Visual Studio to add a <system.serviceModel> element to Web.config, which I've deleted.

The NorthwindNative code file contains the exact same code as NorthwindFormatted code file with one important addition - a new attribute indicating how the GetCategories and GetProductsByCategory methods can be invoked from a client. Specifically, I've added a WebInvoke attribute that specifies two things: that the method will be invoked via a GET request and that the data should be returned as JSON (as opposed to XML).

public class NorthwindNative
{
   [OperationContract]
   [WebInvoke(Method="GET", ResponseFormat=WebMessageFormat.Json)]
   public CategoryDTO[] GetCategories()
   {
      ...
   }


   [OperationContract]
   [WebInvoke(Method = "GET", ResponseFormat = WebMessageFormat.Json)]
   public ProductDTO[] GetProductsByCategory(int categoryId)
   {
      ...
   }
}

Another difference is that in the NorthwindNative.svc file I've added a Factory attribute that references the class WebServiceHostFactory instead of WebScriptServiceHostFactory, which is what was used for the NorthwindFormatted service.

<%@ ServiceHost Language="C#" Debug="true" Service="NorthwindFormatted"
                CodeBehind="~/App_Code/NorthwindFormatted.cs"
                Factory="System.ServiceModel.Activation.WebServiceHostFactory" %>

And that's all there is to it!

Because these methods are now accessible via an HTTP GET you can "run" them by pointing your browser to Services/NorthwindNative.svc/MethodName. For instance, going to http://www.yoursite.com/Services/NorthwindNative.svc/GetCategories should return the following (formatted and abbreviated) JSON payload:

[
   {
      "CategoryID":1,
      "CategoryName":"Beverages",
      "Description":"Soft drinks, coffees, teas, beers, and ales"
   },
   {
      "CategoryID":30,
      "CategoryName":"Biscuits",
      "Description":"Tasty, tasty biscuits!!"
   },
   ...
]

The above payload is the native serialization of the CategoryDTO objects returned by the service. There's no custom formatting involving wrapping the returned objects in an object with a d property and adding a __type property to each CategoryDTO.

To call a method with input parameters, such as GetProductsByCategory, you specify the parameters as querystring values, like so: http://www.yoursite.com/Services/NorthwindNative.svc/GetProductsByCategory?CategoryID=categoryId. (There is a way to customize the URL pattern used to call the service and supply its input parameters; we'll examine how to make such customizations in a future article in this series.)

Calling the NorthwindNative.svc Service from jQuery


The JavaScript you need to write to invoke the NorthwindNative.svc service form jQuery is nearly identical to the script examined in Part 1. Namely, we use jQuery's $.getJSON function to make an HTTP request to the service and then execute script once the service responds with the results. The following snippet shows how to use jQuery's $.getJSON and $.each functions to make a request to NorthwindNative.svc/GetCategories and then add the results to the items in the categories drop-down list.

$.getJSON('Services/NorthwindNative.svc/GetCategories',
         function (data) {
            $.each(data, function (index, elem) {
               // Create a new <option>, set its text and value, and append it to the <select>
               $("<option />")
               .text(elem.CategoryName)
               .val(elem.CategoryID)
               .appendTo("#categories");
            });
         }
);

Download the demo to explore a complete working example of accessing the NorthwindFormatted.svc and NorthwindNative.svc WCF services using the ASP.NET Ajax Library and jQuery, respectively.

Happy Programming!

  • By Scott Mitchell


    Attachments:


  • Download the Demo Code Used in this Article

    Further Reading


  • Accessing Server-Side Data from Client Script: Accessing JSON Data From an ASP.NET Page Using jQuery
  • Accessing Server-Side Data from Client Script: Using Ajax Web Services, Script References, and jQuery
  • REST-Based Ajax Services with WCF in .NET 3.5
  • Article Information
    Article Title: Accessing Server-Side Data from Client Script: Using WCF Services with jQuery and the ASP.NET Ajax Library
    Article Author: Scott Mitchell
    Published Date: November 17, 2010
    Article URL: http://www.4GuysFromRolla.com/articles/111710-1.aspx


    Copyright 2014 QuinStreet Inc. All Rights Reserved.
    Legal Notices, Licensing, Permissions, Privacy Policy.
    Advertise | Newsletters | E-mail Offers