使Asp.net WebApi支持JSONP和Cors跨域访问
2015-12-31 17:04
691 查看
1.服务端处理
同源策略(Same Origin Policy)的存在导致了“源”自A的脚本只能操作“同源”页面的DOM,“跨源”操作来源于B的页面将会被拒绝。同源策略以及跨域资源共享在大部分情况下针对的是Ajax请求。同源策略主要限制了通过XMLHttpRequest实现的Ajax请求,如果请求的是一个“异源”地址,浏览器将不允许读取返回的内容。JSONP是一种常用的解决跨域资源共享的解决方案,现在我们利用ASP.NET Web API自身的扩展性提供一种“通用”的JSONP实现方案。
我们通过继承JsonMediaTypeFormatter定义了如下一个JsonpMediaTypeFormatter类型。它的只读属性Callback代表JavaScript回调函数名称,改属性在构造函数中指定。在重写的方法WriteToStreamAsync中,对于非JSONP调用(回调函数不存在),我们直接调用基类的同名方法对响应对象实施针对JSON的序列化,否则调用WriteToStream方法将对象序列化后的JSON字符串填充到JavaScript回调函数中。
我们重写了GetPerRequestFormatterInstance方法,在默认情况下,当ASP.NET Web API采用内容协商机制选择出与当前请求相匹配的MediaTypeFormatter后,会调用此方法来创建真正用于序列化响应结果的MediaTypeFormatter对象。在重写的这个GetPerRequestFormatterInstance方法中,我们尝试从请求的URL中得到携带的JavaScript回调函数名称,即一个名为“callback”的查询字符串。如果回调函数名不存在,则直接返回自身,否则返回据此创建的JsonpMediaTypeFormatter对象。
1.重写JsonMediaTypeFormatter处理JSONP请求
View Code
2.在网站启动注册
2.客户端实例
分别的相应结果:
同源策略(Same Origin Policy)的存在导致了“源”自A的脚本只能操作“同源”页面的DOM,“跨源”操作来源于B的页面将会被拒绝。同源策略以及跨域资源共享在大部分情况下针对的是Ajax请求。同源策略主要限制了通过XMLHttpRequest实现的Ajax请求,如果请求的是一个“异源”地址,浏览器将不允许读取返回的内容。JSONP是一种常用的解决跨域资源共享的解决方案,现在我们利用ASP.NET Web API自身的扩展性提供一种“通用”的JSONP实现方案。
我们通过继承JsonMediaTypeFormatter定义了如下一个JsonpMediaTypeFormatter类型。它的只读属性Callback代表JavaScript回调函数名称,改属性在构造函数中指定。在重写的方法WriteToStreamAsync中,对于非JSONP调用(回调函数不存在),我们直接调用基类的同名方法对响应对象实施针对JSON的序列化,否则调用WriteToStream方法将对象序列化后的JSON字符串填充到JavaScript回调函数中。
我们重写了GetPerRequestFormatterInstance方法,在默认情况下,当ASP.NET Web API采用内容协商机制选择出与当前请求相匹配的MediaTypeFormatter后,会调用此方法来创建真正用于序列化响应结果的MediaTypeFormatter对象。在重写的这个GetPerRequestFormatterInstance方法中,我们尝试从请求的URL中得到携带的JavaScript回调函数名称,即一个名为“callback”的查询字符串。如果回调函数名不存在,则直接返回自身,否则返回据此创建的JsonpMediaTypeFormatter对象。
1.重写JsonMediaTypeFormatter处理JSONP请求
public class JsonpMediaTypeFormatter : JsonMediaTypeFormatter { public string Callback { get; private set; } public JsonpMediaTypeFormatter(string callback = null) { this.Callback = callback; } public override Task WriteToStreamAsync(Type type, object value, Stream writeStream, HttpContent content, TransportContext transportContext) { 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) { 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 + "("); serializer.Serialize(jsonTextWriter, value); jsonTextWriter.WriteRaw(")"); } } public override MediaTypeFormatter GetPerRequestFormatterInstance(Type type, HttpRequestMessage request, MediaTypeHeaderValue mediaType) { if (request.Method != HttpMethod.Get) { return this; } string callback; if (request.GetQueryNameValuePairs().ToDictionary(pair => pair.Key, pair => pair.Value).TryGetValue("callback", out callback)) { return new JsonpMediaTypeFormatter(callback); } return this; } [StructLayout(LayoutKind.Sequential, Size = 1)] private struct AsyncVoid { } }
View Code
2.在网站启动注册
public class WebApiApplication : System.Web.HttpApplication { protected void Application_Start() { GlobalConfiguration.Configure(WebApiConfig.Register); //注册JSOPN提交处理 GlobalConfiguration.Configuration.Formatters.Insert(0, new JsonpMediaTypeFormatter()); } }
2.客户端实例
//使用Cors方式提交 $.get(apiUrl.getTwo("TestTwo"), { name: '张三' }, function (data) { alert(data); }); //使用Jsonp方式提交 $.ajax({ data: { name: 'zhangsan' }, url: apiUrl.getTwo('TestTwo'), dataType: 'jsonp', success: function (data) { alert(data); }, error: function (XMLRequest, textStatus) { console.info(XMLRequest); console.info(textStatus); alert('失败'); } });
分别的相应结果:
相关文章推荐
- windows server2008下asp.net 的部署
- J48源码学习笔记(四)buildTree(),collaspe(),prune()
- 知识地图项目中当前暂时搁置,后期需要优化的地方--给自己记录一下
- asp.net MVC4 lognet4 日志
- ASP.net 判断上传文件类型的三种方法
- ASP.NET MVC 表单提交多层子级实体集合数据到控制器中
- asp.net mvc 无刷新加载
- ASP.NET MVC html help
- ASP.NET MVC中实现多个按钮提交的几种方法
- ASP.NET-FineUI开发实践-17
- 先锋缓存类(极度加速ASP和提高执行效率)
- 灌水帖 asp.net非法请求时跳转到登录页面
- asp.net获取服务器信息
- ASP事务处理
- ASP.NET网站入侵第三波(fineui系统漏洞,可导致被拖库)
- Asp.Net WebAPI传递json对象、后台手动接收参数
- Asp.Net WebAPI Get提交、Post提交处理
- 详解ASP.NET页面生命周期
- 2.06StuModify.aspx(修改姓名,性别,所在班级)
- 检测到在集成的托管管道模式下不适用的ASP.NET设置的解决方法