Posts Tagged 'WCF'

Using JSONP with WCF and jQuery

In the new release of .NET 4, the WCF team has added support for JSONP.  There are many resource out on the internet about the need for JSONP, if you are reading this article I’m assuming your familar with the concept of JSONP.  Essentially, JSONP utilitzes the <script /> tag as a work around to the cross domain access limitations of web browsers.  This new feature is exposed as an CrossDomainScriptAccessEnabled setting on the WebHttpBinding, and as such is configurable through code or through configuration.

Download

The full source code is available for download from my website

This code requires the latest download of .NET 4 Beta 2 with Visual Studio 2010

Example

In this example we are returning a list of sample customers.  In a standard JSON service using the WebHttpBinding you would recieve this result:

http://localhost:65025/CustomersService.svc/GetCustomers

[{"Email":"bob@example.com","Name":"Bob"},
{"Email":"mark@example.com","Name":"Mark"},
{"Email":"john@example.com","Name":"John"}]

Now using the same service you can supply the optional callback parameter like this http://localhost:65025/CustomersService.svc/GetCustomers?callback=JsonpCallback, which would return the results as the first argument to a function call with a name equal to the one supplied in the query parameter.

JsonpCallback([{"Email":"bob@example.com","Name":"Bob"},
{"Email":"mark@example.com","Name":"Mark"},
{"Email":"john@example.com","Name":"John"}])

So, if you have a javascript function setup on the page, the function will be called successfully without violating the cross-site scripting exceptions.


function JsonpCallback(customers) {
     alert(cutomers.length);
}

WCF Service with CrossDomainScriptAccessEnabled

Creating the WCF Service with CrossDomainScriptAccessEnabled is the same as it would be for any other web enabled WCF service.  In our example we are exposing a simple CustomersService

[ServiceContract]
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
public class CustomersService
{
    [OperationContract]
    [WebGet(ResponseFormat = WebMessageFormat.Json)]
    public List GetCustomers()
    {
        return Customer.GetSampleData().ToList();
    }
}

The new JSONP feature is exposed via the WebHttpBinding.  The configuration for the CustomersService would looks like this:

<system.serviceModel>
  <behaviors>
    <endpointBehaviors>
      <behavior name="webHttpBehavior">
        <webHttp />
      </behavior>
    </endpointBehaviors>
  </behaviors>
  <bindings>
    <webHttpBinding>
      <binding name="webHttpBindingWithJsonP" crossDomainScriptAccessEnabled="true" />
    </webHttpBinding>
  </bindings>
  <services>
    <service name="ServiceSite.CustomersService">
      <endpoint address="" binding="webHttpBinding"
                bindingConfiguration="webHttpBindingWithJsonP"
                contract="ServiceSite.CustomersService"
                behaviorConfiguration="webHttpBehavior"/>
    </service>
  </services>
</system.serviceModel>

Notice that we’ve created a new bindingConfiguration for webHttpBindingWithJsonP, in this new binding configuration we’ve set the new property of crossDomainScriptAccessEnabled to true.  This enables the new callback parameter and under the covers attaches the JavascriptCallbackMessageInspector.  I’ve choosen to explicitly setup my binding configuration, but it should be noted that .NET 4 has created default configuration features, a sample of this is available for download with the WCF Samples for .NET 4 Beta2.

Consuming JSONP with jQuery

Now, consuming this JSONP endpoint with jQuery couldn’t be easier.  jQuery ships with an ajax convenience function called getJSON that accepts a url, data, and a callback function.  In the url property you can provide a ? following a query parameter and the ajax function will replace it with a dynamic function to handle the JSONP callback.  With that being said this is what the code to access the customers would look like.

// Get the JsonP data
$.getJSON('http://localhost:65025/CustomersService.svc/GetCustomers?callback=?', null, function (customers) {
    alert('Received ' + customers.length + ' Customers');
});

Conclusion

Many of the code samples above use an abridged version of the code in the sample, so for more detail you should download the source code above.  Additionally this article and samples are based on the .NET 4 Beta 2 product.  I’ll do my best to update the code and ensure everything is in order with the official release.

Apache Stonehenge Interoperability Presentation at the NYC .NET Dev User Group

