2011-12-04 42 views
8

Tôi đang sử dụng MVC3 và tôi muốn có biểu mẫu Đăng nhập và biểu mẫu Đăng ký trên cùng một trang. Để đạt được điều đó tôi đã xây dựng LogInRegisterViewModel như sau:MVC3 So sánh Thuộc tính, lỗi phía máy khách

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

Nó mang lại cho tôi những gì tôi muốn (hai hình thức trên cùng một màn hình) và đăng tải các dữ liệu để sửa chữa bộ điều khiển và trở về và hiển thị lỗi cho các hình thức (nếu có). Vấn đề duy nhất tôi có là với CompareAttribute mà tôi có trên tài sản ConfirmPassword trong RegisterViewModel tôi:

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 các mật khẩu không bao giờ bằng nhau (~ Tôi luôn luôn nhận được một lỗi xác nhận từ so sánh với một thông điệp nói với tôi rằng họ không bằng nhau), ngay cả khi họ (tôi chắc chắn về điều đó). HTML trong trình duyệt là:

<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> 

Tôi có một cảm giác rằng nó là tất cả về thuộc tính này: dữ liệu val-equalto-khác = "* Password"

CompareAttribute hoạt động tốt, khi tôi sử dụng RegisterViewModel trực tiếp. Bất cứ ai đã đi vào điều này trước? Nó là một lỗi hay tôi đang làm điều gì đó sai? Làm thế nào để so sánh để làm việc trong trường hợp của tôi?

Trả lời

15

Nó sẽ hoạt động với thuộc tính [Compare("Password", ErrorMessage = "Passwords do not match.")] nhưng có vẻ như đây thực sự là lỗi trong tệp jquery.validate.unobtrusive.js. Vấn đề là trong mã này:

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); 
}); 

Vì vậy, nó cố gắng tìm điều khiển khác bằng phương pháp tìm JQuery. Nhưng "." dot ký tự không được thoát trong biến fullOtherName (trong trường hợp của bạn, nó sẽ chứa: "Register.Password") như được mô tả trong số SO question này. Đó là lý do tại sao nó hoạt động khi bạn chỉ sử dụng RegisterViewModel trực tiếp bởi vì sau đó không có dấu chấm trong tên.

Để khắc phục nó, bạn cần phải thêm một dòng vào chức năng appendModelPrefix:

//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; 
} 
+0

Hoạt động như một sự quyến rũ, cảm ơn. –

+1

Ngay cả bản sửa lỗi này cũng có lỗi của riêng nó. Javascript ".replace" chỉ thay thế phiên bản đầu tiên của "." và bỏ qua phần còn lại. Trong các mô hình phức tạp, bất kỳ tài sản nào có nhiều hơn một giai đoạn sẽ chịu chung số phận như mã ban đầu. Để khắc phục nó, bạn nên sử dụng: value = value.split ('.'). Join ('\\.'); –

+0

@NickBork đẹp bắt :). Tôi đã cập nhật câu trả lời của mình. – nemesv

0

câu trả lời Rất tốt, nemesv.

Chỉ có một điều cần thêm cho những tân binh:

function g(a,b){if(a.indexOf("*.")===0)a=a.replace("*.",b);return a} 

trở thành

function g(a,b){if(a.indexOf("*.")===0)a=a.replace("*.",b);a=a.split('.').join('\\.');return a} 

trong .min.js

Nếu khi bạn xuất bản, các lỗi trở lại.

Các vấn đề liên quan