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.
Just what I was looking for, thanks!
awesome post, you save my days.
Hi:
This is a great code clip and article. Thanks for the publication. A great help.
Toraj
Can you give some pointers on how to translate the options into a self hosted version, say in the deployment below:
using (WebServiceHost serviceHost = new WebServiceHost(typeof(FactorNamesService), baseAddress))
{
WebHttpBinding whb = new WebHttpBinding();
whb.CrossDomainScriptAccessEnabled = true;
serviceHost.AddServiceEndpoint(typeof(INameListService), whb, “”);
serviceHost.Open();
Console.WriteLine(“Press to terminate service”);
Console.ReadLine();
serviceHost.Close();
}
haha,very good!Thanks
Thanks, Ben.
Just what I was looking for.
Great work Ben! Yours is the only sample I found which works!
Short and sweet post 🙂
I was trying this myself with the final release of .NET 4.0, but I was having no luck: crossDomainScriptAccessEnabled was apparently ignored altogether and regular JSON was being returned.
It took me a while to spot a difference: in analogy with your example, my endpoint address read “CustomersService.svc” instead of having the empty address like in your configuration. I got rid of it, and that did the trick.
this code is ok ,but if i want pass some params in url to server,405 not allowed happened.l
Thanks a lot for your excellent post, i have been messing with cross domain WCF Service Calling, and no other post could clearly explain the stpes involved. And ur code is the only code which i found successfully running. Two thumbs up
Thank you very much for this helpful post and code sample
The sample you provided works very well HOWEVER when I try to host on windows 7 iis the server service just doesn’t return anything and in fact if I try to navigate to the svc file I get the following..
“Security settings for this service require ‘Anonymous’ Authentication but it is not enabled for the IIS application that hosts this service.”
Any ideas on how to make this sample work while hosted in iis?
thx
Big thanks for the post, Ben! Helped me a lot!
I have been searching for this simple answer for days…
Thanks!!!
I just have one question: what was the reason for not adding a mex endpoint to your service?
This is a REST endpoint that returns JSON data. WSDL can’t be generated for this type of endpoint. Can I ask the opposite question, why do you need a MEX endpoint?
Thanks for the blog post man, it saved me from a day’s worth of research
finally i got a working example awesome dude!
Great Help, I became stupid to see that the getJSON was not working in firefox. Thank you for the blog post.
gr8 Post, finally i’ve overcome the cross domain issue. 🙂
thanks a lot!!!!
got the solutions which worked in all browser IE , Firefox, Goggle Chrome
your post helped me a lot, big thanks
Dude, that is an awesome post. I’ve been struggling with jsonp ajax call for few hours now and you saved me from further agony.
Thanks a lot!
Awesome, you got me most of the way there, after a couple hours of fruitless research. Just wanted to add that in addition to the code you posted, I needed this in my tag in the config:
Thanks so much!
Doh! Your comments don’t like XML tags.
authentication mode=”None”
…is what’s needed in the system.web tag
finally an up to date release about a microsoft product 🙂
This worked! Thanks for the post!
Love you man’ saved a lot of time