Aspnet Core 十进制绑定不适用于非英语文化

Posted

技术标签:

【中文标题】Aspnet Core 十进制绑定不适用于非英语文化【英文标题】:Aspnet Core Decimal binding not working on non English Culture 【发布时间】:2017-02-05 20:23:24 【问题描述】:

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

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")
            
        );

        .........
    

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

10256.35 英文 10256,35 西班牙语

我在控制器中有这个动作:

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

如果我使用邮递员并向该操作发送一个像 val: 15.30 这样的 json,那么操作中的 val 将接收到 0(由于文化,绑定不起作用)。如果我发送这样的 json val: 15,30 然后在操作中我收到 15.30 我遇到的问题是,我需要接受带逗号的小数的操作,因为这是来自应用程序表单中输入类型文本的格式。但我还需要接受带有来自 json 格式请求的点的小数。无法在接受逗号的 json 中指定小数/浮点数(不能将其作为字符串发送)。我怎样才能做到这一点???我快把自己逼疯了。

谢谢!!

【问题讨论】:

您需要创建一个自定义 ModelBinder 来读取 contentType 并根据内容类型解析值 在 MVC5 中我使用了自定义模型绑定器,它解决了我的问题,对于 mvc 核心,您可以在这里找到类似的解决方案 Custom Model Binding in ASP.Net Core 1.0 (RTM) 【参考方案1】:

显然,ASP.NET core 1.0.0 中的十进制绑定默认不是文化不变的。模型绑定取决于服务器文化。

您可以按照 Stephen Muecke 的建议使用自定义模型绑定来更改此行为。这是我的基于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 中:

services.AddMvc(config =>

    config.ModelBinderProviders.Insert(0, new InvariantDecimalModelBinderProvider());
);

【讨论】:

请备注他人,此复制/粘贴将停止绑定负数。为了避免在 decimal.TryParse 中添加 numberStyles.AllowLeadingSign 样式。非常感谢 编辑添加 NumberStyles.AllowLeadingSign。好收获@adopilot @LucGauthier 这仅适用于基本类型。我们有什么方法可以为具有小数属性的类实现这一点? @Ruchan 我没有机会测试这个案例。

以上是关于Aspnet Core 十进制绑定不适用于非英语文化的主要内容,如果未能解决你的问题,请参考以下文章

模型绑定不适用于 ASP.NET Core 2 WebAPI 中的 POST 请求

textarea 双向绑定不适用于 ng-model

用于 aspnet-core web api 的基于令牌的身份验证

iOS 11 自动填充密码功能不适用于英语以外的其他语言

为啥 SelectMany 不适用于 EF Core Cosmos DB?

为啥“位置:粘性”不适用于 Core UI Bootstrap CSS