更改ASP MVC3中使用的默认JSON序列化程序

Tim*_*Tim 17 asp.net-mvc serialization json asp.net-mvc-3

我有一个控制器将大型JSON对象返回到jQuery Flot,我想知道用ServiceStack.Text中的那个更快地替换默认的JavaScriptSerializer是多么容易.

如果我可以使用DependencyResolver更改这样的东西会很好,但我想如果一切都解决了,那么它可能会变得很慢.

Muh*_*hid 41

你最好的办法是继承JsonResult类并重写Execute方法

public class CustomJsonResult: JsonResult
{
    public CustomJsonResult()
    {
       JsonRequestBehavior = JsonRequestBehavior.DenyGet;
    }
    public override void ExecuteResult(ControllerContext context) {
            if (context == null) {
                throw new ArgumentNullException("context");
            }
            if (JsonRequestBehavior == JsonRequestBehavior.DenyGet &&
                String.Equals(context.HttpContext.Request.HttpMethod, "GET", StringComparison.OrdinalIgnoreCase)) {
                throw new InvalidOperationException(MvcResources.JsonRequest_GetNotAllowed);
            }

            HttpResponseBase response = context.HttpContext.Response;

            if (!String.IsNullOrEmpty(ContentType)) {
                response.ContentType = ContentType;
            }
            else {
                response.ContentType = "application/json";
            }
            if (ContentEncoding != null) {
                response.ContentEncoding = ContentEncoding;
            }
            if (Data != null) {
                CustomJsSerializer serializer = new CustomJsSerializer();
                response.Write(serializer.Serialize(Data));
            }
        }
}
Run Code Online (Sandbox Code Playgroud)

代码来自mvc3的JsonResult类并更改了这一行

JavaScriptSerializer serializer = new JavaScriptSerializer();
Run Code Online (Sandbox Code Playgroud)

CustomJsSerializer serializer = new CustomJsSerializer();
Run Code Online (Sandbox Code Playgroud)

你可以在动作方法中使用这个类

public JsonResult result()
{
    var model = GetModel();
    return new CustomJsonResult{Data = model};
}
Run Code Online (Sandbox Code Playgroud)

另外,您可以覆盖Base控制器中的Controller类的json方法

public class BaseController:Controller
{
   protected internal override JsonResult Json(object data)
        {
            return new CustomJsonResult { Data = data };
        }
}
Run Code Online (Sandbox Code Playgroud)

现在,如果您拥有BaseController的所有控制器,那么return Json(data)将调用您的序列化方案.Json您还可以选择覆盖其他方法重载.

  • 它只是我还是MvcResources.JsonRequest_GetNotAllowed标记为内部? (7认同)
  • 不,但JsonResult Json(对象数据,字符串contentType,编码contentEncoding)是,而另一个只是委托那里.太开心了:) (6认同)
  • 显然,您需要覆盖具有4个参数的一个:protected override JsonResult Json(object data,string contentType,Encoding contentEncoding,JsonRequestBehavior behavior) (4认同)

Joe*_*ger 5

我正在添加这个答案只是因为我正在使用一个不需要覆盖System.Web.Mvc.Controller类的备用解决方案.我将以下扩展方法添加到System.Web.Mvc.Controller类.此解决方案的唯一"好处"是它不需要您更改代码生成的Controller类的基类.否则,它在功能上等同于接受的答案.

public static JsonResult ToJsonResult(this Controller controller, 
                                          object target, 
                                          string contentType, 
                                          Encoding contentEncoding,
                                          JsonRequestBehavior behavior)
    {
        if (target != null)
        {
            if (target.GetType().HasAttribute<DataContractAttribute>())
            {
                return new DataContractJsonResult() { ContentType = contentType, ContentEncoding = contentEncoding, JsonRequestBehavior = behavior, Data = target };
            }
        }
        return new JsonResult() { ContentType = contentType, ContentEncoding = contentEncoding, JsonRequestBehavior = behavior, Data = target };
    }

    public static JsonResult ToJsonResult(this Controller controller, object target)
    {
        return controller.ToJsonResult(target, null, null, JsonRequestBehavior.DenyGet);
    }

    public static JsonResult ToJsonResult(this Controller controller, object target, string contentType)
    {
        return controller.ToJsonResult(target, contentType, null, JsonRequestBehavior.DenyGet);
    }

    public static JsonResult ToJsonResult(this Controller controller, object target, string contentType, Encoding contentEncoding)
    {
        return controller.ToJsonResult(target, contentType, contentEncoding, JsonRequestBehavior.DenyGet);
    }

    public static JsonResult ToJsonResult(this Controller controller, object target, string contentType, JsonRequestBehavior behavior)
    {
        return controller.ToJsonResult(target, contentType, null, behavior);
    }
Run Code Online (Sandbox Code Playgroud)

在我的应用程序中,如果类型具有DataContract属性,则覆盖默认控制器并使用JSON.NET序列化程序.此功能封装在DataContractJsonResult类中,该类未包含在内,但是在接受此问题的答案中的类之后建模.