Проверка на стороне клиента MVC 3, десятичное значение привязки модели и культура (другой десятичный разделитель) - PullRequest
14 голосов
/ 02 апреля 2012

Я пытаюсь выполнить проверку на стороне клиента (привязку модели) для поддержки разных культур, и я нашел интересный блог по теме, которую я пытаюсь реализовать.

http://haacked.com/archive/2011/03/19/fixing-binding-to-decimals.aspx

Poco

  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

Ответы [ 3 ]

19 голосов
/ 03 апреля 2012

Наконец, понимая, что 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

5 голосов
/ 02 апреля 2012

Попробуйте, это немного измененная версия:

 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;
        }
    }

Это работает для меня.

ОБНОВЛЕНИЕ

Если вы используете частичныйиспользуйте $.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, который я разместил, будет правильно анализировать десятичную или запятую.Привет

1 голос
/ 19 июня 2015

Я только что исправил эту проблему, заменив строку 1050 в jquery.validate.js следующим кодом:

return this.optional (element) || /^-?(?:\d+|\d{1,3}(?:,\d{3})+)?(?:[.|\,]\d+)?$/.test(value) ;

Я только что изменил что-то в регулярном выражении, используемом для проверки числа, и теперь оно отлично работает !!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...