2016-02-23 57 views
3

我有問題,驗證在客戶端的一個領域,這是我的代碼:在客戶端驗證MVC場

型號:

public class Registration 
    { 
     public int Id { get; set; } 
     [IsUserExistAttribute(ErrorMessage = "Email already exists!")] 
     [EmailAddress(ErrorMessage = "Please enter valid Email")] 
     [Required(ErrorMessage = "Email is required")] 
     public string Email 
     { 
      get; set; 

     } 
     [MustBeTrue(ErrorMessage = "Please Accept the Terms & Conditions")] 
     public bool TermsAndConditions { get; set; } 


    } 

ValidationAttribute:

public class IsUserExistAttribute : ValidationAttribute,IClientValidatable 
    { 
     public override bool IsValid(object email) 
     { 
      DemoDbContext demoContext=new DemoDbContext(); 
      string emailString = Convert.ToString(email); 
      if (demoContext.Registrations.Any(a=>a.Email.Contains(emailString))) 
      { 
       return false; 
      } 
      return true; 
     } 

     public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context) 
     { 
      yield return new ModelClientValidationRule 
      { 
       ErrorMessage = this.ErrorMessage, 
       ValidationType = "emailvalidate" 
      }; 
     } 
    } 

查看:

@using (Html.BeginForm()) 
{ 
    @Html.AntiForgeryToken() 

    <div class="form-horizontal"> 
     <h4>Registration</h4> 
     <hr /> 
     @Html.ValidationSummary(true, "", new { @class = "text-danger" }) 
     <div class="form-group"> 
      @Html.LabelFor(model => model.Email, htmlAttributes: new { @class = "control-label col-md-2" }) 
      <div class="col-md-10"> 
       @Html.EditorFor(model => model.Email, new { htmlAttributes = new { @class = "form-control" } }) 
       @Html.ValidationMessageFor(model => model.Email, "", new { @class = "text-danger" }) 
      </div> 
     </div> 

     <div class="form-group"> 
      @Html.LabelFor(model => model.TermsAndConditions, htmlAttributes: new { @class = "control-label col-md-2" }) 
      <div class="col-md-10"> 
       <div class="checkbox"> 
        @Html.EditorFor(model => model.TermsAndConditions) 
        @Html.ValidationMessageFor(model => model.TermsAndConditions, "", new { @class = "text-danger" }) 
       </div> 
      </div> 
     </div> 

     <div class="form-group"> 
      <div class="col-md-offset-2 col-md-10"> 
       <input type="submit" value="Create" class="btn btn-default" /> 
      </div> 
     </div> 
    </div> 
} 

打倒這個窩rks罰款,但我的問題是這IsUserExistAttribute不驗證它在客戶端,在服務器端它驗證並給出如郵件已存在!

但是,我希望它也驗證客戶端。那麼,實現這個目標的好方法是什麼?另一種方法是也歡迎:)

我想這樣的事情似乎沒有成功:

$.validator.addMethod("emailvalidate", function (value, element) { 
      var is_valid = false; 
      $.ajax({ 
       // as before... 
       async: false, 
       success: function (data) { 
        is_valid = data === 'True'; 
       } 
      }); 
      return is_valid; 
     }, "Username not available."); 
+0

爲什麼你想推倒重來?爲此,MVC帶有一個'[Remote]'屬性。 –

+0

@StephenMuecke會造成併發問題。如果我使用'[remote]'驗證 –

+0

然後你做得不對。 –

回答

2

MVC已經配備了RemoteAttribute用於客戶端驗證(參見How to: Implement Remote Validation in ASP.NET MVC)所以你想少點重新發明輪子。 (作爲一個方面說明,您當前錯過了爲客戶端驗證添加規則所必需的方法$.validator.unobtrusive.adapters.add())。

但您的當前驗證屬性存在一些問題。驗證屬性不應該訪問數據庫,並且您無法單元測試您的代碼。並且您將在控制器方法中再次重複屬性中的代碼,該方法由ajax函數調用,違反了DRY主體並使其難以維護您的代碼。

相反,建立在你的控制器爲你的數據庫代碼的私有方法(或者在一個單獨的服務的公共方法),例如

private bool IsEmailUnique(string email) 
{ 
    return !db.Registrations.Any(a => a.Email.Contains(email))) 
} 

那麼對於客戶端驗證,裝點你的RemoteAttribute

財產
[Remote("IsEmailValid", "ControllerName", ErorMessage = "...")] 
public string Email { get; set; } 

並添加控制器的方法

public JsonResult IsEmailValid(string email) 
{ 
    bool isValid = IsEmailUnique(email); 
    return Json(isValid, JsonRequestBehavior.AllowGet); 
} 

,然後如果你也想擁有服務器端驗證,當您提交表單,調用相同的方法,如果無效,加ModelStateError

public ActionResult Register(Registration model) 
{ 
    bool isValid = IsEmailUnique(model.Email); 
    if (!isValid) 
    { 
     ModelState.AddModelError("Email", "..."); 
    } 
    if (!ModelState.IsValid) 
    { 
     return View(model); 
    } 
    // save and redirect 
}