ASP.NET MVC控制器单方法如何配置反序列化时将DateTime设为UTC?
局部配置DateTime反序列化为Utc类型的实现方案
以下方案均不会修改全局配置,仅作用于目标方法/控制器:
方案1:仅对目标Action参数生效(最精准)
适合只需要修改UpdateCalendar方法的newCalendar参数反序列化规则的场景:
- 自定义支持Utc时间反序列化的Json模型绑定器:
using Newtonsoft.Json; using System.Web.Mvc; using System.IO; using System.Globalization; public class UtcDateTimeJsonModelBinder : IModelBinder { private static readonly JsonSerializerSettings _serializerSettings = new JsonSerializerSettings { // 强制将带Z标识的日期反序列化为Utc类型 DateTimeZoneHandling = DateTimeZoneHandling.Utc, // 匹配客户端传入的日期格式,可根据实际情况调整 DateFormatString = "dd/MM/yyyy HH:mm:ssZ", // 其余配置保持和全局序列化配置一致即可 Culture = CultureInfo.InvariantCulture }; public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) { controllerContext.HttpContext.Request.InputStream.Position = 0; using (var streamReader = new StreamReader(controllerContext.HttpContext.Request.InputStream)) { string jsonContent = streamReader.ReadToEnd(); return JsonConvert.DeserializeObject(jsonContent, bindingContext.ModelType, _serializerSettings); } } }
- 在目标方法的参数上绑定该模型绑定器:
public PartialViewResult UpdateCalendar(long id, [ModelBinder(typeof(UtcDateTimeJsonModelBinder))] List<List<CalendarDay>> newCalendar, int selectedMonth) { // 此处newCalendar内所有DateTime对象的Kind属性均为Utc }
方案2:对控制器下所有Action生效
如果需要当前控制器所有接口的DateTime反序列化都使用Utc规则,可以自定义ActionFilter特性:
using Newtonsoft.Json; using System.Web.Mvc; using System.IO; using System.Globalization; using System; public class UtcDateTimeSerializationAttribute : ActionFilterAttribute { private static readonly JsonSerializerSettings _serializerSettings = new JsonSerializerSettings { DateTimeZoneHandling = DateTimeZoneHandling.Utc, DateFormatString = "dd/MM/yyyy HH:mm:ssZ", Culture = CultureInfo.InvariantCulture }; public override void OnActionExecuting(ActionExecutingContext filterContext) { var request = filterContext.HttpContext.Request; if (request.ContentType.StartsWith("application/json", StringComparison.OrdinalIgnoreCase)) { request.InputStream.Position = 0; using (var streamReader = new StreamReader(request.InputStream)) { string jsonContent = streamReader.ReadToEnd(); // 反序列化所有复杂类型参数 foreach (var parameter in filterContext.ActionDescriptor.GetParameters()) { if (parameter.ParameterType.IsPrimitive || parameter.ParameterType == typeof(string)) { continue; } object paramValue = JsonConvert.DeserializeObject(jsonContent, parameter.ParameterType, _serializerSettings); filterContext.ActionParameters[parameter.ParameterName] = paramValue; } } } base.OnActionExecuting(filterContext); } }
将该特性直接贴在目标控制器类上即可:
[UtcDateTimeSerialization] public class YourController : Controller { // 控制器内所有Action的DateTime参数均会反序列化为Utc类型 }
表单提交场景适配
如果参数是表单格式而非Json格式传递,可针对DateTime类型自定义模型绑定器,在CalendarDay类的DateTime属性上单独绑定:
public class UtcDateTimeModelBinder : IModelBinder { public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) { ValueProviderResult valueResult = bindingContext.ValueProvider.GetValue(bindingContext.ModelName); if (valueResult == null || string.IsNullOrEmpty(valueResult.AttemptedValue)) { return null; } // 强制识别Z标识为UTC时间,转换后保留Utc的Kind属性 if (DateTime.TryParse(valueResult.AttemptedValue, CultureInfo.InvariantCulture, DateTimeStyles.AdjustToUniversal | DateTimeStyles.AssumeUniversal, out DateTime utcDate)) { return DateTime.SpecifyKind(utcDate, DateTimeKind.Utc); } return valueResult.ConvertTo(bindingContext.ModelType); } }
在属性上声明即可:
public class CalendarDay { [ModelBinder(typeof(UtcDateTimeModelBinder))] public DateTime YourDateProperty { get; set; } }
内容的提问来源于stack exchange,提问作者markzzz
相关产品推荐
相关产品推荐

