Asp.net-Mvc
服務層驗證
我正在嘗試在我的應用程序中實施驗證策略。我有一個 MVC 層、服務層、儲存庫和域 POCO。現在在 MVC 層,我在我的視圖模型上使用數據註釋來驗證使用者輸入,從而允許我給使用者快速回饋。在控制器中,我呼叫 ModelState.IsValid 來檢查輸入,然後再使用 automapper 設置域對象。
這就是我的麻煩所在。我將我的域對像傳遞給需要根據我的業務規則對其進行驗證的服務,但是如何將驗證錯誤傳遞回控制器?我發現的範例執行以下操作之一:
- 在 Service 層拋出異常並在 Contoller 中擷取。但這似乎是錯誤的,例外情況肯定是例外,我們應該返回一些有意義的東西。
- 使用 ModelStateWrapper 並將 ModelStateDictionary 注入到服務中。但是這種方法最終會展開為循環依賴(控制器依賴於服務,服務依賴於控制器),這似乎是一種不好的程式碼味道。
- 向 POCO 添加一個 Validate 方法。問題在於業務規則可能依賴於其他 POCO 對象,因此這肯定應該在有權訪問所需表和對象的服務中完成。
有沒有我想念的更簡單的方法?我已經看到了很多關於這個的問題,但除了上面提到的之外沒有具體的解決方案。我認為服務中任何進行驗證的方法都可以傳回一些我可以在控制器中使用的鍵/值對象,但我不確定這個策略以後是否會出現問題。
我認為一種非常優雅的方法是在您的服務上使用一個 validate 方法,該方法從業務邏輯返回一個模型錯誤字典。這樣,就不會向服務注入 ModelState - 服務只是進行驗證並返回任何錯誤。然後由控制器將這些 ModelState 錯誤合併回它的 ViewData。
因此服務驗證方法可能如下所示:
public IDictionary<string, string> ValidatePerson(Person person) { Dictionary<string, string> errors = new Dictionary<string, string>(); // Do some validation, e.g. check if the person already exists etc etc // Add model erros e.g.: errors.Add("Email", "This person already exists"); }然後您可以在控制器中使用擴展方法將這些錯誤映射到 ModelState,例如:
public static class ModelStateDictionaryExtensions { public static void Merge(this ModelStateDictionary modelState, IDictionary<string, string> dictionary, string prefix) { foreach (var item in dictionary) { modelState.AddModelError((string.IsNullOrEmpty(prefix) ? "" : (prefix + ".")) + item.Key, item.Value); } } }然後您的控制器將使用:
ModelState.Merge(personService.ValidatePerson(person), "");