2012年5月25日星期五

Asp.net MVC3 实现JSONP

Asp.net MVC3 实现JSONP

    JSONP可以帮我们解决跨域访问的问题。JSONP is JSON With Padding. 这里我们将不再解释其原理。我们来看在ASP.NET MVC 3 如何实现。首先我们需要定义一个JsonpResult. 代码像这样, 直接继承自JsonResult, override了ExecuteResult方法

 

public class JsonpResult : JsonResult{    private static readonly string JsonpCallbackName = "callback";    private static readonly string CallbackApplicationType = "application/json";    /// <summary>    /// Enables processing of the result of an action method by a custom type that inherits from the <see cref="T:System.Web.Mvc.ActionResult"/> class.    /// </summary>    /// <param name="context">The context within which the result is executed.</param>    /// <exception cref="T:System.ArgumentNullException">The <paramref name="context"/> parameter is null.</exception>    public override void ExecuteResult(ControllerContext context)    {        if (context == null)        {            throw new ArgumentNullException("context");        }        if ((JsonRequestBehavior == JsonRequestBehavior.DenyGet) &&              String.Equals(context.HttpContext.Request.HttpMethod, "GET"))        {            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));            else                buffer = serializer.Serialize(Data);            response.Write(buffer);        }    }}

接着简单定义一个扩展方法:
public static class ContollerExtensions{    /// <summary>    /// Extension methods for the controller to allow jsonp.    /// </summary>    /// <param name="controller">The controller.</param>    /// <param name="data">The data.</param>    /// <returns></returns>    public static JsonpResult Jsonp(this Controller controller, object data)    {        JsonpResult result = new JsonpResult()        {            Data = data,            JsonRequestBehavior = JsonRequestBehavior.AllowGet        };               return result;    }}


在Controller里使用它, 我们的Controller叫ApiController,其中的Action:

 

/// <summary>/// Get some basic information with a JSONP GET request. /// </summary>/// <remarks>///    Sample url: ///    http://localhost:50211/Api/GetInformation?key=test&callback=json123123/// </remarks>/// <param name="key">key</param>/// <returns>JsonpResult</returns>public JsonpResult GetInformation(string key){    var resp = new Models.CustomObject();    if (ValidateKey(key))    {        resp.Data = "You provided key: " + key;        resp.Success = true;    }    else    {        resp.Message = "unauthorized";    }    return this.Jsonp(resp);}private bool ValidateKey(string key){    if (!string.IsNullOrEmpty(key))        return true;    return false;}

 

上面的方法接收一个string的参数,接着我们在前面加一个前缀字符串,最后返回就是Jsonp Result.

传值的Model:

public class CustomObject{    public bool Success { get; set; }    public object Data { get; set; }    public string Message { get; set; }}


运行WebSite, 访问 http://localhost:50211/Api/GetInformation?callback=myfunction&key=haha

我们可以看到这样的结果:

myfunction({"Success":true,"Data":"You provided key: haha","Message":null})
 
好的,现在让我们在另一个站点里使用它:
<html ="http://www.w3.org/1999/xhtml"><head runat="server">    <title>Index</title>    <script src="../../Scripts/jquery-1.4.1.min.js" type="text/javascript"></script>    <script type="text/javascript">        $(document).ready(function () {            $('.result').hide();            $('#test').click(function () {                $('.result').fadeOut('fast');                $('.result').html('');                $.ajax({                    url: 'http://localhost:50211/Api/GetInformation',                    data: { key: $('input[name=key]').val() },                    type: "GET",                    dataType: "jsonp",                    jsonpCallback: "localJsonpCallback"                });            });        });        function localJsonpCallback(json) {            //do stuff...            if (json.Success) {                $('.result').html(json.Data);            }            else {                $('.result').html(json.Message);            }            $('.result').fadeIn('fast');        }    </script></head><body>    <div>        Enter key: <input type="text" name="key" value="some data key, this parameter is optional" />        <br /><input type="button" value="Test JSONP" id="test" />        <div class="result">        </div>    </div></body></html>


这里使用的JQuery的Ajax来调用它, 熟悉JQuery的应该能看懂, 结果是在button下div显示字符串:

You provided key: some data key, this parameter is optional

在这里,也可以使用getJSON方法。
好了,就这么简单。希望对您Web开发有帮助。

您可参感兴趣的文章:

Asp.net MVC 3 中 Unobtrusive javascript 与Ajax

HTML5中custom data-*特性与asp.net mvc 3 表单验证


作者:Petter Liu
出处:http://www.cnblogs.com/wintersun/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
该文章也同时发布在我的独立博客中-Petter Liu Blog。


TAG: