1

I'm having issues with a controller which gets as parameters in the query string a pair of coordinates.

My controller looks like:

[HttpGet("/location")]
public IActionResult GetForLocation(double lat, double lon)
{
// Do stuff
}

When clients send coordinates with different decimal separators (e.g. /location?lat=4,4&lon=45,5) the framework's parsed them to 44 and 455. I've used app.UseRequestLocalization() in my startup class and reviewing the current thread culture I get the correct values for the decimal separators, but the model bindings are wrong.

1 Answer 1

2

Minutes after asking this I found the answer, https://learn.microsoft.com/en-us/aspnet/core/mvc/models/model-binding?view=aspnetcore-5.0#globalization-behavior-of-model-binding-route-data-and-query-strings

In short Query string parameters and Paths are treated by default as Invariant Culture unless you replace the QueryStringValueProviderFactory and RouteValueProviderFactory with the following:

    public class CulturedQueryStringValueProviderFactory : IValueProviderFactory
    {
        /// <inheritdoc />
        public Task CreateValueProviderAsync(ValueProviderFactoryContext context)
        {
            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }

            var query = context.ActionContext.HttpContext.Request.Query;

            if (query != null && query.Count > 0)
            {
                var valueProvider = new QueryStringValueProvider(
                    BindingSource.Query,
                    query,
                    CultureInfo.CurrentCulture);

                context.ValueProviders.Add(valueProvider);
            }

            return Task.CompletedTask;
        }
    }
    public class CulturedRouteValueProviderFactory : IValueProviderFactory
    {
        /// <inheritdoc />
        public Task CreateValueProviderAsync(ValueProviderFactoryContext context)
        {
            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }

            var valueProvider = new RouteValueProvider(
                BindingSource.Path,
                context.ActionContext.RouteData.Values,
                CultureInfo.CurrentCulture);

            context.ValueProviders.Add(valueProvider);

            return Task.CompletedTask;
        }
    }
Sign up to request clarification or add additional context in comments.

1 Comment

No worries @SaeedEsmaeelinejad, I didn't know either and I feel that finding that doc was a lucky strike

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.