Does the new September build provide a way to work with JSONP?

Topics: jQuery, Web Api
Oct 24, 2011 at 7:43 AM
Edited Oct 24, 2011 at 7:43 AM

I need to be able to handle JSONP in my code but don't see away to do this. I found the article by Alex Z at http://blog.alexonasp.net/post/2011/07/26/Look-Ma-I-can-handle-JSONP-(aka-Cross-Domain-JSON)-with-WCF-Web-API-and-jQuery!.aspx which comes close but it doesn't seem to build properly with the new release. The question is, is there any native support for jsonp in the latest release? and if not, does anyone have any examples on how to get Alex's code to work with the new release?

Oct 24, 2011 at 11:51 AM

Please read this post 

http://wcf.codeplex.com/discussions/274789

Seems like the changes broke Alex's example, but that it's now part of the framework. My assumption is that if I get the latest code and build it I can use it directly from there, but that it's not in the current drop.

Coordinator
Oct 24, 2011 at 4:52 PM

JSONP is supported in the Web API Enhancements. Just grab the WebApi.All NuGet package and it should “just work” with JQuery calls.

Daniel Roth

From: elmerm [email removed]
Sent: Monday, October 24, 2011 12:44 AM
To: Daniel Roth
Subject: Does the new September build provide a way to work with JSONP? [wcf:276947]

From: elmerm

I need to be able to handle JSONP on my code but don't see away to do this. I found the article by Alex Z at http://blog.alexonasp.net/post/2011/07/26/Look-Ma-I-can-handle-JSONP-(aka-Cross-Domain-JSON)-with-WCF-Web-API-and-jQuery!.aspx which comes close but it doesn't seem to build properly with the new release. The question is, is there any native support for jsonp in the latest release? and if not, does anyone have any examples on how to get Alex's code to work with the new release?

Oct 24, 2011 at 5:38 PM

Thanks ssuing8825 and Daniel for the quick response. I do have the latest WebApi.All package (v 9/15/2011) but it does not "just work" for me. When I run the Test Client and append ?callback=myFunc1 to the URL, the JSON sent back is not JSONP. I did download the JsonpSample you linked to and that does work in the sample as well as in the Test Client. Could it be that I need to be using an MVC project? That's the only difference I saw between the sample and my project. Or do i need to download and build the latest source (meaning the WebApi.All package is outdated)?

Coordinator
Oct 24, 2011 at 5:46 PM

Sending a callback query parameter is not enough to get back JSONP. The implementation requires you to request application/javascript in the Accept header.

The reason for this is that padded JSON is not actually JSON. JSONP requests are typically made through the browser using the <script> tag and the browser will automatically use the right Accept header.

Daniel Roth

From: elmerm [email removed]
Sent: Monday, October 24, 2011 10:39 AM
To: Daniel Roth
Subject: Re: Does the new September build provide a way to work with JSONP? [wcf:276947]

From: elmerm

Thanks ssuing8825 and Daniel for the quick response. I do have the latest WebApi.All package (v 9/15/2011) but it does not "just work" for me. When I run the Test Client and append ?callback=myFunc1 to the URL, the JSON sent back is not JSONP. I did download the JsonpSample you linked to and that does work in the sample as well as in the Test Client. Could it be that I need to be using an MVC project? That's the only difference I saw between the sample and my project. Or do i need to download and build the latest source (meaning the WebApi.All package is outdated)?

Oct 24, 2011 at 6:08 PM

Understood, I am in fact specifying the header (Accept:application/json) in the Test Client and I do get back jsonp when I run the sample but I do not get back any jsonp when I run it in my ASP.NET Web Application project. If I make a call from jQuery, I get the following exception because the function is not returned in the json:

 

jQuery12612616261261261 was not called

 

For your reference, here is the code I am using:

// HelloWorldApi.cs
[ServiceContract]
	public class HelloWorldApi
	{
		[WebGet(UriTemplate = "hello")]
		public string GetHelloWorld()
		{
			return "Hello, World!";
		}
	}

