The existence of the Origin policy (same) causes the "source" from a script to operate only the DOM of the "Same origin" page, and the "cross-origin" operation from page B will be rejected. The same-Origin policy and cross-domain resource sharing are, in most cases, Ajax requests. The same-origin policy mainly restricts AJAX requests implemented through XMLHttpRequest, and if the request is a "heterogeneous" address, the browser will not be allowed to read the returned content. JSONP is a common solution for cross-domain resource sharing, and now we are leveraging the extensibility of the ASP. NET Web API itself to provide a "common" JSONP implementation scenario.
First, Jsonpmediatypeformatter
In the [CORS: cross-domain resource sharing] homology policy and JSONP, we are "populating" the returned JSON object into a JavaScript callback function in a specific action method, Now we are using custom mediatypeformatter to provide a more general implementation for JSONP.
We define the following Jsonpmediatypeformatter type by inheriting Jsonmediatypeformatter. Its read-only property, callback, represents the name of the JavaScript callback function, and the property is specified in the constructor. In the overridden method Writetostreamasync, for a non-JSONP call (the callback function does not exist), we directly invoke the method of the same name on the base class to implement the JSON serialization for the response object. Otherwise, call the WriteToStream method to populate the JavaScript callback function with the JSON string after the object is serialized.
1:public class Jsonpmediatypeformatter:jsonmediatypeformatter
2: {
3: Public string Callback {get; private set;}
5: Public jsonpmediatypeformatter (string callback = null)
6: {
7: This . Callback = Callback;
8: }
Ten: Public override Task Writetostreamasync (type type, object value, Stream writestream, httpcontent content, TRANSP Ortcontext TransportContext)
One: {
: if (string. IsNullOrEmpty (this. Callback))
: {
: return base. Writetostreamasync (type, value, Writestream, content, TransportContext);
: }
: Try
: {
: This . WriteToStream (type, value, writestream, content);
: return task.fromresult<asyncvoid> (New asyncvoid ());
: }
: catch (Exception Exception)
: {
: taskcompletionsource<asyncvoid> Source = new taskcompletionsource<asyncvoid> ();
: source. SetException (Exception);
: return source. Task;
: }
: }
: private void WriteToStream (type type, object value, Stream writestream, httpcontent content)
: {
To: Jsonserializer serializer = jsonserializer.create (this. Serializersettings);
: using (StreamWriter StreamWriter = new StreamWriter (Writestream, this. Supportedencodings.first ()))
: using (jsontextwriter jsontextwriter = new JsonTextWriter (streamWriter) {closeoutput = false})
: {
£ º Jsontextwriter.writeraw (this. Callback + "(");
Panax Notoginseng: serializer. Serialize (jsontextwriter, value);
: Jsontextwriter.writeraw (")");
: }
Max: }
All: Public override Mediatypeformatter getperrequestformatterinstance (type type, httprequestmessage request, Mediatypeheadervalue mediatype)
: {
: if (request. Method! = httpmethod.get)
: {
*: return this;
: }
Callback: string;
49:
: pair = = pair. Value). TryGetValue ("Callback", out callback))
Wuyi: {
Jsonpmediatypeformatter: return New (callback);
: }
Si: return this;
: }
£ º [StructLayout (layoutkind.sequential, Size = 1)]
Asyncvoid: Private struct
: {}
60:}
We have rewritten the Getperrequestformatterinstance method, by default, when the ASP. NET Web API chooses a mediatypeformatter that matches the current request by using the content negotiation mechanism. This method is called to create a Mediatypeformatter object that is really used to serialize the result of the response. In this overridden Getperrequestformatterinstance method, we try to get the JavaScript callback function name that is carried from the requested URL, which is a query string called "callback". If the callback function name does not exist, it returns itself directly, otherwise the Jsonpmediatypeformatter object created accordingly is returned.
Ii. apply Jsonpmediatypeformatter to ASP. NET Web API
Next we demonstrate the limitations of the same-origin policy for cross-domain AJAX requests through a simple example. As shown in the image on the right, we created two Web apps in the same solution using Visual Studio. As you can see from the project name, Webapi and Mvcapp are both ASP. NET Web API and MVC application, which is the caller of the Web API. We directly use the default IIS Express as the host for two applications, and fixed the port number: The port numbers for Webapi and Mvcapp are "3721" and "9527" respectively, so the URI to the two app must not be homologous.
In the WEBAPI application, we defined a Contactscontroller type that inherits from Apicontroller, and it has a unique action method getallcontacts returns a list of contacts.
1:public class Contactscontroller:apicontroller
2: {
3: Public ienumerable<contact> getallcontacts ()
4: {
5: contact[] contacts = new contact[]
6: {
7: New contact{name= "Zhang San", phoneno= "123", emailaddress= "[email protected]"},
8: new contact{name= "John Doe", phoneno= "456", emailaddress= "[email protected]"},
9: new contact{name= "Harry", phoneno= "789", emailaddress= "[email protected]"},
Ten: };
One: return contacts;
: }
13:}
15:public class Contact
16: {
N: Public string Name {get; set;}
: Public string Phoneno {get; set;}
: Public string EmailAddress {get; set;}
20:}
Now we use the following program to create this Jsonpmediatypeformatter object in the global.asax of the WEBAPI application and add the currently registered Mediatypeformatter list. To make it a priority, we put this Jsonpmediatypeformatter object at the forefront of this list.
1:public class WebApiApplication:System.Web.HttpApplication
2: {
3: protected void Application_Start ()
4: {
5: GlobalConfiguration.Configuration.Formatters.Insert (0, New Jsonpmediatypeformatter ());
6: //Other operations
7: }
8:}
The following homecontroller are defined in the Mvcapp application, and the default action method, index, renders the corresponding view.
1:public class Homecontroller:controller
2: {
3: Public actionresult Index ()
4: {
5: return View ();
6: }
7:}
As shown below, the action method index corresponds to the view definition. Our goal is to invoke the Web API defined above as an AJAX request to get a list of contacts after the page has been successfully loaded, and will be rendered from the page. As shown in the following code snippet, we call the $.ajax method directly and set the datatype parameter to "JSONP".
1:
2:
3: <title> Contact List </title>
4: <script type= "Text/javascript" src= "@Url. Content (" ~/scripts/jquery-1.10.2.js ")" ></script>
5:
6: <body>
7: <ul id= "Contacts" ></ul>
8: <script type= "Text/javascript" >
9: $ (function ()
Ten: {
One: $.ajax ({
Type : "GET",
: URL : "Http://localhost:3721/api/contacts",
DataType: "jsonp",
: success : listcontacts
: });
: });
: function Listcontacts (contacts) {
: $.each (Contacts, function (index, contact) {
$: var html = "<li><ul>";
: html + = "<li>name:" + contact. Name + "</li>";
Page: html + = "<li>phone No:" + contact. Phoneno + "</li>";
: html + = "<li>email Address:" + contact. EmailAddress + "</li>";
: html + = "</ul>";
: $ ("#contacts"). Append ($ (HTML));
: });
: }
£ º </script>
: </body>
:
After you run the ASP. NET MVC program, you get the output as shown, and the list of contacts that you get through the cross-domain call to the Web API is displayed properly.
Iii. requests and responses for JSONP
The AJAX request and response content for JSONP, as shown below. You can see that the URL of the request provides the name of the JavaScript callback function through the query string "callback", while the body part of the response is not a purely JSON object, but rather a function call statement generated by populating the JSON object into the callback return.
1:get http://localhost:3721/api/contacts?callback=jQuery110205729522893670946_1386232694513 &_=1386232694514 http/1.1
2:host:localhost:3721
3:connection:keep-alive
4:accept: */*
5:user-agent:mozilla/5.0 (Windows NT 6.1) applewebkit/537.36 (khtml, like Gecko) chrome/31.0.1650.57 safari/537.36
6:referer:http://localhost:9527/
7:accept-encoding:gzip,deflate,sdch
9:http/1.1 OK
10:cache-control:no-cache
11:pragma:no-cache
12:content-type:application/json; Charset=utf-8
13:expires:-1
14:server:microsoft-iis/8.0
15:x-aspnet-version:4.0.30319
16:x-sourcefiles: =? UTF-8? B? Rtpc5oir55qe6jgx5l2cxeftuc5orvqgv2viiefqseahhuaetuapreenmfxozxcgu2ftcgxlc1xdagfwdgvyide0xfmxndazxfdlykfwavxhcglcy29ud ?=
17:x-powered-by:asp.net
18:date:thu, 08:38:15 GMT
19:content-length:248
21:jquery110205729522893670946_1386232694513 ([{"Name": "Zhang San", "Phoneno": "123", "EmailAddress": "[email protected]"}, {"Name": "John Doe", "Phoneno": "456", "EmailAddress": "[email protected]"},{"name": "Harry", "Phoneno": "789", "EmailAddress": [email protected]}])
This article turns from http://www.cnblogs.com/artech/archive/2013/12/05/3460544.html
Extending the support for the ASP. NET Web API Jsonp