MVC web API & jsonp



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

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

任何方向都将不胜感激

我一直在这条路上,可以提供以下代码,将 JsonP 调用封装到 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)));
            }
        }
    }
}

接下来,控制器扩展方法:

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
        }

最新更新