我有一个将大型JSON对象返回给jQuery Flot的控制器,我想知道用ServiceStack.Text中的那个更快地替换默认的JavaScriptSerializer是多么容易。
如果我可以使用DependencyResolver更改这样的东西会很好,但我想如果一切都解决了,那么它可能会变得很慢。
答案 0 :(得分:40)
最好的办法是继承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));
}
}
}
代码来自mvc3的JsonResult类并更改了这一行
JavaScriptSerializer serializer = new JavaScriptSerializer();
到
CustomJsSerializer serializer = new CustomJsSerializer();
你可以在行动方法中使用这个类,如
public JsonResult result()
{
var model = GetModel();
return new CustomJsonResult{Data = model};
}
此外,您可以覆盖Base控制器中的Controller类的json方法,如
public class BaseController:Controller
{
protected internal override JsonResult Json(object data)
{
return new CustomJsonResult { Data = data };
}
}
现在,如果您拥有BaseController的所有控制器,那么return Json(data)
将调用您的序列化方案。您还可以选择覆盖Json
方法的其他重载。
答案 1 :(得分: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);
}
在我的应用程序中,如果类型具有DataContract属性,则覆盖默认控制器并使用JSON.NET序列化程序。此功能封装在DataContractJsonResult类中,该类未包含在内,但是在接受此问题的答案中的类之后建模。