在我的项目中,我使用 DateTimeOffset 数据类型作为参数。我意识到偏移量总是“0”。但我需要服务器端的本地时间。为了解决这个问题,我在 http header 中发送 timezoneoffset 并将在创建 DateTimeOffset 参数时读取它。因此,我创建了一个 ModelBinder 来将请求转换为 DateTimeOffset 并从标题中获取 timezoneoffset。这是可行的,但是如果任何操作具有具有 DateTimeOffset 属性的复杂对象(通过 http POST 以 JSON 格式发送到 web api),则不会执行模型绑定(bind)器并且 DateTimeOffset 属性中的偏移量为“0”。有什么方法可以自定义从 JSON 创建对象的行为,以便我可以从 http header 中获取 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 header 加载 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;
    }
}

关于Asp.net Web API DateTimeOffset 从 http header 设置偏移量,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/20645227/

10-12 12:49