ASP.NET核心本地化十进制字段点和逗号

时间:2017-08-25 12:09:15

标签: c# asp.net asp.net-mvc asp.net-core

我有一个本地化的ASP.NET核心Web应用程序:en-US和it-IT。

在en-US上,小数点分隔符为点,在其中 - 小数点分隔符为逗号。

我有这个ViewModel

public class MyViewModel 
{
    public int Id {get; set; }

    // Omitted

    public decimal? Amount{get; set;}

}

对于在 en-US 上呈现创建/编辑页面时的十进制字段,html文本框呈现

  

1000.00

如果我发布表单,则操作完成且没有错误。

到目前为止一切顺利。

当我在 it-IT 上呈现创建/编辑页面时,html文本框呈现

  

1000,00(注意逗号)

如果我尝试发布表单,(CLIENT)验证失败

  

字段金额必须是数字。

我读到了有关IModelBinder的信息,但我理解的是,当表单在服务器上发布时映射viewModel,在我的情况下,我被客户端验证阻止。

更好的是在en-US时使用dot,而在IT时使用逗号,但只使用点

就可以了

3 个答案:

答案 0 :(得分:7)

在挖掘深度问题后,我找到了两个解决方案:

来自Stephen Muecke的评论解释了如何将所需的jquery添加到validation for comma and dot的输入

自定义InputTagHelper,将逗号转换为点。这里我只添加了一个十进制类型,但显然你可以添加float和double。

[HtmlTargetElement("input", Attributes = ForAttributeName, TagStructure = TagStructure.WithoutEndTag)]
public class InvariantDecimalTagHelper : InputTagHelper
{
    private const string ForAttributeName = "asp-for";

    private IHtmlGenerator _generator;

    [HtmlAttributeName("asp-is-invariant")]
    public bool IsInvariant { set; get; }

    public InvariantDecimalTagHelper(IHtmlGenerator generator) : base(generator)
    {
        _generator = generator;
    }

    public override void Process(TagHelperContext context, TagHelperOutput output)
    {
        base.Process(context, output);

        if (IsInvariant && output.TagName == "input" && For.Model != null && For.Model.GetType() == typeof(decimal))
        {
            decimal value = (decimal)(For.Model);
            var invariantValue = value.ToString(System.Globalization.CultureInfo.InvariantCulture);
            output.Attributes.SetAttribute(new TagHelperAttribute("value", invariantValue));                
        }
    }
}

要使用此第二个解决方案,您只需在输入中添加asp-is-invariant,就像这样

 <input asp-for="AmountSw" class="form-control" asp-is-invariant="true" />

答案 1 :(得分:0)

转换失败,因为ASP.NET尝试使用当前文化(check this link)转换值。 您需要在请求的当前线程中设置区域性。浏览器将发送当前使用的语言,并使用Request.UserLanguage发送支持。

您可以使用自定义过滤器,http模块或使用mvc的事件结构自动为每个请求设置文化。 Check this link for a sample

答案 2 :(得分:0)

我尝试了上面提到的自定义验证器,但是它不起作用。我让它像这样工作:

namespace Project.Helpers
{
[HtmlTargetElement("input", Attributes = ForAttributeName, TagStructure = TagStructure.WithoutEndTag)]
public class InvariantDecimalTagHelper : TagHelper
{
    private const string ForAttributeName = "asp-for-invariant";

    private readonly IHtmlGenerator _generator;
    private readonly InputTagHelper _inputTagHelper;

    [HtmlAttributeNotBound]
    [ViewContext]
    public Microsoft.AspNetCore.Mvc.Rendering.ViewContext ViewContext { get; set; }
    [HtmlAttributeName("asp-for-invariant")]
    public ModelExpression For { get; set; }
    [HtmlAttributeName("asp-format")]
    public string Format { get; set; }
    [HtmlAttributeName("type")]
    public string InputTypeName { get; set; }
    public string Name { get; set; }
    public string Value { get; set; }

    public InvariantDecimalTagHelper(IHtmlGenerator generator)
    {
        _generator = generator;
        _inputTagHelper = new InputTagHelper(_generator);
    }

    public override void Process(TagHelperContext context, TagHelperOutput output)
    {

        _inputTagHelper.Value = Value;
        _inputTagHelper.Name = Name;
        _inputTagHelper.InputTypeName = InputTypeName;
        _inputTagHelper.Format = Format;
        _inputTagHelper.For = For;
        _inputTagHelper.ViewContext = ViewContext;

        _inputTagHelper.Process(context, output);

        if (output.TagName == "input" && _inputTagHelper.For.Model != null && _inputTagHelper.For.Model.GetType() == typeof(decimal))
        {
            decimal value = (decimal)(_inputTagHelper.For.Model);
            var invariantValue = value.ToString(System.Globalization.CultureInfo.InvariantCulture);
            output.Attributes.SetAttribute(new TagHelperAttribute("value", invariantValue));
        }
    }
}
}

在ViewImports中:

 @addTagHelper *, Project

在视图中:

 <input asp-for-invariant="numberProp"/>