Data Access has been discontinued. Please refer to this page for more information.

Error Handling

This article is relevant to entity models that utilize the deprecated Visual Studio integration of Telerik Data Access. The current documentation of the Data Access framework is available here.

This topic demonstrates error and exception handling in ASP.NET Web API.

By default, when an exception is thrown in an ApiController, a response message is returned to the client with a status code set to 500 (Internal Server Error). Here is an example:

public virtual Car Get( Int32 id )
{
   Car entity = repository.GetBy( c => c.CarID == id );
   if ( entity == null )
   {
       throw new ArgumentNullException( "entity", "Car cannot be found" );
   }
   return entity;
}
Public Overridable Function [Get](ByVal id As Int32) As Car
 Dim entity As Car = repository.GetBy(Function(c) c.CarID = id)
 If entity Is Nothing Then
  Throw New ArgumentNullException("entity", "Car cannot be found")
 End If
 Return entity
End Function

If the car entity is not found in the database, the response message will be:

HTTP/1.1 500 Internal Server Error
Content-Type: application/json; charset=utf-8
Content-Length: 851
{"Message":"An error has occurred.","ExceptionMessage":"Car cannot be found\r\nParameter name: entity","StackTrace":" at....}

There is a specific exception provided by ASP.NET Web API. It is the HttpResponseException. The HttpResponseException returns any HTTP status code that you specify in the constructor. For example, the following get method returns 404 Not Found, if the car entity is not found.

public virtual Car Get( Int32 id )
{
   Car entity = repository.GetBy( c => c.CarID == id );
   if ( entity == null )
   {
       throw new HttpResponseException(HttpStatusCode.NotFound);
   }
   return entity;
}
Public Overridable Function GetById(id As Int32) As Car
    Dim entity As Car = repository.GetBy(Function(c) c.CarID = id )
    If entity Is Nothing Then
        Throw New HttpResponseException(HttpStatusCode.NotFound)
    End If
    Return entity
End Function

Because the HttpResponseException takes an HttpResponseMessage as a parameter, you can also construct the entire response message:

public virtual Car Get( Int32 id )
{
   Car entity = repository.GetBy( c => c.CarID == id );
   if ( entity == null )
   {
       HttpResponseMessage message = new HttpResponseMessage
       {
           StatusCode = HttpStatusCode.NotFound,
           Content = new StringContent( string.Format( "Cannot find car with Id: {0}", id ) ),
           ReasonPhrase = "Car not found"
       };
       throw new HttpResponseException( message );
   }
   return entity;
}
Public Overridable Function GetById(id As Int32) As Car
    Dim entity As Car = repository.GetBy(Function(c) c.CarID = id)
    If entity Is Nothing Then
        Dim message As HttpResponseMessage = New HttpResponseMessage With {
            .StatusCode = HttpStatusCode.NotFound,
            .Content = New StringContent(String.Format("Cannot find car with Id: {0}", id)),
            .ReasonPhrase = "Car not found"}
        Throw New HttpResponseException(message)
    End If
    Return entity
End Function

The code above will have the following response if the car is not found:

HTTP/1.1 404 Car not found
Content-Length: 28
Content-Type: text/plain; charset=utf-8
Cannot find car with Id: 125

Exception Filters

You can customize how the controllers deal with unhandled exceptions by using exception filters. The exception filters are executed when an action method throws any unhandled exception that is not an HttpResponseException. The HttpResponseException is specially designed for returning an HTTP response. This is very useful when you have to write multiple try-catch statements to every ApiController method. By using your own exception filters, you can reduce code duplication. To create an exception filter, you need to derive from the System.Web.Http.Filters.ExceptionFilterAttribute class and override the OnException method. For example:

public class NotImplementedFilterAttribute : ExceptionFilterAttribute
{
   public override void OnException( HttpActionExecutedContext actionExecutedContext )
   {
       if ( actionExecutedContext.Exception is NotImplementedException )
       {
           actionExecutedContext.Response = new HttpResponseMessage( HttpStatusCode.NotImplemented );
       }
   }
}
Public Class NotImplementedFilterAttribute
    Inherits ExceptionFilterAttribute
    Public Overrides Sub OnException(ByVal actionExecutedContext As HttpActionExecutedContext)
        If TypeOf actionExecutedContext.Exception Is NotImplementedException Then
            actionExecutedContext.Response = New HttpResponseMessage(HttpStatusCode.NotImplemented)
        End If
    End Sub
End Class

There are three ways to register exception filters:

  • By action method
  • By controller
  • Globally

To apply the filter to a specific action, simply mark the method with the attribute:

[NotImplementedFilter]
public virtual Car Get( Int32 id )
{
}
<NotImplementedFilter>
Public Overridable Function GetById(id As Int32) As Car
End Function

To apply the filter to all action method in a specific controller, add the attribute to the controller class:

[NotImplementedFilter]
public partial class CarsController : OpenAccessBaseApiController<Car, WebApplication.EntityDiagrams>
{
}
<NotImplementedFilter>
Partial Public Class CarsController
    Inherits OpenAccessBaseApiController(Of Car, Global.WebApplication1.EntityDiagrams)
End Class

To apply the filter to all api controllers (globally), register the attribute in the GlobalConfiguration.Configuration.Filters collection. You can do this in the Application_Start method of Global.asax.

GlobalConfiguration.Configuration.Filters.Add(new NotImplementedFilterAttribute());
GlobalConfiguration.Configuration.Filters.Add(New NotImplementedFilterAttribute())