title: Web Api 2 - Returning NotFound(); vs throwing an exception with global exception handler
body: <p>I'm working on an API being developed with .net Web Api 2. I've seen many blog posts and SO questions about Web Api version 1, but answers using the changes made in version 2 seem to be scarce by comparison.</p>
  
  <p>Compare these two ways of handling 'errors' in a controller <code>ItemsController</code></p>
  
  <h3>A. Using methods that create objects from <code>System.Web.Http.Results</code></h3>
  
  <pre><code>// GET api/user/userID/item/itemID
  [Route("{itemID:int}", Name="GetItem")]
  [ResponseType(typeof(ItemDTO))]
  public IHttpActionResult Get(int userID, int itemID)
  {
      if (userID &lt; 0 || itemID &lt; 0) return BadRequest("Provided user id or item id is not valid");
      ItemDTO item = _repository.GetItem(itemID);
  
      if (item == null) return NotFound();
  
      if (item.UserID != userID) return BadRequest("Item userID does not match route userID");
  
      return Ok&lt;ItemDTO&gt;(item);
  }
  </code></pre>
  
  <h3>B. Throwing exceptions that can be caught by registering a custom Global Exception Handler</h3>
  
  <pre><code>// ex) in WebApiConfig.cs
  // config.Services.Replace(typeof(IExceptionHandler), new GlobalExceptionHandler());
  public class GlobalExceptionHandler : ExceptionHandler
  {
      public override void Handle(ExceptionHandlerContext context)
      {
          Exception exception = context.Exception;
  
          HttpException httpException = exception as HttpException;
  
          if (httpException != null)
          {
              context.Result = new SimpleErrorResult(context.Request, (HttpStatusCode)httpException.GetHttpCode(), httpException.Message);
              return;
          }
  
          if (exception is RootObjectNotFoundException)
          {
              context.Result = new SimpleErrorResult(context.Request, HttpStatusCode.NotFound, exception.Message);
              return;
          }
  
          if (exception is BadRouteParametersException || exception is RouteObjectPropertyMismatchException)
          {
              context.Result = new SimpleErrorResult(context.Request, HttpStatusCode.BadRequest, exception.Message);
              return;
          }
  
          if (exception is BusinessRuleViolationException)
          {
              context.Result = new SimpleErrorResult(context.Request, (HttpStatusCode)422, exception.Message);
              return;
          }
  
          context.Result = new SimpleErrorResult(context.Request, HttpStatusCode.InternalServerError, exception.Message);
      }
  }
  
  GET api/user/userID/item/itemID
  [Route("{itemID:int}", Name="GetItem")]
  [ResponseType(typeof(ItemDTO))]
  public IHttpActionResult Get(int userID, int itemID)
  {
      if (userID &lt; 0 || itemID &lt; 0)
          throw new BadRouteParametersException("Provided user or item ID is not valid");
      ItemDTO item = _repository.GetItem(itemID);
  
      if (item.UserID != userID)
          throw new RouteObjectPropertyMismatchException("Item userID does not match route userID");
  
      return Ok&lt;ItemDTO&gt;(item);
  }
  </code></pre>
  
  <p>Both of these seem like valid options. Since I am able to return <code>System.Web.Http.Results</code> objects it seems like solution A. is the best one.</p>
  
  <p>But consider when in my <code>_repository</code> my <code>GetItem</code> method is implemented like so</p>
  
  <pre><code>public ItemDTO GetItem(int itemId)
  {
      ItemInfo itemInfo = ItemInfoProvider.GetItemInfo(itemId);
  
      if (itemInfo == null) throw new RootObjectNotFoundException("Item not found");
  
      ItemDTO item = _autoMapper.Map&lt;ItemDTO&gt;(itemInfo);
      return item;
  }
  </code></pre>
  
  <p>Here I can skip calling the autoMapper on null in <code>GetItem</code> and also skip checking for null in the controller.</p>
  
  <h3>Questions</h3>
  
  <ul>
  <li>Which way makes more sense? </li>
  <li>Should I attempt a combination of A &amp; B?</li>
  <li>Should I try to keep my Controllers thin or should this type of validation &amp; processing logic be kept there since I have access to the NotFound() and BadRequest() methods?</li>
  <li>Should I be performing this type of logic somewhere else in the framework pipeline?</li>
  </ul>
  
  <p>I realize my question is more architectural rather than 'how do i use this feature' but again, I haven't found too many explanations of how and when to use these different features.</p>