解决方案
不提倡跨域的post请求。
0.jquery中ajax的跨域方案jsonp
.ashx代码
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Web;
- namespace KB.DSN.Web.API.Tokens
- {
- /// <summary>
- /// Summary description for Get
- /// </summary>
- public class Get : IHttpHandler
- {
- public void ProcessRequest(HttpContext context)
- {
- setresponsecontext(context);
- var token = KB.DSN.BusinessAccess.UniqueCommunicationCode.GenerateUniqueCommunicationCode();
- var outputobject = new
- {
- Head = new Models.KBJsonHeadResponse(),
- Body = new { Token = token }
- };
- var outputjsonstring = Newtonsoft.Json.JsonConvert.SerializeObject(outputobject);
- context.Response.Write(context.Request.QueryString["callback"]+"("+outputjsonstring+")");
- }
- private void setresponsecontext(HttpContext context)
- {
- context.Response.ContentEncoding = System.Text.Encoding.UTF8;
- context.Response.ContentType = "application/json";
- }
- public bool IsReusable
- {
- get
- {
- return false;
- }
- }
- }
- }
html页面
- function getToken_jsonp(){
- $.ajax({
- url: "http://192.168.0.111/api/tokens/get.ashx",
- type: "get",
- dataType: "jsonp",
- jsonp: "callback",
- async: false,
- contentType: "application/json",
- success: function(data){
- //alert("getToken success");
- $("#token").text($.toJSON(data));
- //console.log(data);
- },
- error:function(){
- alert("getToken fail");
- }
- });
- }
jsonp只支持GET请求,不支持POST请求,就算你写了POST,它会自动转换为GET请求,把你的data放在querystring中。
1.修改web.config文件
整个应用都支持跨域的请求。
web.config
- <system.webServer>
- <httpProtocol>
- <customHeaders>
- <add name="Access-Control-Allow-Methods" value="OPTIONS,POST,GET"/>
- <add name="Access-Control-Allow-Headers" value="x-requested-with"/>
- <add name="Access-Control-Allow-Origin" value="*" />
- </customHeaders>
- </httpProtocol>
- </system.webServer>
html page
- function addContact() {
- var contact = new Object();
- contact.FirstName = $("#firstName").attr("value");
- contact.LastName = $("#lastName").attr("value");
- contact.PhoneNo = $("#phoneNo").attr("value");
- contact.EmailAddress = $("#emailAddress").attr("value");
- $.ajax({
- url: "http://localhost:10401/api/contacts/AddContact.ashx",
- type: "POST",
- dataType: "json",
- data: $.toJSON(contact),
- success: function () { loadAllContacts(); }
- });
- }
这种方式不能设置contentType: "application/json",否则会提示 "Request header field Content-Type is not allowed by Access-Control-Allow-Headers." 去掉ajax中的contentType设置就可以了! |
想要设置contentType也可以,需要将web.config文件中的 <add name="Access-Control-Allow-Headers" value="x-requested-with"/> 修改为 <add name="Access-Control-Allow-Headers" value="x-requested-with,content-type"/> |
在II6中web.config不支持system.webServer配置节,所以需要在IIS中设置httprequestheader。将web.config文件中的自定义头加入IIS的设置中。 |
FindContact.ashx
- /// <summary>
- /// Summary description for FindContact
- /// </summary>
- public class FindContact : IHttpHandler
- {
- public void ProcessRequest(HttpContext context)
- {
- context.Response.ContentEncoding = Encoding.UTF8;
- context.Response.ContentType = "application/json";
- var stream = context.Request.InputStream;
- var reader = new StreamReader(stream);
- var input=reader.ReadToEnd();
- var o = Newtonsoft.Json.JsonConvert.DeserializeObject<Models.Contact>(input);
- var list = new List<Models.Contact>();
- list.Add(o);
- list.Add(o);
- context.Response.Write(Newtonsoft.Json.JsonConvert .SerializeObject ( list ));
- }
- public bool IsReusable
- {
- get
- {
- return false;
- }
- }
- }
2.在请求中设置HttpHeader
针对单个请求。
FindContact.ashx
- /// <summary>
- /// Summary description for FindContact
- /// </summary>
- public class FindContact : IHttpHandler
- {
- public void ProcessRequest(HttpContext context)
- {
- context.Response.ContentEncoding = Encoding.UTF8;
- context.Response.ContentType = "application/json";
- var stream = context.Request.InputStream;
- var reader = new StreamReader(stream);
- var input=reader.ReadToEnd();
- var o = Newtonsoft.Json.JsonConvert.DeserializeObject<Models.Contact>(input);
- var list = new List<Models.Contact>();
- list.Add(o);
- list.Add(o);
- #region 支持跨域请求
- context.Response.ClearHeaders();
- string origin = context.Request.Headers["Origin"];
- context.Response.AppendHeader("Access-Control-Allow-Origin",
- string.IsNullOrEmpty(origin) ? "*" : origin);
- string requestHeaders = context.Request.Headers["Access-Control-Request-Headers"];
- context.Response.AppendHeader("Access-Control-Allow-Headers",
- string.IsNullOrEmpty(requestHeaders) ? "*" : requestHeaders);
- context.Response.AppendHeader("Access-Control-Allow-Methods", "POST, OPTIONS");
- #endregion
- context.Response.Write(Newtonsoft.Json.JsonConvert .SerializeObject ( list ));
- }
- public bool IsReusable
- {
- get
- {
- return false;
- }
- }
- }
html page
- function addContact() {
- var contact = new Object();
- contact.FirstName = $("#firstName").attr("value");
- contact.LastName = $("#lastName").attr("value");
- contact.PhoneNo = $("#phoneNo").attr("value");
- contact.EmailAddress = $("#emailAddress").attr("value");
- $.ajax({
- url: "http://localhost:10401/api/contacts/AddContact.ashx",
- type: "POST",
- dataType: "json",
- data: $.toJSON(contact),
- success: function () { loadAllContacts(); }
- });
- }
3.使用代理
假设你有两个web应用:一个应用放html页面,给用户提供界面;一个应用放服务,使用.ASHX处理请求。
你在html应用中使用ajax请求ashx应用的接口,就是ajax跨域请求。
你可以在html应用中写一些后台代码,在代码中向ashx应用提交数据。
然后你的html应用的页面中将收集到的数据发送到html应用的后台代码中,由后台代码发送数据到ashx应用,这就不是ajax跨域请求了。
在html应用中的后台代码就被叫做“代理”,代理html应用到ashx应用的请求。
参考文档
1.implementing-cors-support-in-asp-net-web-apis
2.Implementing CORS support in ASP.NET Web APIs – take 2
3.说说JSON和JSONP,也许你会豁然开朗,含jQuery用例
4.Cross-Origin Resource Sharing
5.cannot POST to IHTTPHandler class, origin not allowed by Access-Control-Allow-Origin
6.Secure Cross-Domain Communication in the Browser
8.jQuery File Uploader, Cross Domain Requests, and ASHX Web Services
9.jquery跨域访问解决方案