Проверка на стороне клиента MVC 3, десятичное значение привязки модели и культура (разный десятичный разделитель)
Я пытаюсь проверить свою клиентскую сторону (привязка к модели) для поддержки разных культур, и я нашел интересный блог по этому вопросу, который я пытаюсь реализовать.
http://haacked.com/archive/2011/03/19/fixing-binding-to-decimals.aspx
Поко
public class Jogador
{
public int ID { get; set; }
public string Name { get; set; }
public decimal Salary { get; set; }
}
У меня есть собственный класс DecimalModelBinder
public class DecimalModelBinder : IModelBinder
{
public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
ValueProviderResult valueResult = bindingContext.ValueProvider.GetValue(bindingContext.ModelName);
ModelState modelState = new ModelState {Value = valueResult};
object actualValue = null;
try
{
actualValue = Convert.ToDecimal(valueResult.AttemptedValue, CultureInfo.CurrentCulture);
}
catch (FormatException e)
{
modelState.Errors.Add(e);
}
bindingContext.ModelState.Add(bindingContext.ModelName, modelState);
return actualValue;
}
}
Мой web.config:
<compilation debug="true" targetFramework="4.0">
<assemblies>
<add assembly="System.Web.Abstractions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
<add assembly="System.Web.Helpers, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
<add assembly="System.Web.Routing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
<add assembly="System.Web.Mvc, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
<add assembly="System.Web.WebPages, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
</assemblies>
</compilation>
<authentication mode="Forms">
<forms loginUrl="~/Account/LogOn" timeout="2880" />
</authentication>
<pages>
<namespaces>
<add namespace="System.Web.Helpers" />
<add namespace="System.Web.Mvc" />
<add namespace="System.Web.Mvc.Ajax" />
<add namespace="System.Web.Mvc.Html" />
<add namespace="System.Web.Routing" />
<add namespace="System.Web.WebPages"/>
</namespaces>
</pages>
Global.asax изменены, чтобы использовать мой пользовательский ModelBinder в десятичной и десятичной форме? Значения
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
ModelBinders.Binders.Add(typeof(decimal), new DecimalModelBinder());
ModelBinders.Binders.Add(typeof(decimal?), new DecimalModelBinder());
RegisterGlobalFilters(GlobalFilters.Filters);
RegisterRoutes(RouteTable.Routes);
}
Тем не менее проверка на стороне клиента завершается с ошибкой на десятичном значении, введенном в моем представлении, с разделителем "," в качестве разделителя десятичной дроби. Он не обрабатывает как ",", так и ".". Проверка js, по-видимому, не учитывает мою собственную привязку
Чтение статьи блога снова и снова, я просто не могу понять, что мне не хватает.
Вот представление:
@model MVC_Empty.Web.Models.Jogador
@{
ViewBag.Title = "Create";
}
<h2>Create</h2>
<script src="@Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script>
@using (Html.BeginForm()) {
@Html.ValidationSummary(true)
<fieldset>
<legend>Jogador</legend>
<div class="editor-label">
@Html.LabelFor(model => model.Name)
</div>
<div class="editor-field">
@Html.EditorFor(model => model.Name)
@Html.ValidationMessageFor(model => model.Name)
</div>
<div class="editor-label">
@Html.LabelFor(model => model.Salary)
</div>
<div class="editor-field">
@Html.EditorFor(model => model.Salary)
@Html.ValidationMessageFor(model => model.Salary)
</div>
<p>
<input type="submit" value="Create" />
</p>
</fieldset>
}
<div>
@Html.ActionLink("Back to List", "Index")
</div>
Проверка на стороне сервера кажется прекрасной, но как обрабатывать проверку на стороне клиента, чтобы отправить POST при нажатии кнопки отправки.
Проверка javascript не обрабатывает запятую. ![enter image description here]()
![enter image description here]()
Ответы
Ответ 1
Наконец, понимая, что Custom DecimalModelBinder будет обрабатывать только серверную проверку и не влияет на jquery.validate.js, который обрабатывает проверку на стороне клиента, я нашел решение проблемы.
Расширение проверки разрешило мою проблему.
![enter image description here]()
Расширить проверку новым .js файлом в качестве обходного пути к проблеме:
$.validator.methods.number = function(value, element) {
return this.optional(element) || /^-?(?:\d+|\d{1,3}(?:[\s\.,]\d{3})+)(?:[\.,]\d+)?$/ .test(value);
};
Этот блог был очень полезен
http://rebuildall.umbraworks.net/2011/03/02/jQuery_validate_and_the_comma_decimal_separator
Ответ 2
Попробуйте немного модифицированную версию:
public class DecimalModelBinder : IModelBinder
{
public object BindModel(ControllerContext controllerContext,
ModelBindingContext bindingContext)
{
ValueProviderResult valueResult = bindingContext.ValueProvider
.GetValue(bindingContext.ModelName);
ModelState modelState = new ModelState { Value = valueResult };
object actualValue = null;
try
{
//if with period use InvariantCulture
if (valueResult.AttemptedValue.Contains("."))
{
actualValue = Convert.ToDecimal(valueResult.AttemptedValue,
CultureInfo.InvariantCulture);
}
else
{
//if with comma use CurrentCulture
actualValue = Convert.ToDecimal(valueResult.AttemptedValue,
CultureInfo.CurrentCulture);
}
}
catch (FormatException e)
{
modelState.Errors.Add(e);
}
bindingContext.ModelState.Add(bindingContext.ModelName, modelState);
return actualValue;
}
}
Это работает для меня.
UPDATE
Если вы используете частичное представление, используйте $.validate.unobtrusive.parse("#selector")
для повторной проверки. Если вы не попытаетесь установить глобализацию в свой web.config(один в корне, а не в представлениях) примерно так:
<configuration>
<system.web>
<globalization fileEncoding="utf-8"
requestEncoding="utf-8"
responseEncoding="utf-8"
culture="hr-HR" uiCulture="hr-HR" />
</system.web>
</configuration>
У меня есть глобализация, установленная на Hr, где мы используем запятую как разделители, но с DecimalModelBinder, которую я опубликовал, будет правильно анализировать десятичную или запятую.
Отношения
Ответ 3
Я только что исправил эту проблему, заменив строку 1050 jquery.validate.js на этот код:
return this.optional(element) ||/^-?(?:\d+|\d{1,3}(?:,\d{3})+)?(?:[.|\,]\d+)?$/.test(value);
Я только что изменил smth на регулярное выражение, используемое для проверки числа, и теперь он отлично работает!!