zoukankan      html  css  js  c++  java
  • ASP.NET MVC 定义JsonpResult实现跨域请求

    1:原理

    在js中,XMLHttpRequest是不能请求不同域的数据,但是script标签却可以,所以可以用script标签实现跨域请求。具体是定义一个函数,例如jsonp1234,请求不同域的url时带上函数名,例如:http://otherdomain.com/index?callback=jsonp1234,然后服务端根据callback获取这个函数名,然后传入json字符串作为函数参数。

    2:实现

    http://localhost:62203/home/index页面代码如下

    @{
        Layout = null;
    }
    
    <!DOCTYPE html>
    
    <html>
    <head>
        <meta name="viewport" content="width=device-width" />
        <title>Index</title>
        <script>
        function showMessage(result) {
            alert(result.name)
        }
        </script>
        <script src="http://localhost:16308/home/index?callback=showMessage" type="text/javascript"></script>
    </head>
    <body>
        <div> 
        </div>
    </body>
    </html>

    主要是这句  

    <script src="http://localhost:16308/home/index?callback=showMessage" type="text/javascript"></script>,

    可以看到,访问的是不同的站点,并且callback的参数值为showMessage,

    http://localhost:16308/home/index代码如下

    public ActionResult Index()
            {
                string callback = this.Request["callback"];
                string json="{"name":"server"}";
                this.Response.Write(callback + "(" + json + ")");
                return new EmptyResult();
            }

    根据callback获取函数名,然后将json字符串作为函数参数。

    访问页面http://localhost:62203/home/index,效果如下

    image

    可见,站点localhost:62203从站点localhost:16308获取到了数据。

    但是我们看服务端的实现,这也太不美观,也比较麻烦。

    public ActionResult Index()
            {
                string callback = this.Request["callback"];
                string json="{"name":"server"}";
                this.Response.Write(callback + "(" + json + ")");
                return new EmptyResult();
            }

    我们想要的是调用一个方法,就能实现跨域了,那如何实现呢。看到Controller有个this.Json方法,类型是JsonResult,我们可以参考这个类。定义一个类JsonpResult,派生于JsonResult,在ExecuteResult方法根据callback获取函数名,然后传入json字符串作为函数参数。

    public class JsonpResult : JsonResult
        {
            public static readonly string JsonpCallbackName = "callback";
            public static readonly string CallbackApplicationType = "application/json";
    
            public override void ExecuteResult(ControllerContext context)
            {
                if (context == null)
                {
                    throw new ArgumentNullException("context");
                }
                if ((JsonRequestBehavior == JsonRequestBehavior.DenyGet) &&
                      String.Equals(context.HttpContext.Request.HttpMethod, "GET", StringComparison.OrdinalIgnoreCase))
                {
                    throw new InvalidOperationException();
                }
                var response = context.HttpContext.Response;
                if (!String.IsNullOrEmpty(ContentType))
                    response.ContentType = ContentType;
                else
                    response.ContentType = CallbackApplicationType;
                if (ContentEncoding != null)
                    response.ContentEncoding = this.ContentEncoding;
                if (Data != null)
                {
                    String buffer;
                    var request = context.HttpContext.Request;
                    var serializer = new JavaScriptSerializer();
                    if (request[JsonpCallbackName] != null)
                        buffer = String.Format("{0}({1})", request[JsonpCallbackName], serializer.Serialize(Data));//首先根据callback获取获取函数名,然后传入json字符串作为函数参数
                    else
                        buffer = serializer.Serialize(Data);
                    response.Write(buffer);
                }
            }
        }

    JsonpResult类有了,但是想在Controller这样使用this.Jsonp,所以为Controller类定义一个扩展方法,

    public static class ControllerExtension
        {
            public static JsonpResult Jsonp(this Controller controller, object data)
            {
                JsonpResult result = new JsonpResult()
                {
                    Data = data,
                    JsonRequestBehavior = JsonRequestBehavior.AllowGet
                }; 
                return result;
            }
        }

    这是在Controller就可以直接使用this.Jsonp了,把跨域服务端的代码改下
    public ActionResult Index()
            {
                return this.Jsonp(new { name = "server JsonpResult" });
            }

    相比上面那个简洁多了

    再次打开http://localhost:62203/home/index

    image

    同样,站点localhost:62203从站点localhost:16308获取到了数据,和上面的一样

  • 相关阅读:
    [转载]Python爬虫之xpath使用技巧
    手机自动化脚本
    英镑像素转换
    小程序路径存入数据库
    avalonia项目在银河麒麟操作系统arm架构上运行报错:default font family is not be null or empty
    http 301、304状态码
    一文完全理解IP
    TCP是如何保证可靠传输的?
    一文弄懂TCP常见面试题
    一文弄懂HTTP常见面试题
  • 原文地址:https://www.cnblogs.com/dandzm/p/4758453.html
Copyright © 2011-2022 走看看