zoukankan      html  css  js  c++  java
  • 前后端分离之CORS和WebApi

    目前的项目是前端mv*+api的方式进行开发的,以前都是没有跨域的方案,前后端人员在同一个解决方案里边进行开发,前端人员要用IIS或VS来开发和调试Api,这样就很不方便,迫切需要跨域访问Api.

    评选了很多解决方案最终选择,CORS+WebApi

    cors科普:http://www.ruanyifeng.com/blog/2016/04/cors.html

    cors网站:http://enable-cors.org/

    mvc源码:https://github.com/ASP-NET-MVC/aspnetwebstack/blob/master/src/System.Web.Http.Cors/CorsMessageHandler.cs

    快速入门可以看一些教程,自己要扩展源码是一条捷径.

    示例代码:https://github.com/gutun/aspnet/tree/master/cors

    1.新建WebApi项目实现CORS跨域

    1.1 新建一个新的项目CrossDomain

    1.2. 安装 Microsoft.AspNet.WebApi.Cors

    Install-Package Microsoft.AspNet.WebApi.Cors
    

    1.3. 配置App_Start目录下的 WebApiConfig文件

    Config中要启用 CORS的支持我选择默认的MediaType为json方式。

    1.4 新增UserController,在里边新增两个方法,get用来ping,代表url是通的,post模拟真正的数据提交,我们所有的api访问走post, request的入参和出参可以定义通用的实体。这里模拟post提交数据解析成UserInfo的实例。

    2.JQuery Ajax跨域

    <!DOCTYPE html>
    <html lang="en">
        <head>
            <title></title>
            <meta charset="UTF-8">
            <meta name="viewport" content="width=device-width, initial-scale=1">
            <script src="http://cdn.bootcss.com/jquery/1.11.1/jquery.min.js"></script>
        </head>
        <body>
        <script>
            $.ajax({
                url:'http://localhost:64542/api/user',
                type:'POST',
                data:{"Id":"1","Name":"张三"},
                dataType:'json',
                //Content-Type:只限于三个值application/x-www-form-urlencoded、multipart/form-data、text/plain
                //contentType: 'application/json; charset=utf-8',
                cache: false,
                crossDomain: true,
                success:function(data){
                    alert(data);
                }
            });
        </script>
        </body>
    </html>
    

    使用Nodejs本地服务器访问WebApi项目,成功的访问到了api/User,状态是200.

    3.IE8,IE9支持CORS.

    CORS在浏览器的支持情况,IE8和IE9是部分兼容,86%的浏览器是支持的,占了大部分,为了支持IE8和IE9我找到了一个补丁jquery.transport.xdr.min.js 用来弥补在IE8和IE9下的不足。

    https://github.com/gfdev/javascript-jquery-transport-xdr.js

    <!DOCTYPE html>
    <html lang="en">
        <head>
            <title></title>
            <meta charset="UTF-8">
            <meta name="viewport" content="width=device-width, initial-scale=1">
            <script src="http://cdn.bootcss.com/jquery/1.11.1/jquery.min.js"></script>
            <script src="http://cdn.bootcss.com/jquery/1.11.1/jquery.min.js"></script>
            <!--[if (IE 8)|(IE 9)]>
            <script src="http://cdn.rawgit.com/gfdev/javascript-jquery-transport-xdr/master/dist/jquery.transport.xdr.min.js"></script>
            <![endif]-->
        </head>
        <body>
        <script>
            //http://www.ruanyifeng.com/blog/2016/04/cors.html
            $.ajax({
                url:'http://localhost:64542/api/user',
                type:'POST',
                data:{"Id":"1","Name":"张三"},
                dataType:'json',
                //Content-Type:只限于三个值application/x-www-form-urlencoded、multipart/form-data、text/plain
                //contentType: 'application/json; charset=utf-8',
                cache: false,
                crossDomain: true,
                success:function(data){
                    alert(data);
                }
            });
        </script>
        </body>
    </html>

    喜出往外,跑起来后遇到了,415错误,未识别的Content-Type,这是因为在IE8和IE9下,Content-Type为空造成的。

     

    http://stackoverflow.com/questions/18964258/asp-web-api-post-request-with-cors-and-ie9-xdomainrequest-objec

    新增DefaultContentTypeMessageHandler用来处理Request 

    using System.Net.Http;
    using System.Threading;
    using System.Threading.Tasks;
    using System.Web.Cors;
    using System.Web.Http.Cors;
    
    namespace CrossDomain
    {
        public class DefaultContentTypeMessageHandler : DelegatingHandler
        {
            protected async override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
            {
                CorsRequestContext corsRequestContext = request.GetCorsRequestContext();
                if (corsRequestContext != null) //判断是否是跨域的请求
                {
                    if (request.Method == HttpMethod.Post && request.Content.Headers.ContentType == null) //ConentType为空,使用默认值
                        request.Content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/x-www-form-urlencoded");
                }
    
                var response = await base.SendAsync(request, cancellationToken);
    
                return response;
            }
    
        }
    }

    再次更改WebApiConfig文件,在MessageHandlers管道中追加刚写的DefaultContentTypeMessageHandler,这样ContentType为空的跨域请求会使用默认的ContentType.

    using System.Web.Http;
    using System.Web.Http.Cors;
    
    namespace CrossDomain
    {
        public static class WebApiConfig
        {
            public static void Register(HttpConfiguration config)
            {
                //新增CORS支持
                var corsAttr = new EnableCorsAttribute("*", "*", "*");
                config.EnableCors(corsAttr);
                //默认使用json格式,移除xml格式
                config.Formatters.XmlFormatter.SupportedMediaTypes.Clear();
                //处理Content-Type
                config.MessageHandlers.Add(new DefaultContentTypeMessageHandler());
    
                // Web API configuration and services
    
                // Web API routes
                config.MapHttpAttributeRoutes();
    
                config.Routes.MapHttpRoute(
                    name: "DefaultApi",
                    routeTemplate: "api/{controller}/{id}",
                    defaults: new { id = RouteParameter.Optional }
                );
            }
        }
    }

    在chrome,IE8,IE9,IE10+上测试没有问题。

  • 相关阅读:
    Mac下安装svn服务器
    php 当前日期加一天和指定日期加一天
    MariaDB与MySQL
    JS中判断null、undefined与NaN的方法
    PHP保留两位小数的几种方法
    jquery的cookie插件
    mysql(5.7以上)查询报错:ORDER BY clause is not in GROUP BY..this is incompatible with sql_mode=only_full_group_by
    MySQL数据的导出和导入
    qrCode二维码字符串长度太多压缩的问题
    解决 img 标签上下出现的间隙
  • 原文地址:https://www.cnblogs.com/gutun/p/5981396.html
Copyright © 2011-2022 走看看