使用JSON.NET作为ASP.NET MVC 3中的默认JSON序列化程序 – 有可能吗?

是否有可能在ASP.NET MVC 3中使用JSON.NET作为默认的JSON序列化程序?

根据我的研究,似乎要做到这一点的唯一方法是将ActionResult扩展为MVC3中的JsonResult不是虚拟的 …

我希望在ASP.NET MVC 3中有一种方法可以指定一个可序列化为JSON的可插件提供者。

思考?

我相信最好的办法就是 – 如你的链接所述 – 直接扩展ActionResult或扩展JsonResult。

至于在控制器上不是虚拟的方法JsonResult是不正确的,只需select正确的重载。 这很好:

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

编辑1 :JsonResult扩展名…

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

编辑2 :我删除了数据为空根据下面的build议检查。 这应该使更新版本的JQuery开心,似乎是理智的事情,因为响应可以无条件反序列化。 但请注意,这不是来自ASP.NET MVC的JSON响应的默认行为,在没有数据的情况下,响应的是空string。

我实现了这个,而不需要一个基础控制器或注入。

我用动作filter来replaceJsonResult的JsonResult。

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

在Global.asax.cs中的Application_Start()你需要添加:

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

为了完成的目的,下面是我从其他地方拿起的JsonNetResult扩展类,稍微修改以获得正确的传输支持:

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

我知道这是问题已被回答后,但我正在使用不同的方法,因为我正在使用dependency injection来实例化我的控制器。

我已经用一个覆盖InvokeActionMethod方法的版本replace了IActionInvoker(通过注入控制器的ControllerActionInvoker属性)。

这意味着不会改变控制器的inheritance,当升级到MVC4时,可以很容易地将其删除,方法是更改​​所有控制器的DI容器注册

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

—编辑 – 更新显示控制器的容器注册。 我在这里使用Unity。

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

使用Newtonsoft的JSON转换器:

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

https://stackoverflow.com/users/183056/sami-beyoglu上的答案扩展,如果你设置内容types,那么jQuery将能够将返回的数据转换为一个对象为你。;

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

我做了一个版本,使Web服务行为types安全和简单。 你这样使用它:

 public JsonResult<MyDataContract> MyAction() { return new MyDataContract(); } 

class上:

 public class JsonResult<T> : JsonResult { public JsonResult(T data) { Data = data; JsonRequestBehavior = JsonRequestBehavior.AllowGet; } public override void ExecuteResult(ControllerContext context) { // Use Json.Net rather than the default JavaScriptSerializer because it's faster and better 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; var serializedObject = JsonConvert.SerializeObject(Data, Formatting.Indented); response.Write(serializedObject); } public static implicit operator JsonResult<T>(T d) { return new JsonResult<T>(d); } }