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.