I just finished my Apache Stonehenge interoperability demo at the NYC .NET Developer’s User Group meeting. Thanks to all that attended, we had a great time and some really good questions. Hopefully I’ve sparked some interested in the community about interoperability and the ability to connect multiple languages and platforms together using web services and WCF.

Downloads

As promised the slides from this evening’s presentation are available for download on my website.  If your downloading the slides please join the mailing list and let us know what you think.

http://www.bendewey.com/downloads/Apache-Stonehenge.pptx

Links

Also here are some of the key links from my presentation

LitWare Training sample application now available on MSDN Code Gallery

The WCF Team at Microsoft just posted their LitWare Training sample application (http://code.msdn.microsoft.com/litwaremashup) on the MSDN Code Gallery website.   The Litware Training application is a sample application using WCF and the WCF REST Starter Kit to build a “Mashup” web site.  LitWare Training is a fictitious training company that maintains registration for technical training courses.  The main selling point for this fictitious company is that it provides a rich, integrated user experience by incorporating multiple services that exist on the internet. 

Litware Training Screenshot

This sample application includes more products and services mashed together than any other application that I’ve seen.  Among the many services and products featured in this application are:

  • ASP.NET
  • Windows Communication Foundation (WCF)
  • WCF REST Starter Kit Preview 2
  • SQL Server 2008
  • Entity Framework
  • Unity
  • jQuery with AJAX
  • Silverlight
  • Virtual Earth
  • Live Search
  • Twitter
  • Facebook
  • Amazon
  • ATOM/RSS Feeds Viewer

At twentysix New York I worked very closely with Kent Brown from Microsoft on this reference application.  Please download the code, take a look, and leave me feedback on this blog if you have any questions.  Additionally, I will be producing a series of screencasts reviewing and demonstrating this application.  Please stay tuned to my blog for updates and links when those screencasts get posted.

Create SendAsync Convenience Extensions for the WCF REST HttpClient to GetAsync and PostAsync

I recently had the pleasure of speaking with some industry icons. We compared some RESTful jQuery code with the new HttpClient code from the WCF Rest Starter Kit Preview 2. The line by line comparison on the code was quite similar (the WCF REST team has done an excellent job with this API, I’m always amazed at how easy it is to use), the main difference was that the jQuery code was transmitting asynchronously. After our conversation, I decided to create these convenience extensions to give developers an API for using lambda expressions to call RESTful services asynchronously in .NET.

Download

In this application I use the jQuery code from my Intro to jQuery presentation and the Live Search WPF Application. The first method I wrote was the GetAsync extension, and after realizing how simple it was I created this entire Extension Library. Additionally, since all the code fit nicely into a single class I’m going to publish the code as a single cs file. As usual, I’m also including the Sample application for download.

HttpAsyncMethodExtensions.cs (12.1KB)

HttpClientExtensions Sample WPF Application (Compressed Zip, 13.1KB)

Code Comparison

The goal of this API was to mimic the jQuery AJAX code that I had previously written. Here is a actual ajax portion of the jQuery code that retrieves some google search results:

$(document).ready(function() {
	$('.getGoogle').click(function(e) {
		//  Prevent the event and Set Loading Message
		e.preventDefault();
		$('.results .noResults').html('Loading...');

		// Generate the google Url
		var googleUri = "http://www.google.com/search?q=" + $('.searchText').val();

		// Send Async GET call
		$.get(googleUri, {}, function(html) {

			// Parse result and create placeholder
			var google = $(html);
			var ul = $('<ul />');

			// find links from results
			$('.g .r .l', google).each(function() {

				// create the list item, generate the list item, and add it to the placeholder
				ul.append($('<li />')
					.append($(this).clone().removeAttr('onmousedown')) // this.clone() clones the google link
				);
			});

			$('.results').append(ul).find('.noResults').remove();
		});
	});
});

Using this jQuery code as a guide I created the usage code first:

private void Search_Click(object sender, RoutedEventArgs e)
{
	// Set Loading Message
	this.Items.Clear();
	this.Items.Add("Loading ...");

	// Generate Google Uri
	const string googleApiUrl = "http://ajax.googleapis.com/ajax/services/search/web?v=1.0&q={0}";
	var uri = string.Format(googleApiUrl, this.SearchText.Text);

	// Create Client and Send Asynchronous GET
	var client = new HttpClient();
	client.GetAsync(uri, (s, r) =>
	{
		// Clear Loading Message
		this.Items.Clear();

		// Parse Results
		var results = r.Response.Content.ReadAsJsonDataContract<GoogleResults>();

		// Find and add the results
		this.Items.AddRange(results.responseData.results.Cast<object>());
	});
}

I tried to keep the two samples consistent, and as you can see the HttpClient code is 5 lines smaller than its jQuery counterpart. Unfortunately, these samples are not identical implementations. For instance, one client is a web browser and the other is a WPF application. Additionally, both projects have additional code, behind the scenes. But since the goal was to create a similar API I think it works.

HttpClient Extension Methods

What you may not know, is that the HttpClient gains most of its leverage from extension methods. The core functionality of the HttpClient is in its Send method. In the existing API, the Get, Post, Put, Delete methods are extension methods which simple call Send. Using that same concept, here is a GetAsync extension method to the HttpClient:

public static class HttpAsyncMethodExtensions
{
	public static void GetAsync(this HttpClient client, string uri, EventHandler<SendCompletedEventArgs> completed)
	{
		// register callback
		client.SendCompleted += completed;

		// call SendAsync
		var message = new HttpRequestMessage(HttpMethod.GET.ToString(), uri);
		client.SendAsync(message);
	}
}

The HttpClientAsyncExtensions Library, that is downloadable above, contains the full implementation of these extension methods for SendAsync, GetAsync, PostAsync, PutAsync, DeleteAsync, and HeadAsync. There are also a few overloaded helper methods to avoid repeating code.

Conclusion

I think its great that we have the ability to choose between synchronous and asynchronous processing of remote calls. Unfortunately, the amount of code required to perform these tasks is often quite different.

We’ve all seen applications that block the UI thread while executing a long running task synchronously. I’m not sure if this is because of the tools or because of a lack of knowledge around asynchronous programming. Either way, developers often feel that asynchronous programming is difficult.

I’m hoping that these extension methods will show that this doesn’t have to be the case, and that we can actually make remote services calls asynchronously with very little code.

Contributing to the Apache StoneHenge Incubator Project

I’m currently following the Apache StoneHenge Project.   This is an Incubator project that demonstrates using WS-* Standards to interoperate between multiple platforms.  The flagship project is the StockTrader application which currently has an implementation where .NET, JAVA, and PHP can communicate using standard SOAP messages or encrypted SOAP messages. 

StoneHenge is a great project and since it is in this early phase of incubation they’re still looking for new members.  Below is some useful information for getting started.

Proposal

“The aim of the Stonehenge project is to develop a set of sample applications to demonstrate seamless interoperability across multiple underlying platform technologies by using currently defined W3C and OASIS standard protocols.”  Full proposal

Microsoft MSDN StockTrader

The Apache StockTrader application is a subset of MSDN StockTrader Project.  There is no need to install this, it’s just helpful to know that this project exists.

StoneHenge Links

Apache Links

jQuery Tab View using AJAX and WCF REST Service

In response to a question on StackOverflow Master Details using jQuery Tabs I wrote little sample app to demonstrate using jQuery Tabs and a WCF REST Service to create a Master Details view of Orders. I decided I’d also reference the solution here and give a little bit of an overview of how the Sample works.

Download

Sample Project: jQuery-AjaxTabView-Sample.zip (194KB)

Default.aspx

The Default page is basically a UI Tab setup with a ListView on the first tab.  The ListView contains a table of Orders with a simple Select link.  Notice that the select button is not an asp hyperlink control.  If you don’t need the extra code-behind or rendering of the user control I avoid them.  But, back to the Default Page.  On the second tab I have to layers one for loading and one for results.  The results tab is preloaded with the default message of Select an order.

The other major function of the page is in the jQuery Scripting, but I’ll get into that later.  First let me explain the service.

WCF Orders Service

With the release of the WCF REST Starter Kit its become very simple to create a service that returns some simple JSON results.   In this sample I have a single service called Service.svc (OrderService might have been a better name, next time…).  The service has a standard WebServiceHost2 Factory definition (which you can view by opening the actual Service.svc file) and a single Service.svc.cs code-behind.  The Service contains two methods one to return all Orders and one to return a single Order’s Details

[ServiceContract]
[ServiceBehavior(IncludeExceptionDetailInFaults = true, InstanceContextMode = InstanceContextMode.Single, ConcurrencyMode = ConcurrencyMode.Single)]
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Required)]
public class OrderDetailsService
{
    [OperationContract]
    [WebGet(UriTemplate = "", ResponseFormat = WebMessageFormat.Json)]
    public IEnumerable GetOrders()
    {
        // todo: replace with real implementation
        return Order.GetStubData();
    }

