2013-12-17 3 views
2

В моем проекте я использую тип данных DateTimeOffset для параметров. Я понял, что смещение всегда «0». Но мне нужно местное время на сервере. Чтобы исправить это, я отправляю timezoneoffset в http-заголовке и прочитаю это при создании параметра DateTimeOffset. Поэтому я создал ModelBinder для преобразования запроса в DateTimeOffset и получить timezoneoffset из заголовка. Это работает, но если какое-либо действие имеет сложный объект с свойством DateTimeOffset (отправка через http POST в веб-api в формате JSON), значит, модельная строка не была выполнена, а смещение в свойстве DateTimeOffset равно «0». Есть ли способ настроить поведение создания объектов из JSON, чтобы я мог получить timezoneoffset из заголовка http?Asp.net Web API DateTimeOffset set offset from http header

public class DateTimeOffsetModelBinder : IModelBinder 
{ 
    public bool BindModel(HttpActionContext actionContext, ModelBindingContext bindingContext) 
    { 
     if (bindingContext.ModelType != typeof(DateTimeOffset)) 
     { 
      return false; 
     } 

     var timezoneOffsetMinutes = actionContext.Request.Headers 
      .Where(h => String.Equals(h.Key, "TimezoneOffsetMinutes", StringComparison.InvariantCultureIgnoreCase)) 
      .SelectMany(h => h.Value) 
      .FirstOrDefault() 
      .ParseAsNullableInteger(); 

     if (!timezoneOffsetMinutes.HasValue) 
     { 
      bindingContext.ModelState.AddModelError(bindingContext.ModelName, "Http header dosn't contains 'timezoneoffsetminutes'."); 

      return false; 
     } 

     TimeSpan timezoneOffset = TimeSpan.FromMinutes(timezoneOffsetMinutes.Value); 

     ValueProviderResult value = bindingContext.ValueProvider.GetValue(bindingContext.ModelName); 
     DateTime date; 

     if (!DateTime.TryParse(value.AttemptedValue, out date)) 
     { 
      bindingContext.ModelState.AddModelError(bindingContext.ModelName, "Can't parse parameter '" + bindingContext.ModelName + "' to DateTime."); 

      return false; 
     } 

     date = date.ToUniversalTime(); 

     bindingContext.Model = new DateTimeOffset(date).ToOffset(timezoneOffset); 

     return true; 
    } 
} 
+0

Лично я считаю, что вы используете неправильный подход, используя 'DateTimeOffset'. Почему вы не можете использовать время UTC во всем приложении и настраивать часовой пояс только на стороне клиента? – Dai

+0

Да, я использую UTC раз в своем приложении и храню UTC в базе данных. Но мне нужно смещение от клиента, например. для вычисления правильного времени начала и окончания дня (для получения списка со всеми назначениями назначений дня). –

ответ

4

Теперь у меня есть решение: Я реализован собственный JsonConverter основе из IsoDateTimeConverter Wich загружает timezoneoffset из заголовка HTTP Заданная его в DateTimeOffset правильно.

public class DateTimeOffsetConverter : IsoDateTimeConverter 
{ 
    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) 
    { 
     object baseResult = base.ReadJson(reader, objectType, existingValue, serializer); 
     DateTimeOffset? date = baseResult as DateTimeOffset?; 

     if (date.HasValue) 
     { 
      //timezone offset 
      int? timezoneOffsetMinutes = HttpContext.Current.Request.Headers["TimezoneOffsetMinutes"].ParseAsNullableInteger(); 
      TimeSpan? timezoneOffset = timezoneOffsetMinutes.HasValue 
       ? TimeSpan.FromMinutes(timezoneOffsetMinutes.Value) 
       : (TimeSpan?)null; 

      return timezoneOffset.HasValue 
       ? date.Value.ToOffset(timezoneOffset.Value) 
       : date.Value; 
     } 

     return baseResult; 
    } 
}