2012-04-02 23 views
13

我試圖讓我的客戶端驗證(模型綁定)來支持不同的文化,並且我發現了一個有趣的博客,我正在努力實施。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中被改變使用我的自定義模型綁定器在小數和十進制?值

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

回答

19

最後,通過理解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

+0

擴展驗證後,是否還需要DecimalModelBinder? – Romias 2012-04-03 12:19:48

+0

是的,你這樣做。如果不是那麼ModelBinder(服務器端)將添加一個錯誤。實際上,如果您不想在POST之前進行驗證,則只能使用DecimalModelBinder。 – Kman 2012-04-03 12:25:02

+0

很高興你解決了它,並感謝張貼解決方案 – 2012-04-03 14:02:24

4

試試這個它稍作修改的版本:

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")重新申請驗證。如果不嘗試在您的網絡中設置全球化。配置(一個根,而不是在查看),以這樣的:

<configuration> 
    <system.web> 
    <globalization fileEncoding="utf-8" 
        requestEncoding="utf-8" 
        responseEncoding="utf-8" 
        culture="hr-HR" uiCulture="hr-HR" /> 
    </system.web> 
</configuration> 

我有全球化設置爲人力資源在這裏我們使用逗號作爲分隔符但我已經發布,將正確地解析小數或逗號DecimalModelBinder 。 Regards

+0

我會試試看。但我主要關心的是我的斷點沒有被擊中。所以如果代碼永遠不會被執行,我不會看到如何改變應該解決我的問題 – Kman 2012-04-02 16:46:13

+0

如果你打你的發佈行動?並做了像你所說的一切,然後我看不出你的斷點沒有被擊中的原因。 – 2012-04-02 17:00:48

+1

更新:我的自定義十進制模型聯編程序在實際更新時觸發,但客戶端驗證仍然失敗。我會更新我的主帖。問題是提交之前的驗證 – Kman 2012-04-02 17:00:58

1

我剛剛修復了這個問題用以下代碼替換jquery.validate.js的第1050行:

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

我剛剛修改了用於驗證數字的正則表達式,現在它工作的很棒!

相關問題