    [OperationContract]
    [WebGet(UriTemplate = "{orderId}", ResponseFormat = WebMessageFormat.Json)]
    public List GetOrderDetails(string orderId)
    {
        // todo: replace with real implementation
        var orders = Order.GetStubData();

        // todo: handle bad orderIds
        var order = orders.FirstOrDefault(o => o.OrderId == int.Parse(orderId));

        if (order == null)
            return null;

        return order.Details;
    }
}

You can access http://localhost:{port}/Service.svc to get the Orders as a JSON list, or you can access http://localhost:{port}/Service.svc/1 to get the OrderDetails as a JSON list for Order #1.

jQuery Scripts

Now that you have the WCF Service setup you need to have jquery connect to the service and render the data out when it receives the results.  The basic steps are that occur when the Select button is clicked are:

  1. Call preventDefault to stop the link
  2. Update the Tab2 UI to Loading
  3. Select Tab 2
  4. Parse the OrderId from the Hash of the link
  5. call jQuery $.getJSON('Service.svc/{orderId}', null, function(json) {  } );

When the you return from the getJSON call you need to:

  1. Check to determine that you got valid results
  2. Set error message if necessary
  3. Generate table of results
  4. Loop results creating a row for each result
  5. Reset UI to hide loading and show results

Now on to the actual script that handles this.  Keep in mind that all this code is inside a $(document).ready(), for the full implementation download the sample project.

