.NET Framework MVC中JsonResult序列化long为字符串失效如何解决
问题根源
你配置的所有Newtonsoft.Json相关序列化规则(包括属性[JsonConverter]注解、WebApiConfig中的全局转换器注册)仅对ASP.NET Web API接口生效。你的TestController继承的是System.Web.Mvc.Controller,返回的是MVC原生JsonResult,该类型默认使用.NET内置的JavaScriptSerializer做序列化,完全不会调用你配置的Newtonsoft.Json规则,所以所有转换器配置都不生效。
解决方案
可根据你的项目需求任选以下一种方案:
方案1:手动调用Newtonsoft序列化返回(快速验证,无需全局修改)
直接将接口返回值改为ContentResult,手动用JsonConvert序列化对象,会自动触发你定义的Int64JsonConverter,属性上的[JsonConverter]注解也会生效:
[HttpGet,Route("Test2")] public ContentResult Test2() { var customer = new Customer { Id = long.MaxValue, Name = "test15" }; string json = JsonConvert.SerializeObject(customer); return Content(json, "application/json"); }
方案2:自定义Newtonsoft专用JsonResult,全局统一MVC序列化规则
如果希望所有MVC控制器的Json返回都默认使用Newtonsoft.Json,统一序列化规则,可按如下步骤修改:
- 自定义
JsonNetResult类替换原生JsonResult
public class JsonNetResult : JsonResult { public JsonSerializerSettings SerializerSettings { get; set; } public JsonNetResult() { SerializerSettings = new JsonSerializerSettings { // 全局注册long转字符串转换器,注册后属性上不需要再加注解 Converters = new List<JsonConverter> { new Int64JsonConverter() } }; } public override void ExecuteResult(ControllerContext context) { if (context == null) throw new ArgumentNullException(nameof(context)); if (JsonRequestBehavior == JsonRequestBehavior.DenyGet && string.Equals(context.HttpContext.Request.HttpMethod, "GET", StringComparison.OrdinalIgnoreCase)) { throw new InvalidOperationException("不允许GET请求获取JSON数据"); } HttpResponseBase response = context.HttpContext.Response; response.ContentType = string.IsNullOrEmpty(ContentType) ? "application/json" : ContentType; if (ContentEncoding != null) response.ContentEncoding = ContentEncoding; if (Data != null) { var writer = new JsonTextWriter(response.Output) { Formatting = Formatting.None }; JsonSerializer.Create(SerializerSettings).Serialize(writer, Data); writer.Flush(); } } }
- 给控制器添加扩展方法简化调用
public static class ControllerExtensions { public static JsonNetResult JsonNet(this Controller controller, object data, JsonRequestBehavior behavior = JsonRequestBehavior.AllowGet) { return new JsonNetResult { Data = data, JsonRequestBehavior = behavior }; } }
- 接口直接返回自定义
JsonNetResult即可
[HttpGet,Route("Test2")] public JsonNetResult Test2() { var customer = new Customer { Id = long.MaxValue, Name = "test15" }; return this.JsonNet(customer); }
方案3:将控制器改为Web API控制器
如果该接口仅做数据返回,没有视图渲染需求,直接将TestController的父类从Controller改为ApiController,你之前在WebApiConfig中配置的全局转换器就会自动生效,不需要修改接口返回值写法。
内容的提问来源于stack exchange,提问作者dimmits
相关产品推荐
相关产品推荐

