Aspnet Core Decimal绑定不适用于非英语文化 [英] Aspnet Core Decimal binding not working on non English Culture

查看:104
本文介绍了Aspnet Core Decimal绑定不适用于非英语文化的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个以非英语配置(西班牙语)运行的aspnet核心应用程序:

I have an aspnet core app that runs with a non english configuration (spanish):

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
    {
        ......
        app.UseRequestLocalization(new RequestLocalizationOptions
        {
            DefaultRequestCulture = new RequestCulture(new CultureInfo("es-AR"))
            ,SupportedCultures = new List<CultureInfo>
            {
                new CultureInfo("es-AR")
            }
            ,SupportedUICultures = new List<CultureInfo>
            {
                new CultureInfo("es")
            }
        });

        .........
    }

在英语中,十进制数字的十进制部分由点分隔,但在西班牙语中使用逗号:

In english a decimal number has its decimal part delimited with a dot, but in spanish a comma is used:

  • 10256.35英语
  • 10256,35西班牙文

我在控制器中执行此操作:

I have this action in a controller:

 [HttpPost]
 public decimal Test(decimal val)
 {
     return val;
 }

如果我使用邮递员并将该{val:15.30}这样的json发送给该动作,则该动作中的val会收到0(由于文化原因,绑定不起作用).如果我发送这样一个{val:15,30}的json,那么在操作中我会恢复15.30 我的问题是,我需要采取行动以逗号接受小数,因为这是来自应用程序表单中输入类型文本的格式.但是我还需要接受以json格式来自请求的小数点.无法在接受逗号的json中指定小数/浮点数(将其作为字符串发送是不可选项).我怎样才能做到这一点???我为此而发疯.

If I use postman and send to that action a json like this {val: 15.30}, then val in the action recives a 0 (binding not working because of the culture). If I send a json like this {val: 15,30} then in the action I recive 15.30 The problem I have is, I need the action to accept decimals with commas, because that is the format that comes from inputs type text in the app's forms. But i also need to accept decimal with a dot that comes from request in json format. There is no way to specify a decimal/float in json that accepts a comma (send it as string is not an option). How can I do this??? I'm driving my self crazy with this.

谢谢!

推荐答案

显然,默认情况下,ASP.NET core 1.0.0中的十进制绑定不是区域性不变的.模型绑定取决于服务器区域性.

Apparently, the decimal binding in ASP.NET core 1.0.0 is not culture invariant by default. The model binding depends on the server culture.

您可以按照Stephen Muecke的建议使用自定义模型绑定来更改此行为.这是我的基于ASP.Net中的自定义模型绑定核心1.0(RTM)

You can change this behavior with a custom model binding as suggested by Stephen Muecke. Here is mine based on Custom Model Binding in ASP.Net Core 1.0 (RTM)

public class InvariantDecimalModelBinderProvider : IModelBinderProvider
{
    public IModelBinder GetBinder(ModelBinderProviderContext context)
    {
        if (context == null) throw new ArgumentNullException(nameof(context));

        if (!context.Metadata.IsComplexType && (context.Metadata.ModelType == typeof(decimal) || context.Metadata.ModelType == typeof(decimal?)))
        {
            return new InvariantDecimalModelBinder(context.Metadata.ModelType);
        }

        return null;
    }
}

public class InvariantDecimalModelBinder : IModelBinder
{
    private readonly SimpleTypeModelBinder _baseBinder;

    public InvariantDecimalModelBinder(Type modelType)
    {
        _baseBinder = new SimpleTypeModelBinder(modelType);
    }

    public Task BindModelAsync(ModelBindingContext bindingContext)
    {
        if (bindingContext == null) throw new ArgumentNullException(nameof(bindingContext));

        var valueProviderResult = bindingContext.ValueProvider.GetValue(bindingContext.ModelName);

        if (valueProviderResult != ValueProviderResult.None)
        {
            bindingContext.ModelState.SetModelValue(bindingContext.ModelName, valueProviderResult);

            var valueAsString = valueProviderResult.FirstValue;
            decimal result;

            // Use invariant culture
            if (decimal.TryParse(valueAsString, NumberStyles.AllowDecimalPoint | NumberStyles.AllowLeadingSign, CultureInfo.InvariantCulture, out result))
            {
                bindingContext.Result = ModelBindingResult.Success(result);
                return Task.CompletedTask;
            }
        }

        // If we haven't handled it, then we'll let the base SimpleTypeModelBinder handle it
        return _baseBinder.BindModelAsync(bindingContext);
    }
}

在Startup.cs中:

And in Startup.cs:

services.AddMvc(config =>
{
    config.ModelBinderProviders.Insert(0, new InvariantDecimalModelBinderProvider());
});

这篇关于Aspnet Core Decimal绑定不适用于非英语文化的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