Редактировать свойства десятичной модели в C # ASP .Net MVC

У меня простая модель с одним десятичным свойством:

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

На мой взгляд, у меня есть:

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

Дело в том, что когда я пытаюсь опубликовать значение с десятичной частью (например, 1,5, 2,5 и т. Д.), Я получаю ошибки проверки на стороне клиента или сервера в зависимости от того, какой NumberDecimalSeparator я использую. Если я отправляю 1,5, я получаю ошибку проверки на стороне клиента (data-val-number one) или если я отправляю 1.5, я получаю ошибку проверки модели на стороне сервера - "The value '1.5' is not valid for Quantity.". Я пытался установить NumberDecimalSeparator вручную на Application_Start() в Global.asax, но это не помогло.

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

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

Когда я вручную добавил некоторые значения в базу данных и попытался их отредактировать, значение в TextBox отображается с точкой ".", но когда я пытаюсь сохранить другое значение с точкой, я получаю ошибку проверки на стороне сервера. В чем могут быть причины? Почему не работало обновление информации о культуре вручную?

// РЕДАКТИРОВАТЬ: Мой подход к изменению currentCulture.NumberFormat.NumberDecimalSeparator работает, но только если я делаю это каждый раз на 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);
}

Почему не работает при запуске приложения?


person Dmytro    schedule 31.03.2015    source источник
comment
Какая культура у сервера? Если он принимает десятичный разделитель как запятую, вы можете изменить jquery.validator, чтобы принять десятичный разделитель как запятую (по умолчанию это точка)   -  person    schedule 31.03.2015
comment
@StephenMuecke, культура сервера culture="ru" uiCulture="ru-RU", также я хочу использовать точку в качестве десятичного разделителя, как это по умолчанию.   -  person Dmytro    schedule 31.03.2015
comment
Это сработает, если вы измените культуру (скажем en-US)?   -  person    schedule 31.03.2015
comment
@StephenMuecke, да, это так. В этом случае точка является допустимым разделителем для валидаторов на стороне клиента и на стороне сервера.   -  person Dmytro    schedule 31.03.2015
comment
Попробуйте поместить свой код для установки культуры в Application_AcquireRequestState, а не в Application_Start   -  person    schedule 31.03.2015


Ответы (2)


Я считаю логичным, что это не работает в Application_Start, потому что вы устанавливаете культуру для каждого потока.

Вы можете установить глобальную культуру в своем web.config:

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

Но если вы хотите (как в вашем примере) иметь русскую культуру, но с другим десятичным разделителем, то я думаю, что Application_BeginRequest() может быть хорошим кандидатом. Согласно документации:

Происходит как первое событие в цепочке выполнения конвейера HTTP, когда ASP.NET отвечает на запрос.

Но вам нужно быть осторожным, потому что это событие запускается буквально при каждом запросе.

Решил подобную проблему не так давно. В моем случае у пользователя была возможность переключаться между культурами. Таким образом, каждая культура пользователя была сохранена в базе данных, и поэтому мы использовали метод контроллера Initialize вместо Application_BeginRequest(). Затем мы устанавливаем все правила для проверки клиента на основе культуры текущего потока.

Я думаю, что такие функции также можно перенести в фильтр, как в этом ответе .

person Aleksandr Ivanov    schedule 31.03.2015
comment
Большое спасибо! - person Alexander; 11.05.2018

По этой проблеме есть отличный блог. Я уже ответил на это на аналогичный вопрос.

Подход, который я использовал, заключается в расширении валидатора jQuery. Он основан на этом сообщении в блоге. Я установил культуру в метаданных на BE-nl. Поскольку это чисто голландский веб-сайт, я больше не проверяю.

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

Думаю, я использовал эту библиотеку jQuery для глобализации

person Thijs    schedule 31.03.2015