ASP.NET MVC3双重验证(逗号,点,null)

Mat*_*ias 5 c# validation asp.net-mvc

我的控制器看起来像这样:

 public class PortefeuilleController : Controller
    {
            public ActionResult Create()
            {
                return View(new PortefeuilleViewModel{Saldo = 0.0});
            }
    }
Run Code Online (Sandbox Code Playgroud)

我的创建视图如下所示:

@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>
}
Run Code Online (Sandbox Code Playgroud)

我的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; }
}
Run Code Online (Sandbox Code Playgroud)

我的问题在于"Saldo"领域.我想验证它如下:

将字段留空应该是有效的(因为我的代码隐藏将""更改为"0.0"并将该值保存在数据库中).但是,例如,'19,99'和'19 .99'也应该作为有效传递.其余的都是无效的.

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

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

Dar*_*rov 22

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

使用钱时的第一件事(我认为该Saldo字段代表的是使用小数,而不是双倍).所以第一个改变是:

[DisplayName("Saldo")]
public decimal Saldo { get; set; }
Run Code Online (Sandbox Code Playgroud)

好了,现在让我们根据你的情况调整一下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;
    }
}
Run Code Online (Sandbox Code Playgroud)

当然会注册在Application_Start:

ModelBinders.Binders.Add(typeof(decimal), new DecimalModelBinder());
Run Code Online (Sandbox Code Playgroud)

在这个阶段,我们已经解决了服务器端验证问题.就客户端验证而言,您可以使用Microsoft发布的jQuery全球化插件.Scott Hanselman也在博客上写过这篇文章.因此,一旦安装它,您可以强制客户端文化并覆盖$.validator.methods.number负责执行客户端验证的方法:

$.validator.methods.number = function (value, element) {
    // TODO: return true or false if value is a valid decimal
}
Run Code Online (Sandbox Code Playgroud)

  • @Matthias,始终使用小数表示货币:http://stackoverflow.com/questions/1165761/decimal-vs-double-which-one-should-i-use-and-when 除非你想开始失去货币:-)双精度数使用 IEEE 754 存储,而小数存储在 10 基数中。 (2认同)