简体   繁体   中英

Localized query string parameters in ASP core

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 (eg /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.

Minutes after asking this I found the answer, https://docs.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;
        }
    }

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