2017-06-06 35 views
2

我正在一個網站上工作,只是試圖讓我的頭繞着一般結構。我在後臺使用「存儲庫模式」訪問數據庫。我有下面的代碼在我 UserRepository類:存儲庫模式 - 驗證對象和返回消息

public bool IsValid(User user) 
{ 
    if (_context.Users.Any(c => c.EmailAddress == user.EmailAddress)) 
    { 
    Message = "Email address already in use"; 
    return false; 
    } 

    return true; 
} 

,這是

[HttpPost] 
[AllowAnonymous] 
[ValidateAntiForgeryToken] 
public ActionResult Register(User user) 
{ 
    if (ModelState.IsValid) 
    { 
    var context = new Context("DatabaseContext"); 
    var userRepo = new UserRepository(context); 

    if (userRepo.IsValid(user)) 
    { 
     userRepo.Add(user); 
     // return to different view 
    } 
    else 
    { 
     // display userRepo.Message on page 
     return View(user); 
    } 
    } 

    return View(user); 
} 

我的問題是,我不認爲我會圍繞「消息」位正確地在這裏實現,但我無法在網上找到任何幫助我的東西(特別是在存儲庫周圍)。我認爲我應該改變返回類型 IsValid像結果(正如我已經看到的對話框),但我不知道。

任何幫助將不勝感激。

謝謝。

+0

現在,你有一個驗證標準,所以一個布爾將是有道理的。如果事情變得更加複雜,請考慮返回錯誤消息(字符串),然後檢查它是否爲空(成功)。或者如果需要的話,您可以儘量使用ModelState在控制器中執行的操作。 – robjam

回答

2

實現此目的的一種方法與您所建議的完全相同 - 更改退貨類型IsValid

在過去,我曾在我的「業務層」返回的ValidationResult,其中每對模型中的驗證錯誤和一個空的集合返回的記錄賬戶集合類似的驗證方法將被解釋爲一個有效的模式。

例如:

public class ValidationResult 
{ 
    public string FieldName { get; set; } 
    public string Message { get; set; } 
} 

public interface IValidator<T> 
{ 
    IEnumerable<ValidationResult> IsValid(T model); 
} 

//...in your implementation 
public IEnumerable<ValidationResult> IsValid(User user) 
{ 
    //Return a new ValidationResult per validation error 
    if (_context.Users.Any(c => c.EmailAddress == user.EmailAddress)) 
    { 
     yield return new ValidationResult 
     { 
      Message = "Email address already in use", 
      FieldName = nameof(user.EmailAddress) 
     }; 
    } 
} 

這然後可以通過表示層來解釋反饋給用戶。

+1

謝謝你。你不僅給了我一個很好的解決方案,而且你實際上幫助我理解了「收益回報」是如何工作的。 – Oyyou

+0

@oyyou請檢查我的答案。可能會幫助你更多地理解。 – Rajput

2

我同意你提到的問題。返回自定義類將是更好的方法IMO。

public ValidationResult IsValid(User user) 
{ 
    ValidationResult validationResult = new ValidationResult(true, ""); 
    if (_context.Users.Any(c => c.EmailAddress == user.EmailAddress)) 
    { 
    validationResult.Status = false; 
    validationResult.Message = "Email address already in use"; 
    return validationResult; 
    } 

    return validationResult; 
} 

這樣,StatusMessage給你所需要的所有信息。首先檢查狀態。如果它是錯誤的,請檢查消息中的確切細節。

+0

我喜歡這個。這很容易理解和實施。我將馬克奧利弗的答案作爲答案,因爲它可以擴展;但這仍然有效。謝謝! – Oyyou

1

雖然上述用戶提供的解決方案是好的,但我不認爲你是在正確的方式做這個。這種驗證電子郵件地址解決方案有一些缺點。

假設如果電子郵件是可用的(無效,因爲這不是有效的),那麼你必須返回錯誤的視圖。並且如果所有輸入的電子郵件地址可用,那麼最終用戶將多次得到這個錯誤,但整個視圖將在每個請求中呈現,這不是很好的做法。總是嘗試在這種情況下使用遠程驗證。

在您的模型屬性(電子郵件)上使用Remoteattribute,並嘗試通過JsonResult動態地在視圖中返回可用性消息。我給你演示示例可以隨意在代碼中實現。

[OutputCache(Location = OutputCacheLocation.None, NoStore = true)] 
public JsonResult IsEmailAvailable(string emailAddress) 
{ 
    if (!_context.Users.Any(c => c.EmailAddress == emailAddress)) 
    { 
     return Json(true, JsonRequestBehavior.AllowGet); 
    } 
    return Json("Email address already taken" , JsonRequestBehavior.AllowGet); 
} 

OutputCacheAttribute屬性是必需的,以防止ASP.NET MVC從緩存的驗證方法的結果。

和裝飾你的模型email屬性是這樣的:

//inside you model. 
    [Required] 
    [Remote("IsEmailAvailable", "YourControllerName")] 
    [RegularExpression(@"Your email address validation regex here", ErrorMessage = "Email address is not valid .")] 
    [Editable(true)] 
    public string Email{ get; set; } 

而且在Web.config文件中添加此片段允許使用遠程屬性:

<appSettings> 
<add key="ClientValidationEnabled" value="true" /> 
<add key="UnobtrusiveJavaScriptEnabled" value="true" /> 
</appSettings> 

並刪除下面的代碼來自register的操作方法。

if (userRepo.IsValid(user)) 
    { 
     userRepo.Add(user); //write this only inside code cause you will always get valid email now. 
     // return to different view 
    } 
    else 
    { 
     // display userRepo.Message on page 
     return View(user); 
    } 

我希望這會起作用。欲瞭解更多信息,請閱讀這篇文章。 https://msdn.microsoft.com/en-us/library/gg508808(vs.98).aspx

+0

客戶端驗證是一個很好的*補充*。您仍然需要對惡意/錯誤請求進行服務器驗證。 – Oliver

+0

這是提供服務器端驗證。在那裏我提到了客戶端驗證@ @ Oliver – Rajput

+0

幾乎總是有一些基於業務規則的驗證,例如一個電子郵件地址不能在兩個用戶之間重複。這就是爲什麼除了客戶端/表示級別驗證之外,業務級別驗證方法是一個很好的選擇。 – Oliver