本文介绍了MVC3 CompareAttribute,客户端错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用 MVC3,我希望在同一页面上有登录表单和注册表单.为了实现这一点,我构建了 LogInRegisterViewModel 如下:

公共类 LogInRegisterViewModel{公共登录ViewModel登录{获取;放;}公共 RegisterViewModel 注册 { 获取;放;}}

它给了我我想要的东西(在同一个屏幕上有两个表单)并将数据发布到正确的控制器并返回并显示表单的错误(如果有).我遇到的唯一问题是我在 RegisterViewModel 中具有上述 ConfirmPassword 属性的 CompareAttribute:

公共类RegisterViewModel{[必需的][Display(Name = "友好用户名")]公共字符串用户名 { 获取;放;}[必需的][Display(Name = "E-mail address")]公共字符串电子邮件{获取;放;}[必需的][数据类型(数据类型.密码)][显示(名称=密码")][StringLength(16, ErrorMessage = "{0} 必须至少有 {2} 个字符长.", MinimumLength = 6)]公共字符串密码{获取;放;}[数据类型(数据类型.密码)][Display(Name = "确认密码")][Compare("密码", ErrorMessage = "密码不匹配.")]公共字符串 ConfirmPassword { get;放;}}

客户端的密码永远不相等(〜我总是从比较中收到验证错误,并有一条消息告诉我它们不相等),即使它们是(我确信这一点).浏览器中的 HTML 是:

 

<label for="Register_Password">密码</label>

<div class="editor-field"><input class="valid" data-val="true" data-val-length="密码必须至少有 6 个字符长."" data-val-length-max="16" data-val-length-min="6" data-val-required="密码字段是必需的.id="Register_Password" name="Register.Password" type="密码"><span class="field-validation-valid" data-valmsg-for="Register.Password" data-valmsg-replace="true"></span>

<div class="editor-label"><label for="Register_ConfirmPassword">确认密码</label>

<div class="editor-field"><input class="input-validation-error" data-val="true" data-val-equalto="密码不匹配."data-val-equalto-other="*.Password" id="Register_ConfirmPassword" name="Register.ConfirmPassword" type="password"><span class="field-validation-error" data-valmsg-for="Register.ConfirmPassword" data-valmsg-replace="true"><span class=""generated="true" for="Register_ConfirmPassword">密码不匹配.</span></span>

我有一种感觉,就是这个属性:data-val-equalto-other="*.Password"

CompareAttribute 工作正常,当我直接使用 RegisterViewModel 时.以前有人遇到过这个吗?这是一个错误还是我做错了什么?如何让比较在我的情况下工作?

解决方案

它应该与 [Compare("Password", ErrorMessage = "Passwords do not match.")] 属性一起使用,但它似乎这确实是 jquery.validate.unobtrusive.js 文件中的一个错误.问题出在这段代码中:

adapters.add("equalto", ["other"], function (options) {var prefix = getModelPrefix(options.element.name),其他 = options.params.other,fullOtherName = appendModelPrefix(other, prefix),element = $(options.form).find(":input[name=" + fullOtherName + "]")[0];setValidationValues(options, "equalTo", element);});

因此它尝试使用 JQuery find 方法找到另一个控件.但是."dot 字符未在 fullOtherName 变量中转义(在您的情况下,它将包含:"Register.Password"),如本 SO 问题.这就是为什么当您只直接使用 RegisterViewModel 时它起作用的原因,因为名称中没有点.

要修复它,您需要在 appendModelPrefix 函数中添加一行:

//原文函数appendModelPrefix(值,前缀){if (value.indexOf("*.") === 0) {value = value.replace("*.", prefix);}返回值;}//固定的函数appendModelPrefix(值,前缀){if (value.indexOf("*.") === 0) {value = value.replace("*.", prefix);}value = value.split('.').join('\.');返回值;}

I am using MVC3 and I want to have LogIn form and Register form on the same page. To achieve that I built LogInRegisterViewModel as following:

public class LogInRegisterViewModel
{
    public LogInViewModel LogIn { get; set; }
    public RegisterViewModel Register { get; set; }
}

It gives me what I want (two forms on the same screen) and posts the data to correct controllers and returns and displays errors for forms (if any). The only problem I have is with CompareAttribute that I have above ConfirmPassword property in my RegisterViewModel:

public class RegisterViewModel
{
    [Required]
    [Display(Name = "Friendly user name")]
    public string UserName { get; set; }

    [Required]
    [Display(Name = "E-mail address")]
    public string Email { get; set; }

    [Required]
    [DataType(DataType.Password)]
    [Display(Name = "Password")]
    [StringLength(16, ErrorMessage = "The {0} must be at least {2} characters long.", MinimumLength = 6)]
    public string Password { get; set; }

    [DataType(DataType.Password)]
    [Display(Name = "Confirm password")]
    [Compare("Password", ErrorMessage = "Passwords do not match.")]
    public string ConfirmPassword { get; set; }
}

Client-side the passwords are never equal (~ I always get a validation error from Compare with a message telling me that they are not equal), even if they are (I am sure about that). HTML in the browser is:

    <div class="editor-label">
        <label for="Register_Password">Password</label>
    </div>
    <div class="editor-field">
        <input class="valid" data-val="true" data-val-length="The Password must be at least 6 characters long." data-val-length-max="16" data-val-length-min="6" data-val-required="The Password field is required." id="Register_Password" name="Register.Password" type="password">
        <span class="field-validation-valid" data-valmsg-for="Register.Password" data-valmsg-replace="true"></span>
    </div>

    <div class="editor-label">
        <label for="Register_ConfirmPassword">Confirm password</label>
    </div>
    <div class="editor-field">
        <input class="input-validation-error" data-val="true" data-val-equalto="Passwords do not match." data-val-equalto-other="*.Password" id="Register_ConfirmPassword" name="Register.ConfirmPassword" type="password">
        <span class="field-validation-error" data-valmsg-for="Register.ConfirmPassword" data-valmsg-replace="true"><span class="" generated="true" for="Register_ConfirmPassword">Passwords do not match.</span></span>
    </div>

I have a feeling that it's all about this attribute: data-val-equalto-other="*.Password"

CompareAttribute works fine, when I use RegisterViewModel directly. Anyone has come into this before? Is it a bug or am I doing something wrong? How to make Compare to work in my case?

解决方案

It should work with the [Compare("Password", ErrorMessage = "Passwords do not match.")] attribute but it seems this is really a bug in the jquery.validate.unobtrusive.js file. The problem is in this code:

adapters.add("equalto", ["other"], function (options) {
    var prefix = getModelPrefix(options.element.name),
        other = options.params.other,
        fullOtherName = appendModelPrefix(other, prefix),
        element = $(options.form).find(":input[name=" + fullOtherName + "]")[0];

    setValidationValues(options, "equalTo", element);
});

So it tries to find the other control with the JQuery find method. But the "." dot character is not escaped in the fullOtherName variable (in your case it will contain: "Register.Password") as described in this SO question. That is the reason why it works when you only use RegisterViewModel directly because then there is no dots in the names.

To fix it you need to add one line to the appendModelPrefix function:

//original
function appendModelPrefix(value, prefix) {
    if (value.indexOf("*.") === 0) {
        value = value.replace("*.", prefix);
    }
    return value;
}

//fixed
function appendModelPrefix(value, prefix) {
    if (value.indexOf("*.") === 0) {
        value = value.replace("*.", prefix);
    }
    value = value.split('.').join('\.');
    return value;
}

这篇关于MVC3 CompareAttribute,客户端错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-20 05:28