76 votos

Uso JSON.net como predeterminada JSON serializador en ASP.NET MVC 3 - ¿Es posible?

Es posible el uso de JSON.net como predeterminada JSON serializador en ASP.NET MVC 3?

Según mis investigaciones, parece que la única manera de lograr esto es a extender ActionResult como JsonResult en MVC3 no es virtual...

Yo esperaba que con MVC3 que no sería una manera de especificar un proveedor conectable para serializar a JSON.

Pensamientos?

84voto

asgerhallas Puntos 5134

Yo creo que la mejor manera de hacerlo, es - como se describe en sus enlaces para ampliar el ActionResult o ampliar JsonResult directamente.

En cuanto al método JsonResult que no es virtual en el controlador que no es cierto, sólo tiene que elegir el derecho de sobrecarga. Esto funciona bien:

protected override JsonResult Json(object data, string contentType, Encoding contentEncoding)

EDIT 1: UN JsonResult de extensión...

public class JsonNetResult : JsonResult
{
    public override void ExecuteResult(ControllerContext context)
    {
        if (context == null)
            throw new ArgumentNullException("context");

        var response = context.HttpContext.Response;

        response.ContentType = !String.IsNullOrEmpty(ContentType) 
            ? ContentType 
            : "application/json";

        if (ContentEncoding != null)
            response.ContentEncoding = ContentEncoding;

        // If you need special handling, you can call another form of SerializeObject below
        var serializedObject = JsonConvert.SerializeObject(Data, Formatting.Indented);
        response.Write(serializedObject);
    }

EDIT 2: he quitado la verificación de Datos null según las sugerencias de a continuación. Que debería hacer nuevas versiones de JQuery feliz y parece la misma cosa que hacer, como la respuesta puede entonces ser incondicionalmente deserializa. Tenga en cuenta sin embargo, que este no es el comportamiento predeterminado de respuestas JSON de ASP.NET MVC, que más bien responde con una cadena vacía, cuando no hay datos.

28voto

MDB Puntos 111

Este es también mucho después de que la pregunta fue respondida pero he implementado esta sin la necesidad de un controlador de base o de inyección.

He utilizado filtros de acción para reemplazar el JsonResult con un JsonNetResult.

public class JsonHandlerAttribute : ActionFilterAttribute
{
    public override void OnActionExecuted(ActionExecutedContext filterContext)
    {
       var jsonResult = filterContext.Result as JsonResult;

        if (jsonResult != null)
        {
            filterContext.Result = new JsonNetResult
            {
                ContentEncoding = jsonResult.ContentEncoding,
                ContentType = jsonResult.ContentType,
                Data = jsonResult.Data,
                JsonRequestBehavior = jsonResult.JsonRequestBehavior
            };
        }

        base.OnActionExecuted(filterContext);            
    }
}

En el Global.asax.cs Application_Start() deberá agregar:

GlobalFilters.Filters.Add(new JsonHandlerAttribute());

Para la terminación del amor, de aquí es mi JsonNetResult extensión de la clase que me recogió en algún lugar y que he modificado ligeramente para conseguir el correcto vapor de apoyo:

public class JsonNetResult : JsonResult
{
    public JsonNetResult()
    {
        Settings = new JsonSerializerSettings
        {
            ReferenceLoopHandling = ReferenceLoopHandling.Error                
        };
    }

    public JsonSerializerSettings Settings { get; private set; }

    public override void ExecuteResult(ControllerContext context)
    {
        if (context == null)
            throw new ArgumentNullException("context");
        if (this.JsonRequestBehavior == JsonRequestBehavior.DenyGet && string.Equals(context.HttpContext.Request.HttpMethod, "GET", StringComparison.OrdinalIgnoreCase))
            throw new InvalidOperationException("JSON GET is not allowed");

        HttpResponseBase response = context.HttpContext.Response;
        response.ContentType = string.IsNullOrEmpty(this.ContentType) ? "application/json" : this.ContentType;

        if (this.ContentEncoding != null)
            response.ContentEncoding = this.ContentEncoding;
        if (this.Data == null)
            return;

        var scriptSerializer = JsonSerializer.Create(this.Settings);
        scriptSerializer.Serialize(response.Output, this.Data);
    }
}

21voto

Robert Slaney Puntos 2491

Sé que esto es así después de que la pregunta haya sido respondida, pero estoy usando un enfoque diferente como estoy usando la inyección de dependencia para crear instancias de mi controladores.

He sustituido el IActionInvoker ( mediante la inyección del controlador ControllerActionInvoker Propiedad ) con una versión que reemplaza el InvokeActionMethod método.

Esto significa que no hay cambio en el controlador de la herencia y se puede quitar fácilmente cuando actualice a MVC4 por la alteración de la DI del contenedor de registro para TODOS los controladores

public class JsonNetActionInvoker : ControllerActionInvoker
{
    protected override ActionResult InvokeActionMethod(ControllerContext controllerContext, ActionDescriptor actionDescriptor, IDictionary<string, object> parameters)
    {
        ActionResult invokeActionMethod = base.InvokeActionMethod(controllerContext, actionDescriptor, parameters);

        if ( invokeActionMethod.GetType() == typeof(JsonResult) )
        {
            return new JsonNetResult(invokeActionMethod as JsonResult);
        }

        return invokeActionMethod;
    }

