zoukankan      html  css  js  c++  java
  • ASP.NET MVC 扩展之 JsonpResult ,用来提供轻量级跨域调用服务

    ASP.NET MVC 扩展之 JsonpResult ,用来提供轻量级跨域调用服务

    2012-06-21 23:16 by 自由的生活, 522 阅读, 1 评论, 收藏编辑

    关于 JSONP,我想大家都已经很熟悉了,还不是很清楚的童鞋可以在网上搜索一下。众所周知, Ajax 是不能跨域请求的,默认情况下,浏览器是阻止的。那如何来实现跨域提供服务呢?举一个很简单的例子。比如我现在有一个网站 www.abc.com ,其中有一个页面需要提供百度的搜索框,并且还要像百度首页一样,提供智能的提示,就是在我输入文字的同时,及时补全我的搜索,列出供我选择的项。

    由于前面我们说到 Ajax 是不能跨域的,那怎样调用百度的搜索服务呢?答案就是 JSONP。JSONP 说白了就是在 www.abc.com 一个页面里,通过 Javascript 动态构造一个 <Script> </script>,其中 src= 'http://search.baidu.com/service.php?word=博客园&callback=showSearch", 其中 word=博客园 是我们在 www.abc.com 搜索框里面输入的文字,callback=showSearch 就是百度返回的结果里面回调函数的名称,比如 showSearch({ word: '博客园', result : [{博客园a},{博客园b}] }) 。

    由于动态构建 <script> 不是 Ajax 请求,而是普通的 GET 请求,所以它是可以跨域的。

    废话了这么多,下面就贴出我的代码了:

    JsonpResult:

    复制代码
    using System.Web.Mvc;
    using System.Web.Script.Serialization;
    using System.Text;
    
    namespace DearBruce.JsonpActionResultDemo.WebUI.Extensions
    {
        /// <summary>
        /// Jsonp 返回结果
        /// </summary>
        public class JsonpResult : ActionResult
        {
            /// <summary>
            /// 默认的 callback 参数名称
            /// </summary>
            public static readonly string _defaultCallbackName = "jsoncallback";
    
            /// <summary>
            /// 默认的密码的参数名称
            /// </summary>
            public static readonly string _defaultPasswordName = "password";
    
            /// <summary>
            /// 构造函数
            /// </summary>
            /// <param name="data">要序列化为 Jsonp 数据的对象</param>
            public JsonpResult(object data)
                : this(data, null)
            {
    
            }
    
            /// <summary>
            /// 构造函数
            /// </summary>
            /// <param name="data">要序列化为 Jsonp 数据的对象</param>
            /// <param name="callbackName">回调函数的名字,如果为空,则默认为 "jsoncallback"</param>
            public JsonpResult(object data, string callbackName)
            {
                this.Data = data;
                this.CallBackName = callbackName;
            }
    
            /// <summary>
            /// 验证权限
            /// </summary>
            /// <param name="context">控制器上下文</param>
            /// <returns>授权是否成功,如果已经授权,则返回 true</returns>
            protected virtual bool ValidatePrivilege(ControllerContext context)
            {
                if (!string.IsNullOrEmpty(PasswordValue))
                {
                    // 这里验证密码是否正确
                    string password = context.HttpContext.Request.QueryString[PasswordName];
                    if (password != PasswordValue)
                    {
                        return false;
                    }
                }
                return true;
            }
    
            /// <summary>
            /// 核心处理
            /// </summary>
            /// <param name="context"></param>
            public override void ExecuteResult(ControllerContext context)
            {
                if (!ValidatePrivilege(context))
                {
                    HandleUnAuthorizedRequest(context);
                    return;
                }
                string jsonData = null;
                if(Data != null)
                {
                    jsonData = new JavaScriptSerializer().Serialize(Data);
                }
                string callbackValue = context.HttpContext.Request.QueryString[CallBackName];
    
                string result;
                string contentType;
                if (string.IsNullOrEmpty(callbackValue))
                {
                    result = jsonData;
                    contentType = "application/json";
                }
                else
                {
                    result = callbackValue + "(" + jsonData + ")";
                    contentType = "application/x-javascript";
                }
                context.HttpContext.Response.ContentType = contentType;
                if (this.ContentEncoding != null)
                {
                    context.HttpContext.Response.ContentEncoding = this.ContentEncoding;
                }
                if(result != null)
                {
                    context.HttpContext.Response.Write(result);
                }
            }
    
            /// <summary>
            /// 处理为授权的请求
            /// </summary>
            /// <param name="context">控制器上下文</param>
            protected virtual void HandleUnAuthorizedRequest(ControllerContext context)
            {
                // 暂时不实现
                //context.HttpContext.Response.ContentType = "text/plain";
                //context.HttpContext.Response.Write(string.Empty);
            }
    
            /// <summary>
            /// 要序列化为 Jsonp 数据的对象
            /// </summary>
            public object Data { get; set; }
    
            private Encoding _contentEncoding;
    
            /// <summary>
            /// 内容编码
            /// </summary>
            public Encoding ContentEncoding
            {
                get
                {
                    return _contentEncoding; // ?? Encoding.UTF8;
                }
                set
                {
                    _contentEncoding = value;
                }
            }
    
            private string _callBackName;
    
            /// <summary>
            /// 回调函数名称
            /// </summary>
            public string CallBackName
            {
                get
                {
                    return _callBackName ?? _defaultCallbackName;
                }
                set
                {
                    _callBackName = value;
                }
            }
    
    
            private string _passwordName { get; set; }
    
            /// <summary>
            /// 密码的参数名称,默认为 "password"
            /// </summary>
            public string PasswordName
            {
                get
                {
                    return _passwordName ?? _defaultPasswordName;
                }
                set
                {
                    _passwordName = value;
                }
            }
    
            /// <summary>
            /// 正确的密码值
            /// </summary>
            public string PasswordValue { get; set; }
        }
    }
    复制代码

    测试的 Controller:

    复制代码
        public class HomeController : Controller
        {
            public ActionResult Index()
            {
                ViewBag.Message = "欢迎使用 ASP.NET MVC!";
    
                return View();
            }
    
            public ActionResult TestJsonp1()
            {
                return new JsonpResult(new { success = true, message = "测试 jsonp1" });
            }
    
            public ActionResult TestJsonp2()
            {
                return new JsonpResult(new { success = true, message = "测试 jsonp2" }, "callback");
            }
    
            public ActionResult TestJsonp3()
            {
                JsonpResult result = new JsonpResult(new { success = true, message = "测试 jsonp3" }, "callback")
                {
                    PasswordValue = "bruce123456",
                };
                return result;
            }
        }
    复制代码

    测试的 View:

    复制代码
    <p>
        @Html.ActionLink("测试 Jsonp 之不带 jsoncallback 参数和不需要密码,则返回 json 数据", "TestJsonp1")
    </p>
    <p>
        @Html.ActionLink("测试 Jsonp 之带 callback 参数,则返回 javascript 代码", "TestJsonp2", new { callback = "ShowMessage" })
    </p>
    <p>
        @Html.ActionLink("测试 Jsonp 之需要密码 - 为空或错误的密码", "TestJsonp3")
    </p>
    <p>
        @Html.ActionLink("测试 Jsonp 之带 callback 参数和需要密码 - 正确的密码", "TestJsonp3", new { password = "bruce123456", callback = "ShowMessage" })
    </p>
    复制代码

    虽然很简单,只给需要帮助的人!

    谢谢浏览!

    作者:音乐让我说音乐让我说 - 博客园
    微博:http://weibo.com/liuzuliang 
    出处:http://music.cnblogs.com/
    文章版权归本人所有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

    分类: ASP.NET MVC
  • 相关阅读:
    个人学习jQuery笔记
    (转载) jQuery页面加载初始化的3种方法
    [转]学会和同事相处的30个原则
    解决iis出现这个问题-2147467259 (0x80004005)
    不规则瀑布流图片墙
    实现图片大小的自动控制( 图片大小控制CSS代码)
    (转载)DataTable使用技巧总结
    (转载) jQuery 页面加载初始化的方法有3种
    ajax连接数据库并操作数据库
    java Semaphore实现ABC三个线程循环打印
  • 原文地址:https://www.cnblogs.com/Leo_wl/p/2558503.html
Copyright © 2011-2022 走看看