3

I have Simple model with one decimal property:

public class Model {
    public decimal Quantity { get;set; }
}

In my view I have:

@Html.TextBoxFor(m => m.Quantity)
@Html.ValidationMessageFor(m => m.Quantity)

The thing is that when I try to post value with decimal part (like 1.5, 2.5 etc.) I get validation errors on client or server sides depending which NumberDecimalSeparator I use. If I post 1,5 I get client side validation error (the data-val-number one) or if I post 1.5 I get server side model validation error - "The value '1.5' is not valid for Quantity.". I tried to set NumberDecimalSeparator manually on Application_Start() in Global.asax but it didn't help.

var currentCulture = (CultureInfo)CultureInfo.CurrentCulture.Clone();
currentCulture.NumberFormat.NumberDecimalSeparator = ".";

Thread.CurrentThread.CurrentCulture = currentCulture;
Thread.CurrentThread.CurrentUICulture = currentCulture;

When I manually added some values to the database and tried to edit them, the value in TextBox is displayed with dot ".", but when I try to save another value with the dot I get server side validation error. What could be the reasons? Why didn't manual culture info update work?

// EDITS: My approach with changing currentCulture.NumberFormat.NumberDecimalSeparator works but only if I do it each time on Application_BeginRequest():

protected override void Application_BeginRequest(object sender, System.EventArgs e)
{
       var currentCulture = (CultureInfo)CultureInfo.CurrentCulture.Clone();
       currentCulture.NumberFormat.NumberDecimalSeparator = ".";
       currentCulture.NumberFormat.NumberGroupSeparator = " ";
       currentCulture.NumberFormat.CurrencyDecimalSeparator = ".";

       Thread.CurrentThread.CurrentCulture = currentCulture;
       Thread.CurrentThread.CurrentUICulture = currentCulture;
       base.Application_BeginRequest(sender, e);
}

Why doesn't it work on application start?

Dmytro
  • 16,668
  • 27
  • 80
  • 130
  • What is the culture of the server? If it accepts the decimal separator as a comma, then you can modify the jquery.validator to accept the decimal separator as comma (by default its a dot) –  Mar 31 '15 at 06:03
  • @StephenMuecke, the culture of the server is `culture="ru" uiCulture="ru-RU"` also I want to use dot as decimal separator, as it is by default. – Dmytro Mar 31 '15 at 06:05
  • Does it work if you change the culture (to say `en-US`)? –  Mar 31 '15 at 06:12
  • @StephenMuecke, yes, It does. Dot,in that case, is valid separator for client and server side validators. – Dmytro Mar 31 '15 at 06:13
  • Try putting your code for setting the culture in `Application_AcquireRequestState` rather than `Application_Start` –  Mar 31 '15 at 06:21

2 Answers2

3

I think it's logical that it's not working in Application_Start because you set culture per thread.

You can set culture globally in your web.config:

<configuration>
    <system.web>
        <globalization uiCulture="en-GB" culture="en-GB" />
    </system.web>
</configuration>

But if you want (as in your example) to have Russian culture but with different decimal separator, then I think Application_BeginRequest() might be a good candidate. According to documentation:

Occurs as the first event in the HTTP pipeline chain of execution when ASP.NET responds to a request.

But you need to be careful, because this event is fired on literally every request.

I solved the similar problem not so long ago. In my case user had a possibility to switch between cultures. So every user culture was saved in database and because of that we used Initialize method of controller instead of Application_BeginRequest(). Then we set all the rules for client validation based on current thread culture.

I think such functionality can be also moved to filter like in this answer.

Community
  • 1
  • 1
Aleksandr Ivanov
  • 2,778
  • 5
  • 27
  • 35
1

There is an excellent blogpost about this issue. I answered this already to a similar question.

The approach I used is to extend the jQuery validator. It is based on this blogpost. I setted the culture in the metadata to BE-nl. Since this is a pure Dutch website, I don't do any checks further on.

$(function () {
    // Look in metatag what culture we want
    // and set this as culture for the client side.
    var data = $("meta[name='accept-language']").attr("content");
    Globalize.culture(data.toString());

    // Don't validate on keyup event because it will mess up
    // the cursor when replacing values in a textbox.
    $('form').each(function () {
    var validator = $(this).data('validator');
    if (validator) {
        validator.settings.onkeyup = false;
    }
});

// Belgianize/sanitize the numbers inserted
// 1 000 000    =>      1000000
// 1.00         =>      1,00
$.validator.methods.number = function (value, element) {
    var s = value.replace(/\ /g, '').split('.').join(',');

    if (s.split(',').length < 3) {
        var number = Globalize.parseFloat(s);
        if (!isNaN(number)) {
            $(element).val(s);
            return this.optional(element) || true;
        }
    }

    return this.optional(element) || false;
}; }); 

I think I used this jQuery library for the globalization

Community
  • 1
  • 1
Thijs
  • 3,015
  • 4
  • 29
  • 54