    private class JsonNetResult : JsonResult
    {
        public JsonNetResult()
        {
            this.ContentType = "application/json";
        }

        public JsonNetResult( JsonResult existing )
        {
            this.ContentEncoding = existing.ContentEncoding;
            this.ContentType = !string.IsNullOrWhiteSpace(existing.ContentType) ? existing.ContentType : "application/json";
            this.Data = existing.Data;
            this.JsonRequestBehavior = existing.JsonRequestBehavior;
        }

        public override void ExecuteResult(ControllerContext context)
        {
            if (context == null)
            {
                throw new ArgumentNullException("context");
            }
            if ((this.JsonRequestBehavior == JsonRequestBehavior.DenyGet) && string.Equals(context.HttpContext.Request.HttpMethod, "GET", StringComparison.OrdinalIgnoreCase))
            {
                base.ExecuteResult(context);                            // Delegate back to allow the default exception to be thrown
            }

            HttpResponseBase response = context.HttpContext.Response;
            response.ContentType = this.ContentType;

            if (this.ContentEncoding != null)
            {
                response.ContentEncoding = this.ContentEncoding;
            }

            if (this.Data != null)
            {
                // Replace with your favourite serializer.  
                new Newtonsoft.Json.JsonSerializer().Serialize( response.Output, this.Data );
            }
        }
    }
}

--- EDITAR - Actualizado a mostrar el contenedor registro para los controladores. Yo estoy usando la Unidad aquí.

private void RegisterAllControllers(List<Type> exportedTypes)
{
    this.rootContainer.RegisterType<IActionInvoker, JsonNetActionInvoker>();
    Func<Type, bool> isIController = typeof(IController).IsAssignableFrom;
    Func<Type, bool> isIHttpController = typeof(IHttpController).IsAssignableFrom;

    foreach (Type controllerType in exportedTypes.Where(isIController))
    {
        this.rootContainer.RegisterType(
            typeof(IController),
            controllerType, 
            controllerType.Name.Replace("Controller", string.Empty),
            new InjectionProperty("ActionInvoker")
        );
    }

    foreach (Type controllerType in exportedTypes.Where(isIHttpController))
    {
        this.rootContainer.RegisterType(typeof(IHttpController), controllerType, controllerType.Name);
    }
}

public class UnityControllerFactory : System.Web.Mvc.IControllerFactory, System.Web.Http.Dispatcher.IHttpControllerActivator
{
    readonly IUnityContainer container;

    public UnityControllerFactory(IUnityContainer container)
    {
        this.container = container;
    }

    IController System.Web.Mvc.IControllerFactory.CreateController(System.Web.Routing.RequestContext requestContext, string controllerName)
    {
        return this.container.Resolve<IController>(controllerName);
    }

    SessionStateBehavior System.Web.Mvc.IControllerFactory.GetControllerSessionBehavior(RequestContext requestContext, string controllerName)
    {
        return SessionStateBehavior.Required;
    }

    void System.Web.Mvc.IControllerFactory.ReleaseController(IController controller)
    {
    }

    IHttpController IHttpControllerActivator.Create(HttpRequestMessage request, HttpControllerDescriptor controllerDescriptor, Type controllerType)
    {
        return this.container.Resolve<IHttpController>(controllerType.Name);
    }
}

16voto

Sami Beyoglu Puntos 27

Uso newtonsoft json converter

public ActionResult DoSomething()
    {
        dynamic cResponse = new ExpandoObject();
        cResponse.Property1 = "value1";
        cResponse.Property2 = "value2";
        return Content(JsonConvert.SerializeObject(cResponse));
    }

Iteramos.com

Iteramos es una comunidad de desarrolladores que busca expandir el conocimiento de la programación mas allá del inglés.
Tenemos una gran cantidad de contenido, y también puedes hacer tus propias preguntas o resolver las de los demás.

Powered by: