Как сообщить ASP.Net MVC, что все входящие даты, десериализованные из JSon, должны быть UTC?

Я отправляю даты из своего веб-приложения в формате UTC, но когда я получаю их на стороне сервера, сериализатор JSon (который, вероятно, используется при настройке вашей модели) делает это в локальной дате и времени с помощью DateTimeKind.Local относительно часового пояса сервера.

Когда я делаю DateTime.ToUniversalTime(), я получаю правильную дату UTC, поэтому это не проблема. Конверсия работает правильно, и даты отправляются так, как они должны... но.... Мне не нравится звонить в "ToUniversalTime()" в каждую дату моей модели, прежде чем я буду хранить ее в базе данных... Это подвержено ошибкам и легко забывается, когда у вас есть большое приложение.

Итак, вот вопрос: есть ли способ сообщить MVC, что входящие даты всегда должны быть выражены в формате UTC?

1 ответ

После копания немного больше, я нашел способ сделать эту работу.

Проблема заключалась не столько в сериализаторе, сколько в том, что даты модели не выражены в UTC, а в локальное время. ASP.Net позволяет создавать пользовательские привязки моделей, и я думаю, что это ключ к изменению дат в UTC после их десериализации.

Я использовал следующий код, чтобы сделать эту работу, может быть несколько ошибок, чтобы сгладить, но вы получите идею:

public class UtcModelBinder : DefaultModelBinder
{
 protected override void SetProperty(ControllerContext controllerContext, ModelBindingContext bindingContext, System.ComponentModel.PropertyDescriptor propertyDescriptor, object value)
 {
 HttpRequestBase request = controllerContext.HttpContext.Request;
 // Detect if this is a JSON request
 if (request.IsAjaxRequest() &&
 request.ContentType.StartsWith("application/json", StringComparison.OrdinalIgnoreCase))
 {
 // See if the value is a DateTime
 if (value is DateTime)
 {
 // This is ****** casting, but since it a value type there not much other things we can do
 DateTime dateValue = (DateTime)value;
 if (dateValue.Kind == DateTimeKind.Local)
 {
 // Change it
 DateTime utcDate = dateValue.ToUniversalTime();
 if (!propertyDescriptor.IsReadOnly && propertyDescriptor.PropertyType == typeof(DateTime))
 propertyDescriptor.SetValue(bindingContext.Model, utcDate);
 return;
 }
 }
 }
 // Fall back to the default behavior
 base.SetProperty(controllerContext, bindingContext, propertyDescriptor, value);
 }
}

licensed under cc by-sa 3.0 with attribution.