ASP.NET MVC 扩展之 JsonpResult ,用来提供轻量级跨域调用服务
ASP.NET MVC 扩展之 JsonpResult ,用来提供轻量级跨域调用服务
2012-06-21 23:16 by 自由的生活, 522 阅读, 1 评论, 收藏 , 编辑
关于 JSONP,我想大家都已经很熟悉了,还不是很清楚的童鞋可以在网上搜索一下。众所周知, Ajax 是不能跨域请求的,默认情况下,浏览器是阻止的。那如何来实现跨域提供服务呢?举一个很简单的例子。比如我现在有一个网站 HdhCmsTestabc测试数据 ,其中有一个页面需要提供百度的搜索框,并且还要像百度首页一样,提供智能的提示,就是在我输入文字的同时,及时补全我的搜索,列出供我选择的项。
由于前面我们说到 Ajax 是不能跨域的,那怎样调用百度的搜索服务呢?答案就是 JSONP。JSONP 说白了就是在 HdhCmsTestabc测试数据 一个页面里,通过 Javascript 动态构造一个 <Script> </script>,其中 src= 'http://search.baidu测试数据/service.php?word=博客园&callback=showSearch", 其中 word=博客园 是我们在 HdhCmsTestabc测试数据 搜索框里面输入的文字,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测试数据/liuzuliang
出处: http://music.cnblogs测试数据/
文章版权归本人所有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
分类: ASP.NET MVC
作者: Leo_wl
出处: http://HdhCmsTestcnblogs测试数据/Leo_wl/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
版权信息查看更多关于ASP.NET MVC 扩展之 JsonpResult ,用来提供轻量级跨域调用服务的详细内容...