Question

One of the models for my WebAPI v4 endpoint has a field of type NodaTime.Instant. Model validation always reports that this fails (Model.IsValid == false), with the error message "Unexpected token parsing Instant. Expected String, got Date." which is clearly coming from NodaTime.

The request message does in fact pass the Instant as a string containing an ISO-8601 date, so it must be getting parsed to a BCL DateTime at some point before NodaTime gets it. I tried using OffsetDateTime and LocalDateTime, but got similar errors in each case.

So what should I do here? Should I pass something other than an Instant? Is there some other way to handle the parsing or validation that won't cause this error?

I've included a minimal repro below. It should fail if you POST to it with a request body like {"SomeInstant":"2013-08-13T17:51:22.1705292Z"}

using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Net;
using System.Net.Http;
using System.Web.Http;
using NodaTime;

namespace TestProject.Controllers
{
    /** Assume that we called GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings.ConfigureForNodaTime(DateTimeZoneProviders.Bcl) in Global.asax.cs **/
    public class NodaTimeController : ApiController
    {
        public Instant Post(TestModel m)
        {
            //ModelState.IsValid is always false due to error parsing the Instant field
            if (!ModelState.IsValid)
            {
                throw new HttpResponseException(Request.CreateErrorResponse(HttpStatusCode.BadRequest, ModelState));
            }
            return m.SomeInstant;
        }
    }

    public class TestModel
    {
        public Instant SomeInstant { get; set; }
    }
}
Was it helpful?

Solution

Thanks to the joys of Twitter, it looks like this is just a matter of disabling the auto-DateTime-handling in Json.NET, e.g.

[...]JsonFormatter.SerializerSettings.DateParseHandling = DateParseHandling.None

It's possible that we should fix the configuration method to do this automatically...

Note that this will also disable the handling of "Date(...)" values, so you do need to be careful with it. If you're in complete control of the caller of course, that shouldn't be a problem.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top