$('.selectOrder').click(function(e) {
    e.preventDefault();

    //setup loading ui
    $('#tabs').tabs('select', 1);
    $('#tabs-2 .loading').show();
    $('#tabs-2 .results').hide().empty();

    var id = this.hash.replace("#Select_", "")

    $.getJSON("Service.svc/" + id, null, function(details) {
        details.length = details.length ? details.length : 0;
        if (details.length == 0) {
            $('#tabs-2 .results').append('<h3>No Order Details</h3>').show();
        }
        else {
            var table = $('<table />').attr('cellspacing', 0).attr('cellpadding', 4);

            var header = $(<tr />')
                .appendCell("Product")
                .appendCell("Quantity")
                .appendCell("Price")
                .appendCell("Cost")
                .addClass('header');
            table.append(header);

            $.each(details, function() {
                var row = $('<tr />')
                    .appendCell(this.Product)
                    .appendCell(this.Quantity)
                    .appendCell(this.Price)
                    .appendCell(this.Quantity*this.Price);
                table.append(row);
            });

            $('#tabs-2 .results').append(table).show();
        }

        $('#tabs-2 .loading').hide();
    });
});

Conculsion

I hope that you like this sample.  As with any full AJAX solution the real complication comes into play when we start trying to customize the design.  That being said I would recommend putting as much of the design into the css as possible and avoid putting to many styles in the javascript. 

Other things to note, this doesn't work cross domain, in order to do cross-domain json you need to use jsonp (JSON with Padding).   JSONP can be accomplished through the use of WCF Extensions which is not covered in this article, for more information see this msdn article and this msdn forum post.  jQuery supports jsonp; you would change the getJSON call to $.getJSON('Service.svc/1?callback=?'), where callback is the name of the querystring parameter expected by the service, and jquery would recongnize the callback=? and handle all the dirty work for you.  Finally, there is no exception handling in this code.  I just set the length to 0 if I don't find one.  WCF will actually return the Exception message in the json response.  The next iteration of this project would be to include exception handling in the results callback. 

Happy coding.



Follow

Get every new post delivered to your Inbox.