是否可以将JSON.NET用作ASP.NET MVC 3中的默认JSON序列化程序?
根据我的研究,似乎完成此操作的唯一方法是扩展ActionResult,因为MVC3中的JsonResult不是虚拟的 ...
我希望使用ASP.NET MVC 3,可以有一种方法来指定可插拔的提供程序以序列化为JSON。
有什么想法吗?
是否可以将JSON.NET用作ASP.NET MVC 3中的默认JSON序列化程序?
根据我的研究,似乎完成此操作的唯一方法是扩展ActionResult,因为MVC3中的JsonResult不是虚拟的 ...
我希望使用ASP.NET MVC 3,可以有一种方法来指定可插拔的提供程序以序列化为JSON。
有什么想法吗?
Answers:
我相信最好的方法是-如您的链接中所述-扩展ActionResult或直接扩展JsonResult。
至于JsonResult在控制器上不是虚拟的不是真的方法,只需选择正确的重载即可。这很好用:
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:按照以下建议,我删除了Data为null的检查。这应该使新版本的JQuery感到高兴,并且看起来很明智,因为可以无条件反序列化响应。但是请注意,这不是来自ASP.NET MVC的JSON响应的默认行为,当没有数据时,它将以空字符串进行响应。
if (this.JsonRequestBehavior == JsonRequestBehavior.DenyGet && string.Equals(context.HttpContext.Request.HttpMethod, "GET", StringComparison.OrdinalIgnoreCase)) throw new InvalidOperationException(MvcResources.JsonRequest_GetNotAllowed);
如何?我认为需要在答案中添加此检查(没有内部MvcResources.JsonRequest_GetNotAllowed
但有一些自定义消息)另外,另外2个默认的asp.net mvc检查-MaxJsonLength和RecursionLimit又如何呢?如果使用json.net,是否需要它们?
我无需基本控制器或注入就实现了这一点。
我使用动作过滤器将JsonResult替换为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);
}
}
在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);
}
}
return Json()
实际上使用Json.Net。
JsonResult
from Json()
并将其转换为a JsonNetResult
。as
如果无法进行转换,则使用返回null 的关键字来实现。很漂亮 格兰芬多10分!
[BetterJsonHandler]
:-)。
使用Newtonsoft的JSON转换器:
public ActionResult DoSomething()
{
dynamic cResponse = new ExpandoObject();
cResponse.Property1 = "value1";
cResponse.Property2 = "value2";
return Content(JsonConvert.SerializeObject(cResponse), "application/json");
}
我知道在回答问题后一切都很好,但是我使用了一种不同的方法,因为我使用依赖注入来实例化我的控制器。
我已经用覆盖InvokeActionMethod方法的版本替换了IActionInvoker(通过注入控制器的ControllerActionInvoker属性)。
这意味着无需更改控制器继承,并且当我通过更改所有控制器的DI容器的注册升级到MVC4时,可以轻松删除它
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);
}
}
扩展来自https://stackoverflow.com/users/183056/sami-beyoglu的答案,如果您设置了Content类型,那么jQuery将能够为您将返回的数据转换为对象。
public ActionResult DoSomething()
{
dynamic cResponse = new ExpandoObject();
cResponse.Property1 = "value1";
cResponse.Property2 = "value2";
return Content(JsonConvert.SerializeObject(cResponse), "application/json");
}
JObject jo = GetJSON(); return Content(jo.ToString(), "application/json");
我的帖子可能会对某人有所帮助。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web;
using System.Web.Mvc;
namespace MultipleSubmit.Service
{
public abstract class BaseController : Controller
{
protected override JsonResult Json(object data, string contentType,
Encoding contentEncoding, JsonRequestBehavior behavior)
{
return new JsonNetResult
{
Data = data,
ContentType = contentType,
ContentEncoding = contentEncoding,
JsonRequestBehavior = behavior
};
}
}
}
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Web;
using System.Web.Mvc;
namespace MultipleSubmit.Service
{
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);
using (var sw = new StringWriter())
{
scriptSerializer.Serialize(sw, this.Data);
response.Write(sw.ToString());
}
}
}
}
public class MultipleSubmitController : BaseController
{
public JsonResult Index()
{
var data = obj1; // obj1 contains the Json data
return Json(data, JsonRequestBehavior.AllowGet);
}
}
BaseController
,这对chang的影响是最小的-只需添加类和更新即可BaseController
。
我制作了一个使Web服务操作类型安全且简单的版本。您可以这样使用它:
public JsonResult<MyDataContract> MyAction()
{
return new MyDataContract();
}
班上:
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);
}
}