0

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

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

任何方向都将不胜感激

4

1 回答 1

3

我一直在走这条路,并且可以提供以下代码,将 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
        }
于 2013-11-01T03:25:36.477 回答