Связыватель модели ASP.NET MVC с глобальными числовыми форматами
Связыватель модели по умолчанию возвращает ошибки для свойств, имеющих тип double, когда мое приложение используется в странах, которые используют различное форматирование чисел для десятичных чисел (например, 1,2 = 1,2). Культура сайта установлена в моем BaseController условно.
Я попытался добавить привязку пользовательской модели и переопределить функцию bindModel, но я не вижу, как обойти эту ошибку, поскольку для культуры уже установлено значение по умолчанию en-GB.
Поэтому я попытался добавить фильтр действий в свой BaseController, который устанавливает там Культуру, но, к сожалению, bindModel, похоже, срабатывает до моего фильтра действий.
Как я могу обойти это? Или заставить Культуру не сбрасывать себя или установить ее обратно до того, как включится bindModel?
Контроллер, в котором модель становится недействительной:
public ActionResult Save(MyModel myModel)
{
if (ModelState.IsValid)
{
// Save my model
}
else
{
// Raise error
}
}
Фильтр, где установлена культура:
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
CultureInfo culture = createCulture(filterContext);
if (culture != null)
{
Thread.CurrentThread.CurrentCulture = culture;
Thread.CurrentThread.CurrentUICulture = culture;
}
base.OnActionExecuting(filterContext);
}
Пользовательская модель Binder:
public class InternationalDoubleModelBinder : DefaultModelBinder
{
public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
ValueProviderResult valueResult = bindingContext.ValueProvider.GetValue(bindingContext.ModelName);
if (valueResult != null)
{
if (bindingContext.ModelType == typeof(double) || bindingContext.ModelType == typeof(Nullable<double>))
{
double doubleAttempt;
doubleAttempt = Convert.ToDouble(valueResult.AttemptedValue);
return doubleAttempt;
}
}
return null;
}
}
2 ответа
Вы хотите, чтобы ваше приложение использовало единую культуру, верно? Если это так, вы можете сделать это с помощью тега globalisation вашего web.config.
<configuration>
<system.web>
<globalization
enableClientBasedCulture="true"
culture="en-GB"
uiCulture="en-GB"/>
</system.web>
</configuration>
И тогда вы можете забыть эти пользовательские связующие модели и использовать по умолчанию.
ОБНОВЛЕНИЕ: Хорошо, это многоязычное приложение. Как вы получаете культуру, которую вы хотите? Можете ли вы вызвать createCulture для класса MvcApplication? Вы могли бы сделать это:
public class MvcApplication : HttpApplication
{
//...
public void Application_OnBeginRequest(object sender, EventArgs e)
{
CultureInfo culture = GetCulture();
Thread.CurrentThread.CurrentCulture = culture;
Thread.CurrentThread.CurrentUICulture = culture;
}
//...
}
Этот метод вызывается до привязки модели, поэтому, опять же, вам не понадобится пользовательское связывание модели. Я надеюсь, что это работает для вас:)
Посмотрите в этой статье, но, для краткости, если бы вы могли попробовать это:
public ActionResult Create(FormCollection values)
{
Recipe recipe = new Recipe();
recipe.Name = values["Name"];
// ...
return View();
}
... или это, если у вас есть модель:
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Create(Recipe newRecipe)
{
// ...
return View();
}
В статье есть полные ссылки и другие способы сделать это. Я использую эти 2, и они были достаточно для меня до сих пор.