// Global.asax.cs
public class Global : System.Web.HttpApplication
	{
		HttpServiceHostFactory _factory = null;

		protected void Application_Start(object sender, EventArgs e)
		{
			_factory = new HttpServiceHostFactory();
			WebApiConfiguration config = new WebApiConfiguration() { EnableTestClient = true };

			RouteTable.Routes.SetDefaultHttpConfiguration(config);
			RouteTable.Routes.MapServiceRoute<HelloWorldApi>("hello");
		}
	}

Coordinator
Oct 24, 2011 at 6:16 PM

Ah, right – the JSONP support is not actually in Preview 5. It was added to the prototype branch after Preview 5 shipped. My apologies for the confusion. You will need to build the prototype branch yourself to get this functionality.

How are you making the JQuery call? Did you including ?callback=? in the URI?

Daniel Roth

Oct 24, 2011 at 6:55 PM

I've built the latest source and updated the Microsoft.ApplicationServer.HttpEnhancements reference to point to this new build. I can now see jsonp being returned in the Test Client of my project. Woooohooo! 

I am calling the service via jQuery as follows:

<script type="text/javascript">
    	var apiUrl = "http://localhost:5000/hello/hello?callback=?";

    	$(function () {
    		$("#helloButton").click(function () {
    			$.getJSON(apiUrl, function (data) {
    				$("div").html(data);
    			});
    		});
    	});
    </script>

 

However, the problem now is that as Alex points out in his article, the getJSON method does not specify the proper application/jsonp header, it sends */* instead and my service is responding to the above call with an XML result instead of the JSONP result. Do I need to map/register something to tell the WebAPI system to treat everything as application/json?

Coordinator
Oct 24, 2011 at 7:46 PM

Which browser are you using? Can you send me a trace of the JQuery request?

Daniel Roth

Oct 24, 2011 at 8:32 PM

I am using both Google Chrome and Internet Explorer 9 and the latest jQuery version from Google CDN: https://ajax.googleapis.com/ajax/libs/jquery/1.6.4/jquery.min.js

The raw requests for each browser are as follows: 

Google Chrome:
GET http://localhost:5000/hello/hello?callback=jQuery16406169528239406645_1319488136935&_=1319488138433 HTTP/1.1
Host: localhost:5000
Connection: keep-alive
Referer: http://localhost:1000/test.html
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.1 (KHTML, like Gecko) Chrome/13.0.782.112 Safari/535.1
Accept: */*
Accept-Encoding: gzip,deflate,sdch
Accept-Language: en-US,en;q=0.8
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3
Cookie: mstcid=2e5554b3


Internet Explorer 9
GET http://localhost:5000/hello/hello?callback=jQuery16403814751366293632_1319488175908&_=1319488202304 HTTP/1.1
Accept: */*
Referer: http://localhost:1000/test.html
Accept-Language: en-US
User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; WOW64; Trident/5.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E; InfoPath.3; MS-RTC LM 8; Zune 4.7)
Accept-Encoding: gzip, deflate
Host: localhost:5000
Connection: Keep-Alive
Cookie: mstcid=2a4eea2d

Oct 26, 2011 at 2:28 PM

Any idea on how to work around this?

Coordinator
Oct 26, 2011 at 6:22 PM

Looks like you are correct that browsers generally send */* in the Accept header for JSONP requests (which are actually done using a <script> tag). I also found this issue on the JQuery site where a different developer ran into the same problem: http://bugs.jquery.com/ticket/7694

Oddly, I’m actually having trouble reproducing the behavior you are seeing. In my repro code I see application/javascript getting added to the Accept header by IE9. I still need to try my code out with Firefox.

Could you please open an issue in Issue Tracker and attach your code project so that I can take a look?

As a workaround you could try adding a MediaTypeMapping to the JsonpMediaTypeFormatter that maps some part of the URI to application/javascript.

Daniel Roth

Nov 2, 2011 at 5:40 AM

See the workaround I implemented to get JsonP working reliably even if the Accept header comes across as */*:

http://wcf.codeplex.com/discussions/274789

Adam Anderly