码迷,mamicode.com
首页 > Web开发 > 详细

ASP.NET MVC 定义JsonpResult实现跨域请求

时间:2015-08-25 21:09:39      阅读:227      评论:0      收藏:0      [点我收藏+]

标签:

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,效果如下

技术分享

可见,站点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

技术分享

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

ASP.NET MVC 定义JsonpResult实现跨域请求

标签:

原文地址:http://www.cnblogs.com/dandzm/p/4758453.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!