For each of my business entities I have a corresponding view model.
对于我的每个业务实体,我都有一个相应的视图模型。
I have a generic CRUD controller that works like this:
我有一个通用的CRUD控制器,其工作方式如下:
[HttpPost]
public virtual ActionResult Create(TViewModel model, int? id)
{
// Validate input
if (!ModelState.IsValid)
return Json(Failure(createView, model.SelectLists(repository)));
// Prepare Model
var entity = new TModel();
// Add to repository
UpdateModel(entity);
repository.Add(entity);
repository.Save();
return Json(CreateSuccess(entity));
}
I use data annotations on my view model properties and this works great for simple input validation.
我在视图模型属性上使用数据注释,这对于简单的输入验证非常有用。
Now I have a case where I want to make sure a duplicate record isn't created by accident.
现在我有一个案例,我想确保不会偶然创建重复记录。
My first instinct is to put this logic in the repository's Add method. This implementation would be easy, but how do I get the repository to add a model state error and return some useful information to the user? I feel like there has to be a solution out there, but I haven't had much luck searching.
我的第一直觉是将此逻辑放在存储库的Add方法中。这个实现很简单,但是如何让存储库添加模型状态错误并将一些有用的信息返回给用户?我觉得必须有一个解决方案,但我没有太多的运气搜索。
Thanks for any help!
谢谢你的帮助!
3 个解决方案
#1
3
I would use exceptions.
我会使用例外。
- Throw your custom application exception at the Add method, if an enity is doubled.
- Wrap the Add method in a try block to catch this specific exception at the Create method.
-
Add a model state error based on the exception data at the catch block
根据catch块中的异常数据添加模型状态错误
try { repository.Add(entity); } catch(MyRepositoryException ex) { ViewData.ModelState.AddModelError(ex.Key, ex.Value.ToString(), ex.Message) } if (!ModelState.IsValid) return Json(Failure(createView, model.SelectLists(repository)));
如果enity加倍,则在Add方法中抛出自定义应用程序异常。
在Try块中包装Add方法以在Create方法中捕获此特定异常。
#2
1
An alternative to your approach would be to use the idea of a ModelStateWrapper
implementing IValidationDictionary
. It basically decouples the modelState, but still lets your repository/service interact with errors dictionary. This way error handling is all done via an interface and there's no need to reference any MVC-specific data object.
您的方法的替代方法是使用实现IValidationDictionary的ModelStateWrapper的想法。它基本上解耦了modelState,但仍然允许您的存储库/服务与错误字典交互。这种方式错误处理都是通过接口完成的,不需要引用任何特定于MVC的数据对象。
There's a good writeup on it here: http://www.asp.net/mvc/tutorials/validating-with-a-service-layer-cs, but the basic idea is:
这里有一篇很好的文章:http://www.asp.net/mvc/tutorials/validating-with-a-service-layer-cs,但基本思路是:
1) Pass an instance of your ModelStateWrapper to your repository during the controller's initialization:
1)在控制器初始化期间将ModelStateWrapper的实例传递给存储库:
public MyController()
{
repository = new MyRepository(new ModelStateWrapper(this.ModelState));
}
2) Add errors to it inside your repository:
2)在存储库中添加错误:
_validatonDictionary.AddError("Name", "Name is required.");
3) Handle errors like you normally would in your controller:
3)处理您通常在控制器中出现的错误:
if (!repository.Save())
return View();
#3
1
I hate answering my own questions, but I think I stumbled across the answer I was looking for while searching for something else:
我讨厌回答我自己的问题,但我想我在寻找其他东西时偶然发现了我正在寻找的答案:
http://nerddinnerbook.s3.amazonaws.com/Part3.htm
Looks like it was time for a back-to-basics review! I should have thought to go back and review my first tutorial as there was no way I was absorbing everything when I was first starting out.
看起来是回归基础评论的时候了!我应该想回去看看我的第一个教程,因为在我刚开始的时候我无法吸收所有东西。
Part 3 of the tutorial talks about implementing domain model validation that returns errors with property name and error message strings that are to be added to the controller's ModelState, which allows for this kind of validation:
本教程的第3部分讨论了实现域模型验证,该验证返回带有属性名称和错误消息字符串的错误,这些字符串将添加到控制器的ModelState中,从而允许进行此类验证:
if (ModelState.IsValid) {
try {
dinner.HostedBy = "SomeUser";
dinnerRepository.Add(dinner);
dinnerRepository.Save();
return RedirectToAction("Details", new{id=dinner.DinnerID});
}
catch {
ModelState.AddModelErrors(dinner.GetRuleViolations());
}
}
I don't know if I like the idea of raising exceptions for business rule violations, but the basic pattern will work well for my project. Hope this helps someone else!
我不知道我是否喜欢为违反业务规则而引发异常的想法,但基本模式对我的项目很有用。希望这有助于其他人!
#1
3
I would use exceptions.
我会使用例外。
- Throw your custom application exception at the Add method, if an enity is doubled.
- Wrap the Add method in a try block to catch this specific exception at the Create method.
-
Add a model state error based on the exception data at the catch block
根据catch块中的异常数据添加模型状态错误
try { repository.Add(entity); } catch(MyRepositoryException ex) { ViewData.ModelState.AddModelError(ex.Key, ex.Value.ToString(), ex.Message) } if (!ModelState.IsValid) return Json(Failure(createView, model.SelectLists(repository)));
如果enity加倍,则在Add方法中抛出自定义应用程序异常。
在Try块中包装Add方法以在Create方法中捕获此特定异常。
#2
1
An alternative to your approach would be to use the idea of a ModelStateWrapper
implementing IValidationDictionary
. It basically decouples the modelState, but still lets your repository/service interact with errors dictionary. This way error handling is all done via an interface and there's no need to reference any MVC-specific data object.
您的方法的替代方法是使用实现IValidationDictionary的ModelStateWrapper的想法。它基本上解耦了modelState,但仍然允许您的存储库/服务与错误字典交互。这种方式错误处理都是通过接口完成的,不需要引用任何特定于MVC的数据对象。
There's a good writeup on it here: http://www.asp.net/mvc/tutorials/validating-with-a-service-layer-cs, but the basic idea is:
这里有一篇很好的文章:http://www.asp.net/mvc/tutorials/validating-with-a-service-layer-cs,但基本思路是:
1) Pass an instance of your ModelStateWrapper to your repository during the controller's initialization:
1)在控制器初始化期间将ModelStateWrapper的实例传递给存储库:
public MyController()
{
repository = new MyRepository(new ModelStateWrapper(this.ModelState));
}
2) Add errors to it inside your repository:
2)在存储库中添加错误:
_validatonDictionary.AddError("Name", "Name is required.");
3) Handle errors like you normally would in your controller:
3)处理您通常在控制器中出现的错误:
if (!repository.Save())
return View();
#3
1
I hate answering my own questions, but I think I stumbled across the answer I was looking for while searching for something else:
我讨厌回答我自己的问题,但我想我在寻找其他东西时偶然发现了我正在寻找的答案:
http://nerddinnerbook.s3.amazonaws.com/Part3.htm
Looks like it was time for a back-to-basics review! I should have thought to go back and review my first tutorial as there was no way I was absorbing everything when I was first starting out.
看起来是回归基础评论的时候了!我应该想回去看看我的第一个教程,因为在我刚开始的时候我无法吸收所有东西。
Part 3 of the tutorial talks about implementing domain model validation that returns errors with property name and error message strings that are to be added to the controller's ModelState, which allows for this kind of validation:
本教程的第3部分讨论了实现域模型验证,该验证返回带有属性名称和错误消息字符串的错误,这些字符串将添加到控制器的ModelState中,从而允许进行此类验证:
if (ModelState.IsValid) {
try {
dinner.HostedBy = "SomeUser";
dinnerRepository.Add(dinner);
dinnerRepository.Save();
return RedirectToAction("Details", new{id=dinner.DinnerID});
}
catch {
ModelState.AddModelErrors(dinner.GetRuleViolations());
}
}
I don't know if I like the idea of raising exceptions for business rule violations, but the basic pattern will work well for my project. Hope this helps someone else!
我不知道我是否喜欢为违反业务规则而引发异常的想法,但基本模式对我的项目很有用。希望这有助于其他人!