Подтвердить что ты не робот

Проверка на стороне клиента 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 hereenter image description here

4b9b3361

Ответ 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 на регулярное выражение, используемое для проверки числа, и теперь он отлично работает!!