【问题标题】:MVC 3 client side validation, model binding decimal value and culture (different decimal separator)MVC 3客户端验证,模型绑定十进制值和文化(不同的小数分隔符)
【发布时间】:2012-04-02 16:27:21
【问题描述】:

我正在尝试让我的客户端验证(模型绑定)以支持不同的文化,并且我发现了一个关于我正在尝试实施的主题的有趣博客。

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 验证不处理逗号。

【问题讨论】:

    标签: asp.net-mvc-3 model


    【解决方案1】:

    最后,通过了解自定义 DecimalModelBinder 只会处理服务器端验证,不会影响处理客户端验证的 jquery.validate.js,我找到了问题的解决方案。

    延长验证解决了我的问题。

    通过新的 .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

    【讨论】:

    • 扩展验证后是否还需要 DecimalModelBinder?
    • 是的,你知道。如果没有,那么 ModelBinder(服务器端)将添加一个错误。事实上,如果您不想在 POST 之前进行验证,您可以只使用 DecimalModelBinder。
    • 谢谢我遇到了同样的问题,并且能够使用您的解决方案通过服务器端和客户端验证解决它
    • 我通过覆盖客户端的默认验证解决了这个问题,不需要ModelBinder。
    • 绝对很棒。非常感谢。
    【解决方案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;
            }
        }
    

    它对我有用。

    更新

    如果您使用的是局部视图,请使用 $.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,它将正确解析十进制或逗号。 问候

    【讨论】:

    • 我试试看。但我主要担心的是我的断点没有被命中。因此,如果代码从未被执行,我看不出更改应该如何解决我的问题
    • 如果您点击您的帖子操作?并按照你说的做了一切,所以我看不出你的断点没有被命中的原因。
    • 更新:我的自定义十进制模型绑定器在实际更新时触发,但客户端验证仍然失败。我会更新我的主要帖子。问题是提交帖子之前的验证
    • 更新:在我的回答中添加了一些建议。
    • 据我了解,DecimalModelBinder 只会处理服务器端验证。不是我的问题的客户端验证
    【解决方案3】:

    我刚刚解决了这个问题,将 jquery.validate.js 的第 1050 行替换为以下代码:

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

    我刚刚更改了用于验证数字的正则表达式,现在效果很好!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-08-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-07-26
      • 1970-01-01
      相关资源
      最近更新 更多