0

I have been trying to develop an app using the repository pattern like in the Nerd Dinner application however I would like to handle exceptions in the repository and pass the exception messages back to the controller so that I can output the message in a nice page to the user.

How do I pass back this exception message, or even pass that an exception has occured in the repository.

http://www.asp.net/ajaxlibrary/jquery_errors.ashx

In the following example from the above url, "_repository.HasErrors" is used as a check but I want to know what the implementaion of this is in the repository in C# as I dont know how this is implemented and also if its possible to also get the error message as well.

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.}  

Thanks in advance.

CharlesB
  • 86,532
  • 28
  • 194
  • 218

3 Answers3

1

You could allow your repository's exceptions to fall through, and override your controller's OnActionExecuted method to handle specific errors for you. Example:

protected override void OnActionExecuted(ActionExecutedContext filterContext)
{
    if (filterContext.Exception is RepositoryException)
    {
        filterContext.ExceptionHandled = true;

        filterContext.Result = View("Exception", filterContext.Exception);
    }

    base.OnActionExecuted(filterContext);
}
cwharris
  • 17,835
  • 4
  • 44
  • 64
  • So would the [HandleError] attribute do somthing similar to what you are proposing anyway? What would be the definition of the RepositoryException that you have used above? – CheeseAndTuna Apr 09 '11 at 22:36
  • I would check this out: http://stackoverflow.com/questions/5226791/custom-error-pages-on-asp-net-mvc3 – cwharris Apr 12 '11 at 03:17
  • Also, the repository exception is any exception you're expecting to receive from your repository. – cwharris Apr 12 '11 at 03:18
1

So, in general in ASP.NET MVC you need to handle 2 kinds of errors: Validation errors, and System errors.

For System errors, those occurring because of some system rules violation (like foreign key constraint violation in database during insert), you should use try-catche operator and then pass them to the view in some way to show them to the user.

For validation errors, you should read about ASP.NET MVC Validation:

So, as a conclusion, think of separating the concerns about domain/business functionality from the concerns related to validation. The only common thing they should have (in the perfect scenario) is a view where you show the results of validation.

Personally I (taking 2-nd approach) even do a save in validation, so that Validation implementation knows about domain/business logic and manipulates it to validate all the rules. In the end of validation, if all rules were met, then it tries to save the data, and returns the validation error message in case of non-success. This is also a good start to go further and even localize your custom validation messages.

I hope this helps!

Tengiz
  • 8,011
  • 30
  • 39
  • Yes this is the exact thing which I want to do but if I used the try catch in all my repository methods to catch the system errors how to I pass that exception back to the controller action that called the repository method so that I can tell the user that their was a system error? – CheeseAndTuna Apr 09 '11 at 22:40
  • You should use try-catch in methods where you have a mechanism to return back the info about the exception. I think that should not happen in repository, they should not catch the system exceptions; or, the better, they should catch and throw another exception with more clear error message. I would recommend using this approach in the validation layer, where you catch the exception and return the validation error together with all validation errors occurred during this validation. And the controller can put all those errors into model state errors so that the view can show them as a summary. – Tengiz Apr 10 '11 at 07:16
0

I personally still like the GetRuleViolations() approach started by ScottGu and would simply follow this through on the Repository.

In the controller I would do (pseudo here):

[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;
  }
}
Mirko
  • 4,284
  • 1
  • 22
  • 19
  • with this system errors, would get mixed with data validation errors. validation dataannotations take care of validation errors in MVC2. Would it be possible to do somthing similar but without adding to RuleViolations and add to a different list instead maybe for system errors? Any ideas what the implementaion of the _repository.HasErrors might actually be from the blog post above? as that might be some sort of list I guess? he seems to be using it after _repository.SaveOrUpdate(viewModel), so is there somthing special in SaveOrUpdate(),what do you think that implementation of that method is? – CheeseAndTuna Apr 09 '11 at 22:54