简体   繁体   English

MVC Web API和jsonp

[英]MVC web API & jsonp

I'm trying to find a way to wrap aa json response with a callback for jsonp. 我正在尝试找到一种方法来包装带有jsonp回调的json响应。 The problem I am running into though is I don't want to use the 'JsonResult' class to construct the response as it wraps it with its own object where as if I return the model directly it is properly serialized to json. 我遇到的问题是,我不想使用'JsonResult'类构造响应,因为它用自己的对象包装了响应,就像我直接返回模型一样,它已正确序列化为json。

So far I have tried using the a 'ActionFilter' but couldn't find out how I could wrap the result after the action executed. 到目前为止,我已经尝试过使用“ ActionFilter”,但是在执行动作后无法找到如何包装结果的方法。

Any direction at all would be appreciated 任何方向都将不胜感激

I've been down this road, and can offer the following code which encapsulates JsonP calls into an ActionResult, adds a method to your Controller which allows you to prioritize the type of ActionResult you want, and a couple of extension methods to glue it all together. 我一直走这条路,可以提供以下代码,将JsonP调用封装到ActionResult中,为Controller添加一个方法,该方法可以让您优先确定所需的ActionResult类型,以及几个扩展方法来将其粘合在一起一起。 The only requirement is to consistently name your callback parameter, so it can be reliably culled from the Request. 唯一的要求是一致地命名您的回调参数,以便可以从“请求”中可靠地剔除该参数。

First, the derived 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)));
            }
        }
    }
}

Next, the Controller extension methods: 接下来,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;
        }
    }
}

Finally, add this method to your Controller: 最后,将此方法添加到Controller中:

        /// <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
        }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM