【问题标题】:ASP.NET MVC3 double validation (comma, point, null)ASP.NET MVC3 双重验证(逗号、点、空)
【发布时间】:2011-11-09 20:34:31
【问题描述】:

我的控制器如下所示:

 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 但这根本没有解决我的问题(第二部分)......

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

【问题讨论】:

    标签: c# asp.net-mvc validation


    【解决方案1】:

    好的,所以您在 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
    }
    

    【讨论】:

    • 好的,谢谢,那行得通。但只是一个问题:为什么使用小数而不是双精度?
    • @Matthias,始终使用小数表示货币:stackoverflow.com/questions/1165761/…,除非您想开始失去货币 :-) 双打使用 IEEE 754 存储,而小数存储在 10 进制中。
    • 谢谢。我在测试时才意识到的另一件事:如果用户输入字符串而不是数字,它不会发出警告。是否有类似 [Decimal(ErrorMessage = "Please give a decimal number")] 的注释可以用来验证?
    • @Matthias,这很奇怪。这对我来说可以。当您键入一些字符串时,将调用自定义模型绑定器,并且 Convert.ToDecimal 引发异常,该异常被拦截并显示错误消息。不是发生在你身上吗?模型绑定器没有被调用吗?
    • 添加(如果 ModelState.IsValid)检查我的 HttpPost Edit 方法,它现在可以工作了。但是消息“值 'qsdf' 对 Saldo 无效。”显示。是否可以更改此消息?我的应用程序是荷兰语,所以我所有的错误消息也应该是荷兰语。
    猜你喜欢
    • 1970-01-01
    • 2012-05-22
    • 1970-01-01
    • 2012-08-08
    • 2011-08-26
    • 2012-01-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多