11

I have a localized ASP.NET Core Web Application: en-US and it-IT.

On en-US the decimal separator is dot, in it-IT the decimal separator is comma.

I have this ViewModel

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

    // Omitted

    public decimal? Amount{get; set;}

}

For the decimal field when I render the create/edit page on en-US the html textbox render

1000.00

If I POST the form, the operation complete without errors.

So far so good.

When I render the create/edit page on it-IT the html textbox render

1000,00 (notice the comma)

And IF I try to POST the form, (CLIENT) validation fail with

The field Amount must be a number.

I read about the IModelBinder but I understand is for mapping the viewModel when the form is posted on the server, on my case I'm blocked by the client-side validation.

The better is to use dot when en-US and comma when it-IT, but it's fine using only the dot

Max
  • 6,821
  • 3
  • 43
  • 59
  • 1
    You need to write a script to modify the jquery validator –  Aug 25 '17 at 12:10
  • Can you give me some other info about this ? – Max Aug 25 '17 at 12:12
  • I'll see if I can find a link for your shortly –  Aug 25 '17 at 12:13
  • try this https://stackoverflow.com/a/14400739/7880063 – Ravikumar Aug 25 '17 at 12:18
  • 3
    Refer [this article](http://www.stevendewaele.be/validating-numbers-with-commas-with-jquery/#.WaAVoigjHIU) for an example (but you will need to conditionally add it based on the culture) –  Aug 25 '17 at 12:20
  • 1
    @Ravikumar, That is server side, not client side validation –  Aug 25 '17 at 12:20
  • You can replace the decimal separator, try this https://stackoverflow.com/a/12004890/7880063 – Ravikumar Aug 25 '17 at 12:26
  • @StephenMuecke your tips do the job !. Do you know if I can change the comma with dot on rendering, I would a Plan B if the customer ask for only dot on every localization. Thanks.. – Max Aug 25 '17 at 13:25
  • Can't you use a string instead and then format it on the server side based on the culture back to its decimal representation? – MattE Aug 25 '17 at 12:39
  • Sorry, not clear what your asking. Do you have some property that identifies what culture that each user wants in the view? –  Aug 26 '17 at 04:37

4 Answers4

9

After digging depth the problem I found two solution:

The comment from Stephen Muecke where explain how to add the required jquery to the input for a validation for comma and dot

A custom InputTagHelper where transform the comma into dot. Here I added only a decimal type but obviously you can add float and 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));                
        }
    }
}

For use this 2nd solution you simply add asp-is-invariant to your input, like this

 <input asp-for="AmountSw" class="form-control" asp-is-invariant="true" />
Max
  • 6,821
  • 3
  • 43
  • 59
  • None of them worked for me. When I put 123,00 , post the form and open it again, I get 12300.00 there. This for the first case. 2-nd case didn't work at all – Tigran Jul 04 '19 at 19:25
1

The conversion fails because ASP.NET tries to convert the value with its current culture (check this link). You need to set the culture in the current thread of the request. The browser will send the languages it is currently using and supportin with Request.UserLanguage.

You can impliment a custom filter, a http module or use the event structure of mvc to set the culture automatically for every request. Check this link for a sample.

JoeJoe87577
  • 512
  • 3
  • 17
  • 1
    OP is asking about **client** side validation, not server side –  Aug 25 '17 at 12:58
  • Yes but even if the decimal input is validated with the it-IT culture clientside the server will return an error parsing the posted string in the wrong culture. – JoeJoe87577 Aug 25 '17 at 13:06
  • 1
    Not if they have set the server side culture. Again read the question- its about client side validation –  Aug 25 '17 at 13:08
0

I tried the custom validator that was mentioned above but it wasn't working. I got it to work like this:

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

In ViewImports :

 @addTagHelper *, Project

In View :

 <input asp-for-invariant="numberProp"/>
Matheus Lacerda
  • 5,983
  • 11
  • 29
  • 45
0

Comma and dot problem depend on culture and pc language so i solved problem with js like follow

   Amount: { editable: true, type: "number"},