MVC Web API & jsonp

Posted

技术标签:

【中文标题】MVC Web API & jsonp【英文标题】:MVC web API & jsonp 【发布时间】:2013-11-12 05:57:37 【问题描述】:

我正在尝试找到一种方法来包装一个带有 jsonp 回调的 json 响应。我遇到的问题是我不想使用“JsonResult”类来构造响应,因为它用自己的对象包装它,就好像我直接返回模型一样,它被正确序列化为 json。

到目前为止,我已经尝试使用“ActionFilter”,但无法找到在执行操作后如何包装结果。

任何方向都将不胜感激

【问题讨论】:

***.com/questions/12347461/… @Francis 谢谢,这是最简单的方法,它解决了我的问题。 【参考方案1】:

我一直在走这条路,并且可以提供以下代码,将 JsonP 调用封装到 ActionResult 中,向控制器添加一个方法,允许您优先考虑所需的 ActionResult 类型,以及几个扩展方法把它们粘在一起。唯一的要求是一致地命名您的回调参数,以便可以可靠地从请求中剔除它。

一、派生的ActionResult:

using System;
using System.Text;
using System.Web;
using System.Web.Mvc;
using System.Web.Script.Serialization;

namespace CL.Enterprise.Components.Web.Mvc

    /// <summary>
    /// Extension of JsonResult to handle JsonP requests
    /// </summary>
    public class JsonPResult : ActionResult
    
        private javascriptSerializer _jser = new JavaScriptSerializer();                

        public Encoding ContentEncoding  get; set; 
        public string ContentType  get; set; 
        public object Data  get; set; 
        public string JsonCallback  get; set; 

        public JsonPResult()  

        /// <summary>
        /// Package and return the result
        /// </summary>
        public override void ExecuteResult(ControllerContext Context)
        
            //Context.IsChildAction

            if (Context == null)
            
                throw new ArgumentNullException("Context");
            

            JsonCallback = Context.HttpContext.Request["callback"];

            if (string.IsNullOrEmpty(JsonCallback))
            
                JsonCallback = Context.HttpContext.Request["jsoncallback"];
            

            if (string.IsNullOrEmpty(JsonCallback))
            
                throw new ArgumentNullException("JsonP callback parameter required for JsonP response.");
            

            HttpResponseBase CurrentResponse = Context.HttpContext.Response;

            if (!String.IsNullOrEmpty(ContentType))
            
                CurrentResponse.ContentType = ContentType;
            
            else
            
                CurrentResponse.ContentType = "application/json";
            

            if (ContentEncoding != null)
            
                CurrentResponse.ContentEncoding = ContentEncoding;
            

            if (Data != null)
            
                CurrentResponse.Write(string.Format("0(1);", JsonCallback, _jser.Serialize(Data)));
            
        
    

接下来,Controller 扩展方法:

using System.IO;
using System.Web.Mvc;

namespace CL.Enterprise.Components.Web.Mvc

    /// <summary>
    /// Extension methods for System.Web.Mvc.Controller
    /// </summary>
    public static class ContollerExtensions
    
        /// <summary>
        /// Method to return a JsonPResult
        /// </summary>
        public static JsonPResult JsonP(this Controller controller, object data)
        
            JsonPResult result = new JsonPResult();
            result.Data = data;
            //result.ExecuteResult(controller.ControllerContext);
            return result;
        

        /// <summary>
        /// Get the currently named jsonp QS parameter value
        /// </summary>
        public static string GetJsonPCallback(this Controller controller)
        
            return 
                controller.ControllerContext.RequestContext.HttpContext.Request.QueryString["callback"] ?? 
                controller.ControllerContext.RequestContext.HttpContext.Request.QueryString["jsoncallback"] ?? 
                string.Empty;
        
    

最后,将此方法添加到您的控制器中:

        /// <summary>
        /// Gets an ActionResult, either as a jsonified string, or rendered as normally
        /// </summary>
        /// <typeparam name="TModel">Type of the Model class</typeparam>
        /// <param name="UsingJson">Do you want a JsonResult?</param>
        /// <param name="UsingJsonP">Do you want a JsonPResult? (takes priority over UsingJson)</param>
        /// <param name="Model">The model class instance</param>        
        /// <param name="RelativePathToView">Where in this webapp is the view being requested?</param>
        /// <returns>An ActionResult</returns>
        public ActionResult GetActionResult<T>(T Model, bool UsingJsonP, bool UsingJson, string RelativePathToView)
        
            string ViewAsString =
                this.RenderView<T>(
                    RelativePathToView,
                    Model
                );

            if (UsingJsonP) //takes priority
            
                string Callback = this.GetJsonPCallback();
                JsonPResult Result = this.JsonP(ViewAsString.Trim());
                return Result;
            

            if (UsingJson)//secondary
            
                return Json(ViewAsString.Trim(), JsonRequestBehavior.AllowGet);
            

            return View(Model); //tertiary
        

【讨论】:

以上是关于MVC Web API & jsonp的主要内容,如果未能解决你的问题,请参考以下文章

为网站和移动应用程序混合 MVC 5 + WEB API 2 身份验证

如何启用 CORS (JS + MVC Web API)

同一解决方案中的 MVC 和 Web Api 项目

一个 MVC Web 应用程序作为 API 和客户端

微擎MVC

Web API 中的 MVC-6 与 MVC-5 BearerAuthentication