在asp.net MVC2中将错误(异常消息)从存储库传递到控制器操作
本文关键字:存储 操作 控制器 消息 MVC2 net asp 异常 错误 | 更新日期: 2023-09-27 17:49:33
我一直在尝试开发一个应用程序,使用存储库模式,如在书呆子晚餐应用程序,但我想处理存储库中的异常,并将异常消息传递回控制器,以便我可以在一个漂亮的页面输出消息给用户。
我如何传递这个异常消息,或者甚至传递一个异常已经在存储库中发生。
http://www.asp.net/ajaxlibrary/jquery_errors.ashx在上面url的示例中,"_repository. net"HasErrors"被用作检查,但我想知道这在c#中的存储库中的实现是什么,因为我不知道这是如何实现的,也不知道是否有可能也得到错误消息。
01.// GET: /HandlejQueryErrors/Contact/Create
02.public ActionResult Create()
03.{
04. return View();
05.}
06.
07.// POST: /HandlejQueryErrors/Contact/Create
08.[HttpPost]
09.public ActionResult Create(ContactViewModel viewModel)
10.{
11. var response = new AjaxResponseViewModel();
12.
13. try
14. {
15. var contact = _repository.SaveOrUpdate(viewModel);
16. if (!_repository.HasErrors)
17. {
18. response.Success = true;
19. response.Message = "Your contact was successfully created!";
20. }
21. else
22. {
23. response.Message = "There was an error updating your contact!";
24. }
25. }
26. catch (Exception exception)
27. {
28. response.Success = false;
29. response.Messages exception.Message;
30. }
31.
32. return Json(response);
33.}
你可以允许你的存储库的异常落空,并覆盖你的控制器的onactionperformed方法来处理特定的错误。例子:
protected override void OnActionExecuted(ActionExecutedContext filterContext)
{
if (filterContext.Exception is RepositoryException)
{
filterContext.ExceptionHandled = true;
filterContext.Result = View("Exception", filterContext.Exception);
}
base.OnActionExecuted(filterContext);
}
所以,一般在ASP。. NET MVC你需要处理两种错误:验证错误和系统错误。
对于系统错误,那些由于某些系统规则违反而发生的错误(如插入期间数据库中的外键约束违反),您应该使用try-catch操作符,然后以某种方式将它们传递给视图以显示给用户。
对于验证错误,您应该阅读ASP。. NET MVC验证:
- 使用数据注释验证器进行验证——在这里你可以看到如何使用内置的注释属性验证简单的验证规则。
- 使用服务层进行验证——这是一个更高级的主题,您可以在其中学习如何验证更复杂的验证规则(例如,用于相互连接的属性等)
因此,作为结论,考虑将关于域/业务功能的关注与与验证相关的关注分开。他们应该拥有的唯一共同的东西(在完美的场景中)是显示验证结果的视图。
我个人(采用第二种方法)甚至在验证中进行保存,以便验证实现了解域/业务逻辑并操纵它来验证所有规则。在验证结束时,如果满足所有规则,则尝试保存数据,如果不成功,则返回验证错误消息。这也是一个很好的开始,可以更进一步,甚至本地化您的自定义验证消息。
我希望这对你有帮助!
我个人仍然喜欢由ScottGu开始的GetRuleViolations()方法,并且只会在Repository上遵循这个方法。
在控制器中,我将执行(这里是pseudo):[HttpPost]
public ActionResult ControllerAction(MyViewModel viewModel)
{
ModelState.AddRuleViolations(viewModel.GetRuleViolations);
if (!ModelState.IsValid)
{
return View();
}
// Perform repository action (pseudo code to follow)
_repository.ClearErrorState();
_repository.DoSomething();
ModelState.AddRuleViolation(repository.GetRuleViolations());
if (!ModelState.IsValid)
{
return View();
}
return RedirectToAction("Foo","Bar");
}
class Repository
{
List<RuleViolation> _errors = new List<RuleViolation>();
public void ClearErrorState()
{
_errors.Clear();
}
public void DoSomething(...)
{
try
{
DoSomthingThatFails();
}
catch (Exception ex)
{
_errors.Add(new RuleViolation(null, "Error while saving customer");
_errors.Add(new RuleViolation("SSN", "SSN must be unique"); // This one I struggle with as bad design, tying UI element to data elements is bad, so generally I try to prevent everything when checking the viewmodel and only catch general (unforeseen) errors here.
}
}
public IEnumerable<RuleViolation> GetRuleViolations()
{
return _errors;
}
}