2011-09-03 42 views
4

我的控制器看起来是这样的:ASP.NET MVC3双重验证(逗号,点,空)

public class PortefeuilleController : Controller 
    { 
      public ActionResult Create() 
      { 
       return View(new PortefeuilleViewModel{Saldo = 0.0}); 
      } 
    } 

我创建视图看起来是这样的:

@model PortefeuilleViewModel 

@{ 
    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>PortefeuilleViewModel</legend> 

     <div class="editor-label"> 
      @Html.LabelFor(model => model.Naam) 
     </div> 
     <div class="editor-field"> 
      @Html.EditorFor(model => model.Naam) 
      @Html.ValidationMessageFor(model => model.Naam) 
     </div> 

     <div class="editor-label"> 
      @Html.LabelFor(model => model.Saldo) 
     </div> 
     <div class="editor-field"> 
      @Html.EditorFor(model => model.Saldo) 
      @Html.ValidationMessageFor(model => model.Saldo) 
     </div> 

     <p> 
      <input type="submit" value="Create" /> 
     </p> 
    </fieldset> 
} 

而且我PortefeuilleViewModel看起来是这样的:

public class PortefeuilleViewModel 
{ 
    [DisplayName("Naam")] 
    [Required(ErrorMessage = "Gelieve een naam in te voeren")] 
    public string Naam { get; set; } 

    [DisplayName("Saldo")] 
    public double Saldo { get; set; } 
} 

我的问题在于“Saldo”字段。我想验证它如下:

离开字段为空应该是有效的(因为我的代码隐藏将更改为“0.0”并将该值保存在数据库中)。但是,例如,'19,99'和'19.99'都应该被认为是有效的。其余的都是无效的。

我真的不知道该如何解决这个问题。我已经找到这篇文章:http://haacked.com/archive/2011/03/19/fixing-binding-to-decimals.aspx 但这并没有解决(第二部分)我的问题...

任何帮助将不胜感激。谢谢。

回答

20

好的,所以你有验证激活2级:服务器端和客户端。首先处理服务器端验证问题。

用钱工作的第一件事(这是我认为Saldo字段代表的是使用小数,而不是双打)。因此,第一个变化是:

[DisplayName("Saldo")] 
public decimal Saldo { get; set; } 

好了,现在让我们适应了一点Haacked模型绑定到你的情况(接受.,作为小数点分隔符以及空值)

public class DecimalModelBinder : IModelBinder 
{ 
    public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) 
    { 
     var valueResult = bindingContext.ValueProvider.GetValue(bindingContext.ModelName); 
     if (string.IsNullOrEmpty(valueResult.AttemptedValue)) 
     { 
      return 0m; 
     } 
     var modelState = new ModelState { Value = valueResult }; 
     object actualValue = null; 
     try 
     { 
      actualValue = Convert.ToDecimal(
       valueResult.AttemptedValue.Replace(",", "."), 
       CultureInfo.InvariantCulture 
      ); 
     } 
     catch (FormatException e) 
     { 
      modelState.Errors.Add(e); 
     } 

     bindingContext.ModelState.Add(bindingContext.ModelName, modelState); 
     return actualValue; 
    } 
} 

这当然将在Application_Start注册:

ModelBinders.Binders.Add(typeof(decimal), new DecimalModelBinder()); 

在这个阶段,我们已经解决了服务器端验证的问题。就客户端验证而言,您可以使用Microsoft发布的jQuery globalization plugin。 Scott Hanselman也有关于它的blogged。所以,一旦你安装它,你可能会迫使客户端文化和覆盖$.validator.methods.number方法负责执行客户端验证:

$.validator.methods.number = function (value, element) { 
    // TODO: return true or false if value is a valid decimal 
} 
+1

好,谢谢你,那工作。但只是一个问题:为什么使用小数点以上的双倍? – Matthias

+1

@Matthias,总是使用货币小数:http://stackoverflow.com/questions/1165761/decimal-vs-double-which-one-should-i-use-and-when除非你想开始放松货币: - )使用IEEE 754存储双精度,而小数则存储在10个基数中。 –

+0

谢谢。在测试时,我只是意识到另外一件事情:如果用户输入字符串而不是数字,则不会发出警告。是否有像[Decimal(ErrorMessage =“Please give a decimal number”)]这样的注释可用于验证? – Matthias