asp.net核心api模型中的datetimeoffset

时间:2019-03-06 03:25:21

标签: c# asp.net asp.net-core asp.net-core-2.1

我有这样的模型

class MyModel{
    public DateTimeOffset plannedStartDate {get;set;}
}

和类似的动作

[HttpPost]
public IActionResult Get(MyModel activityUpdate){
}

我正在从angular发送请求作为json

{
   plannedStartDate: 2019-03-04T16:00:00.000Z
}

这是一个有效日期

enter image description here

但是我在api中得到的是错误的

enter image description here

如果我在立即窗口中插入变量,则可以看到偏移无法正确解析 enter image description here

我试图将mvc选项更改为

service.AddMvc()
.AddJsonOptions(opt=>
    opt.SerializerSettings.DateParseHandling=DateParseHandling.DateTimeOffset);

这没有帮助,我不认为这与反序列化选项有关。 我还有其他编写自定义modelBinder的选项吗?

2 个答案:

答案 0 :(得分:1)

如果您的客户使用application/json发送请求,则控制器应指定[FromBody]以启用JsonInputFormatter来绑定模型。

public IActionResult Get([FromBody]MyModel activityUpdate)
{
    //your code.
}

对于启用绑定DateTimeOffset,您可以像

那样实现自己的JsonInputFormatter
public class DateTimeOffSetJsonInputFormatter : JsonInputFormatter
{
    private readonly JsonSerializerSettings _serializerSettings;
    public DateTimeOffSetJsonInputFormatter(ILogger logger
        , JsonSerializerSettings serializerSettings
        , ArrayPool<char> charPool
        , ObjectPoolProvider objectPoolProvider
        , MvcOptions options
        , MvcJsonOptions jsonOptions) 
            : base(logger, serializerSettings, charPool, objectPoolProvider, options, jsonOptions)
    {
        _serializerSettings = serializerSettings;
    }

    public override async Task<InputFormatterResult> ReadRequestBodyAsync(InputFormatterContext context, Encoding encoding)
    {
        var request = context.HttpContext.Request;
        using (var reader = new StreamReader(request.Body))
        {
            var content = await reader.ReadToEndAsync();
            var resource = JObject.Parse(content);
            var result = JsonConvert.DeserializeObject(resource.ToString(), context.ModelType);
            foreach (var property in result.GetType().GetProperties())
            {
                if (property.PropertyType == typeof(DateTimeOffset))
                {
                    property.SetValue(result, DateTimeOffset.Parse(resource[property.Name].ToString()));
                }
            }
            return await InputFormatterResult.SuccessAsync(result);
        }
    }
}

一样在Startup.cs中注册
services.AddMvc(mvcOptions => {
    var serviceProvider = services.BuildServiceProvider();
    var jsonInputLogger = serviceProvider.GetRequiredService<ILoggerFactory>().CreateLogger<DateTimeOffSetJsonInputFormatter>();
    var jsonOptions = serviceProvider.GetRequiredService<IOptions<MvcJsonOptions>>().Value;
    var charPool = serviceProvider.GetRequiredService<ArrayPool<char>>();
    var objectPoolProvider = serviceProvider.GetRequiredService<ObjectPoolProvider>();

    var customJsonInputFormatter = new DateTimeOffSetJsonInputFormatter(
                jsonInputLogger,
                jsonOptions.SerializerSettings,
                charPool,
                objectPoolProvider,
                mvcOptions,
                jsonOptions
        );
    mvcOptions.InputFormatters.Insert(0, customJsonInputFormatter);
})
.SetCompatibilityVersion(CompatibilityVersion.Version_2_1);

答案 1 :(得分:1)

使用ISO 8601格式的字符串:"yyyy-MM-ddTHH:mm:ssZZZ"

这应该将您的日期正确绑定到DateTimeOffset,并应包含偏移值。