简体   繁体   中英

datetimeoffset in the asp.net core api model

i have a model like this

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

and an action like this

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

and i'm sending request from angular as a json

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

which is a valid date

在此处输入图片说明

but what i'm getting in the api is wrong

在此处输入图片说明

if i inspet the variable in the immediate windows i can see that the offset couldnt' parse correctly在此处输入图片说明

i tried to change the mvc options to

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

which didn't help, i dont' think it's about deserialize options. do i have any other optiosn that writing custom modelBinder?

If your client send request with application/json , the controller should specify [FromBody] to enable JsonInputFormatter to bind the model.

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

For enable binding DateTimeOffset , you could implement your own JsonInputFormatter like

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);
        }
    }
}

Register it in Startup.cs like

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);

Use the ISO 8601 format string: "yyyy-MM-ddTHH:mm:ssZZZ"

This should bind your date properly to DateTimeOffset, and should include the offset value.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM