Azure-functions-host: HTTP model binding can't handle DateTimes with seconds

Created on 23 Feb 2019  路  3Comments  路  Source: Azure/azure-functions-host

I have a C# v2 Function with an HTTP trigger that looks like this:

public static async Task<IActionResult> Run(
            [HttpTrigger(AuthorizationLevel.Function, "post", Route = null)] MyParameters parameters,
            ILogger log, ExecutionContext context)

The MyParameters class has a DateTime property.
If I run this in Azure and use Postman to POST JSON to it with the DateTime property set to "2019-01-28T13:23:34.12345Z" it works fine.

If I run it locally and use Postman to POST to it with the same value I get the following error:

[23/02/2019 15:33:11] System.Private.CoreLib: Exception while executing function: MyFunction. Microsoft.Azure.WebJobs.Host: 
Exception binding parameter 'parameters'. System.Private.CoreLib: String '01/28/2019 13:23:34' was not recognized as a valid DateTime.

Note that the local locale is en-GB - not that that should make a difference to it working.

If I remove the seconds from the DateTime property, i.e. "2019-01-28T13:23" it works locally.

bug needs-investigation

All 3 comments

I think this is a runtime issue. It's unable to serialize "2019-01-28T13:23:34.12345Z" as a DateTime if the locale is set to en_GB for some reason.

On Linux to repro:

LANG=en_GB.UTF-8 func start

Investigated 3.0.10 with Newtonsoft.Json 11.0.2

The root of the problem is in the Microsoft.Azure.WebJobs.Extensions.Http.Utility class:

        private static object ConvertPropertyValue(JProperty property)
        {
            if (property.Value != null && property.Value.Type == JTokenType.Object)
            {
                return (JObject)property.Value;
            }
            else
            {
                return (string)property.Value;
            }
        }

In my example, the incoming JObject property has the following representation {"SubmissionDate": "2019-07-30T09:55:57.5032422+01:00"}, but the else clause yields:

"07/30/2019 09:55:57"

If I ToString() the property value, it yields:

"30/07/2019 09:55:57"

Ergo, the problem appears to be a problem with Newtonsoft.Json.Linq.JToken at v11.0.2, and its explicit string cast operators https://github.com/JamesNK/Newtonsoft.Json/blob/c4af75c8e91ca0d75aa6c335e8c106780c4f7712/Src/Newtonsoft.Json/Linq/JToken.cs#L1224

When I do a simple watch expression on (at time of writing): Convert.ToString(DateTimeOffset.Now, CultureInfo.InvariantCulture), it yields:

07/30/2019 10:35:54 +01:00

Which I guess is correct in the InvariantCulture, but not for my CurrentCulture: en-GB.

Another problem here is the apparent loss of DateTimeOffset precision in the model binding - my en-GB offset is missing in either string conversion. The following returns the result as I _imagine_ I want it:

(DateTimeOffset)property.Value

Which must be leveraging some innate cultural awareness in the DateTimeOffset behaviours, despite also having an invariant culture based explicit cast operator within JToken: https://github.com/JamesNK/Newtonsoft.Json/blob/c4af75c8e91ca0d75aa6c335e8c106780c4f7712/Src/Newtonsoft.Json/Linq/JToken.cs#L508

A simple fix may be an additional branch condition: property.Value.Type == JTokenType.Date.

@alrod this bug seems ... pervasive. Having "worked around it" it in one place ([HttpTrigger]), its reappearing in another binding now.

Having added a model containing a DateTimeOffset to a strong typed IAsyncCollector queue output binding, a subsequent [QueueTrigger] input binding is now throwing the same error.

Any ideas on a way to force the host into an en-US culture when running Func.exe in Windows?

I've checked:
https://docs.microsoft.com/en-us/azure/azure-functions/functions-app-settings https://docs.microsoft.com/en-us/azure/azure-functions/functions-host-json

And there's no mention of locale / culture / language.

Was this page helpful?
0 / 5 - 0 ratings