CheeseAndTuna
CheeseAndTuna

Reputation: 1

Passing Errors (Exception Messages) from Repository to Controller Action in asp.net MVC2

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.

Upvotes: 0

Views: 4444

Answers (3)

Tengiz
Tengiz

Reputation: 8399

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!

Upvotes: 1

cwharris
cwharris

Reputation: 18125

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);
}

Upvotes: 1

Mirko
Mirko

Reputation: 4282

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

Upvotes: 0

Related Questions