CultureInfo выходят с Modelbinding дважды в asp.net-mvc (2)

В моем сценарии JQuery я отправляю два, удваивает использование CultureInfo браузера (en-Великобритания), которая использует .как дробный разделитель. Мое приложение MVC работает на сервере с локалью nl - использовать , как дробный разделитель.

[AcceptVerbs(HttpVerbs.Post)]
public JsonResult GetGridCell(double longitude, double latitude)
{
    var cell = new GridCellViewModel { X = (int)Math.Round(longitude, 0), Y = (int)Math.Round(latitude, 0) };
    return Json(cell);
}

modelbinding перестал работать из-за проблемы парсинга.

Я думаю, что было бы лучше установить мой JavaScript на en-Великобританию и то же для modelbinding в моем приложении MVC. Но я не знаю, как сделать также.
Какие-либо предложения?

6
задан Boris Callens 2 July 2010 в 19:39
поделиться

2 ответа

Я не уверен, насколько далеко заходит локализация со связывателем модели по умолчанию (DefaultModelBinder), но вы можете легко создать связыватель самостоятельно, который может обрабатывать специфичный для культуры синтаксический анализ данных, например, создать новый класс, назовем его DoubleModelBinder, скопируйте следующее:

public class DoubleModelBinder : IModelBinder
{
    /// <summary>
    /// Binds the value to the model.
    /// </summary>
    /// <param name="controllerContext">The current controller context.</param>
    /// <param name="bindingContext">The binding context.</param>
    /// <returns>The new model.</returns>
    public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        var culture = GetUserCulture(controllerContext);

        string value = bindingContext.ValueProvider
                           .GetValue(bindingContext.ModelName)
                           .ConvertTo(typeof(string)) as string;

        double result = 0;
        double.TryParse(value, NumberStyles.Any, culture, out result);

        return result;
    }

    /// <summary>
    /// Gets the culture used for formatting, based on the user's input language.
    /// </summary>
    /// <param name="context">The controller context.</param>
    /// <returns>An instance of <see cref="CultureInfo" />.</returns>
    public CultureInfo GetUserCulture(ControllerContext context)
    {
        var request = context.HttpContext.Request;
        if (request.UserLanguages == null || request.UserLanguages.Length == 0)
            return CultureInfo.CurrentUICulture;

        return new CultureInfo(request.UserLanguages[0]);
    }
}

Теперь то, что мы делаем здесь, - это создание нашего собственного двойного синтаксического анализатора, учитывающего язык. Когда мы реализуем интерфейс IModelBinder, нам нужно создать метод BindModel. Здесь и делается основная часть работы, но прежде чем мы сможем что-либо проанализировать, нам нужно получить IFormatProvider, основанный на языке браузера. Итак, мы используем метод GetUserCulture, чтобы попробовать подготовить язык браузера. Если мы не сможем вернуться к нынешней культуре.

Когда у нас это есть, мы можем проанализировать значение. Сначала мы берем его из ValueProvider (который на самом деле представляет собой составную часть многих поставщиков значений, например, из коллекции Form, Request и т. Д.), А затем анализируем его, используя обнаруженный IFormatProvider, который сейчас у нас есть CultureInfo.

После того, как вы это сделаете, довольно просто добавить его в коллекцию связывателей модели;

ModelBinder.Binders[typeof(Double)] = new DoubleModelBinder();

Попробуйте это и посмотрите, поможет ли это.

8
ответ дан 10 December 2019 в 02:42
поделиться

ModelBinding использует CurrentCulture для разбора значений. Это понятно, потому что пользователь может ввести дату или десятичную дробь в текстовое поле, и значение будет разобрано правильно.

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

Вот почему я устанавливаю CurrentCulture в Application.BeginRequest в CultureInfo.InvariantCulture. Благодаря этому все связывания используют неизменную культуру. Если позже вы захотите использовать ресурсы или форматировать значения на языке браузера, вам придется переключиться обратно на язык пользователя, снова установив CurrentCulture на язык пользователя. Я делаю это в фильтре действий.

EDIT:

ОП поправил меня в том, что только представления формы учитывают культуру: это правда. См. источник для ValueProviderDictionary:PopulateDictionary, где это документировано:

   We use this order of precedence to populate the dictionary:
   1. Request form submission (should be culture-aware)
   2. Values from the RouteData (could be from the typed-in URL or from the route's default values)
   3. URI query string
1
ответ дан 10 December 2019 в 02:42
поделиться
Другие вопросы по тегам:

Похожие вопросы: