2011-07-30 10 views
17

Tengo un controlador que devuelve grandes objetos JSON a jQuery Flot y me preguntaba qué fácil sería reemplazar el JavaScriptSerializer predeterminado con algo más rápido como el de ServiceStack.Text.Cambiar serializador JSON predeterminado utilizado en ASP MVC3

Sería bueno si pudiera cambiar este tipo de cosas usando DependencyResolver, pero supongo que si todo se resolviera, podría ser bastante lento.

+0

relacionado: http://stackoverflow.com/questions/7109967/using-json-net-as-default-json-serializer-in-asp-net-mvc-3-is-it-possible –

+1

Pregunté esto pregunta 2 semanas antes del duplicado vinculado ... ¡Eso hace que la otra cuestione el duplicado! – Tim

Respuesta

40

su mejor apuesta es a heredar de la clase JsonResult y anular Ejecutar método como

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)); 
      } 
     } 
} 

código se toma de la clase JsonResult de MVC3 y cambió esta línea

JavaScriptSerializer serializer = new JavaScriptSerializer(); 

a

CustomJsSerializer serializer = new CustomJsSerializer(); 

puede usar esta clase en el método de acción como

public JsonResult result() 
{ 
    var model = GetModel(); 
    return new CustomJsonResult{Data = model}; 
} 

Además, puede reemplazar el método de la clase JSON controlador en el controlador de base como

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

ahora si tiene todos sus controladores de BaseController continuación return Json(data) llamará a su esquema de serialización. También hay otras sobrecargas del método Json que puede elegir anular.

+0

En asp.net MVC 3 el método - JsonResult Json (datos de objeto) no es virtual :( – Maxim

+6

No, pero JsonResult Json (datos de objeto, string contentType, Codificación de codificación de contenido) es, y el otro simplemente delega allí. :) – asgerhallas

+3

Aparentemente, debes anular el que tiene 4 parámetros: anulación protegida JsonResult Json (datos de objeto, string contentType, codificación ContentEncoding, comportamiento de JsonRequestBehavior) – Daniel

5

Agregué esta respuesta simplemente porque estoy usando una solución alternativa que no requiere anular la clase System.Web.Mvc.Controller. Agrego los siguientes métodos de extensión a la clase System.Web.Mvc.Controller. El único "beneficio" de esta solución es que no requiere que cambie la clase base de las clases de controlador generadas por el código. De lo contrario, es funcionalmente equivalente a la respuesta aceptada.

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); 
    } 

En mi solicitud, puedo reemplazar el controlador por defecto y utilizar el serializador JSON.NET si el tipo tiene el atributo DataContract. Esta funcionalidad está encapsulada en la clase DataContractJsonResult, que no está incluida, pero está modelada después de la clase en la respuesta aceptada a esta pregunta.

Cuestiones relacionadas