Как сообщить ASP.Net MVC, что все входящие даты, десериализованные из JSon, должны быть в формате UTC? - PullRequest
8 голосов
/ 03 марта 2012

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

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

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

1 Ответ

3 голосов
/ 03 марта 2012

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

Проблема не столько в сериализаторе, сколько в том, что даты модели выражены не в 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 double casting, but since it's a value type there's 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);

  }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...