0

Forgive me for my ignorance but at the moment I'm struggling to figure out the best approach to catch an exception and display a message to the client based on an exception type.

My architecture:

Repository

Page IPageRepository.FindDefault()
{
    try
    {
        return MapPageFromCategory.MapFromEntity(_context.tbl_Category.
                             FirstOrDefault(p =>
                                                p.IsLandingPage == true
                                            )
                     );
    }
    catch (Exception ex)
    {
        throw new ApplicationException("Error getting values from database :", ex);
    }
}

With the above as you can see it just fetches data from the DB, but in some scenarios I could get a object not set to an instance of an object exception due to physically no data in the table or a Null exception depending on the data passed in.

Now in both scenario I would like to generate a 404 exception which passes to my controller.

Controller

 public class PageController : ApiController
 {
   private IPageRepository _pageRepository;
   public PageController(IPageRepository pageRepository)
   {
      this._pageRepository = pageRepository;
   }
   // GET
   [HttpGet]
   [Route("")]
   public Page Get()
   {
       return this._pageRepository.FindDefault();
   }
}

My Controller hit's the method and if any of those exceptions are hit, what would be the best approach to intercept those exceptions and pass to the end client (Calling app) ?

Again apologies for the question, really trying to create some sort of systematic approach to exception handling.

Thanks for your time!

Tez Wingfield
  • 2,129
  • 5
  • 26
  • 46
  • 2
    Have a read of Eric Lippert's [Vexing Exceptions](https://blogs.msdn.microsoft.com/ericlippert/2008/09/10/vexing-exceptions/) - it might help you to formulate the best approach. – Enigmativity Sep 20 '16 at 10:07
  • Is `_context` a `DbContext` type? If yes, I would suggest creating context in each `Repository` method. Because you may end up in strange situations if multiple threads try to use the same `_context`. – Gabrielius Sep 20 '16 at 10:13
  • @Gabrielius Yes it is, It's my entities Context which derives from DbContext. My base class(Generic EntityRepository) instantiates the Context and in my derived class (PageRepository) it fetches from the base and passes into the Ctor in which I use IoC thus creating a new instance for that repo. – Tez Wingfield Sep 20 '16 at 10:19
  • @Enigmativity Thank you, I'll look into that now. – Tez Wingfield Sep 20 '16 at 10:19
  • 1
    @TezWingfield, if you have configured `IoC` to create a new instance of type which inherits `IPageRepository` each time you need it, there should be no problems. That is, new `PageRepository` which creates `Context` type object on instantiation per web request. [Otherwise you may run into issues](http://stackoverflow.com/questions/10585478/one-dbcontext-per-web-request-why) :) – Gabrielius Sep 20 '16 at 10:41
  • @Gabrielius Cheers for the heads up! – Tez Wingfield Sep 20 '16 at 10:49
  • @TezWingfield, no problem, stepped on that rake myself in the past ;) – Gabrielius Sep 20 '16 at 11:26

1 Answers1

0

You can either have a separate try/catch in the Controller class and handle the exception thrown from repository there or do something different.

You can create a class similiar to this:

public class Result
{
    public bool Succeded { get; private set; }

    protected Result(bool succeeded)
    {
        Succeded = succeeded;
    }
}

public class Result<TData> : Result
{
    public TData Data { get; private set; }

    protected Result(bool succeeded, TData data) : base(succeeded)
    {
        Data = data;
    }
}    

Then, you can return this from your repository and check in the controller if the call has succeeded. If not, throw a desired exception, which will set StatusCode accordingly.

Jakub Jankowski
  • 731
  • 2
  • 9
  • 20
  • I used a similar process - not exact but similar. The link in one of the comments helped me identify the best approach. Thanks for your time. – Tez Wingfield Sep 20 '16 at 11:59