在我的项目中,我使用DateTimeOffset数据类型作为参数。我意识到偏移量总是"0"。但我需要服务器端的本地时间。为了解决这个问题,我在http头中发送了timezoneoffset,并将在创建DateTimeOffset参数时读取它。因此,我创建了一个ModelBinder来将请求转换为DateTimeOffset,并从标头中获取timezoneoffset。这是可行的,但如果任何操作都有一个具有DateTimeOffset属性的复杂对象(通过http POST以JSON格式发送到web api),则模型绑定器没有执行,DateTimeOffsets属性中的偏移量为"0"。有没有什么方法可以自定义从JSON创建对象的行为,这样我就可以从http头中获得timezoneoffset?
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;
}
}
现在我有了一个解决方案:我在IsoDateTimeConverter的基础上实现了自己的JsonConverter,它从http头加载timezoneoffset并将其正确设置为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;
}
}