Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 8558313
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: June 11, 20262026-06-11T15:46:59+00:00 2026-06-11T15:46:59+00:00

After reviewing an article Exception Handling in ASP.NET Web API I am a bit

  • 0

After reviewing an article Exception Handling in ASP.NET Web API I am a bit confused as to when to throw an exception vs return an error response. I am also left wondering whether it is possible to modify the response when your method returns a domain specific model instead of HttpResponseMessage…

So, to recap here are my questions followed by some code with case #s:

Questions

Questions regarding Case #1

  1. Should I always use HttpResponseMessage instead of a concrete domain model, so that the message can be customized?
  2. Can the message be customized if you are returning concrete domain model?

Questions regarding Case #2,3,4

  1. Should I be throwing an exception or returning error response? If the answer is “it depends”, can you give situations/examples on when to use one vs the other.
  2. What is the difference between throwing HttpResponseException vs Request.CreateErrorResponse ? The output to client seems identical…
  3. Should I always use HttpError to “wrap” response messages in errors (whether the exception is thrown or error response returned)?

Case Samples

// CASE #1
public Customer Get(string id)
{
    var customer = _customerService.GetById(id);
    if (customer == null)
    {
        var notFoundResponse = new HttpResponseMessage(HttpStatusCode.NotFound);
        throw new HttpResponseException(notFoundResponse);
    }
    //var response = Request.CreateResponse(HttpStatusCode.OK, customer);
    //response.Content.Headers.Expires = new DateTimeOffset(DateTime.Now.AddSeconds(300));
    return customer;
}        

// CASE #2
public HttpResponseMessage Get(string id)
{
    var customer = _customerService.GetById(id);
    if (customer == null)
    {
        var notFoundResponse = new HttpResponseMessage(HttpStatusCode.NotFound);
        throw new HttpResponseException(notFoundResponse);
    }
    var response = Request.CreateResponse(HttpStatusCode.OK, customer);
    response.Content.Headers.Expires = new DateTimeOffset(DateTime.Now.AddSeconds(300));
    return response;
}

// CASE #3
public HttpResponseMessage Get(string id)
{
    var customer = _customerService.GetById(id);
    if (customer == null)
    {
        var message = String.Format("customer with id: {0} was not found", id);
        var errorResponse = Request.CreateErrorResponse(HttpStatusCode.NotFound, message);
        throw new HttpResponseException(errorResponse);
    }
    var response = Request.CreateResponse(HttpStatusCode.OK, customer);
    response.Content.Headers.Expires = new DateTimeOffset(DateTime.Now.AddSeconds(300));
    return response;
}

// CASE #4
public HttpResponseMessage Get(string id)
{
    var customer = _customerService.GetById(id);
    if (customer == null)
    {
        var message = String.Format("customer with id: {0} was not found", id);
        var httpError = new HttpError(message);
        return Request.CreateErrorResponse(HttpStatusCode.NotFound, httpError);
    }
    var response = Request.CreateResponse(HttpStatusCode.OK, customer);
    response.Content.Headers.Expires = new DateTimeOffset(DateTime.Now.AddSeconds(300));
    return response;
}

Update

To help further demonstrate cases #2,3,4 the following code snippet highlights several options that “can happen” when a customer is not found…

if (customer == null)
{
    // which of these 4 options is the best strategy for Web API?

    // option 1 (throw)
    var notFoundMessage = new HttpResponseMessage(HttpStatusCode.NotFound);
    throw new HttpResponseException(notFoundMessage);

    // option 2 (throw w/ HttpError)
    var message = String.Format("Customer with id: {0} was not found", id);
    var httpError = new HttpError(message);
    var errorResponse = Request.CreateErrorResponse(HttpStatusCode.NotFound, httpError);
    throw new HttpResponseException(errorResponse);

    // option 3 (return)
    var message = String.Format("Customer with id: {0} was not found", id);
    return Request.CreateErrorResponse(HttpStatusCode.NotFound, message);
    // option 4 (return w/ HttpError)
    var message = String.Format("Customer with id: {0} was not found", id);
    var httpError = new HttpError(message);
    return Request.CreateErrorResponse(HttpStatusCode.NotFound, httpError);
}
  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-06-11T15:47:00+00:00Added an answer on June 11, 2026 at 3:47 pm

    The approach I have taken is to just throw exceptions from the api controller actions and have an exception filter registered that processes the exception and sets an appropriate response on the action execution context.

    The filter exposes a fluent interface that provides a means of registering handlers for specific types of exceptions prior to registering the filter with global configuration.

    The use of this filter enables centralized exception handling instead of spreading it across the controller actions. There are however cases where I will catch exceptions within the controller action and return a specific response if it does not make sense to centralize the handling of that particular exception.

    Example registration of filter:

    GlobalConfiguration.Configuration.Filters.Add(
        new UnhandledExceptionFilterAttribute()
        .Register<KeyNotFoundException>(HttpStatusCode.NotFound)
    
        .Register<SecurityException>(HttpStatusCode.Forbidden)
    
        .Register<SqlException>(
            (exception, request) =>
            {
                var sqlException = exception as SqlException;
    
                if (sqlException.Number > 50000)
                {
                    var response            = request.CreateResponse(HttpStatusCode.BadRequest);
                    response.ReasonPhrase   = sqlException.Message.Replace(Environment.NewLine, String.Empty);
    
                    return response;
                }
                else
                {
                    return request.CreateResponse(HttpStatusCode.InternalServerError);
                }
            }
        )
    );
    

    UnhandledExceptionFilterAttribute class:

    using System;
    using System.Collections.Concurrent;
    using System.Net;
    using System.Net.Http;
    using System.Text;
    using System.Web.Http.Filters;
    
    namespace Sample
    {
        /// <summary>
        /// Represents the an attribute that provides a filter for unhandled exceptions.
        /// </summary>
        public class UnhandledExceptionFilterAttribute : ExceptionFilterAttribute
        {
            #region UnhandledExceptionFilterAttribute()
            /// <summary>
            /// Initializes a new instance of the <see cref="UnhandledExceptionFilterAttribute"/> class.
            /// </summary>
            public UnhandledExceptionFilterAttribute() : base()
            {
    
            }
            #endregion
    
            #region DefaultHandler
            /// <summary>
            /// Gets a delegate method that returns an <see cref="HttpResponseMessage"/> 
            /// that describes the supplied exception.
            /// </summary>
            /// <value>
            /// A <see cref="Func{Exception, HttpRequestMessage, HttpResponseMessage}"/> delegate method that returns 
            /// an <see cref="HttpResponseMessage"/> that describes the supplied exception.
            /// </value>
            private static Func<Exception, HttpRequestMessage, HttpResponseMessage> DefaultHandler = (exception, request) =>
            {
                if(exception == null)
                {
                    return null;
                }
    
                var response            = request.CreateResponse<string>(
                    HttpStatusCode.InternalServerError, GetContentOf(exception)
                );
                response.ReasonPhrase   = exception.Message.Replace(Environment.NewLine, String.Empty);
    
                return response;
            };
            #endregion
    
            #region GetContentOf
            /// <summary>
            /// Gets a delegate method that extracts information from the specified exception.
            /// </summary>
            /// <value>
            /// A <see cref="Func{Exception, String}"/> delegate method that extracts information 
            /// from the specified exception.
            /// </value>
            private static Func<Exception, string> GetContentOf = (exception) =>
            {
                if (exception == null)
                {
                    return String.Empty;
                }
    
                var result  = new StringBuilder();
    
                result.AppendLine(exception.Message);
                result.AppendLine();
    
                Exception innerException = exception.InnerException;
                while (innerException != null)
                {
                    result.AppendLine(innerException.Message);
                    result.AppendLine();
                    innerException = innerException.InnerException;
                }
    
                #if DEBUG
                result.AppendLine(exception.StackTrace);
                #endif
    
                return result.ToString();
            };
            #endregion
    
            #region Handlers
            /// <summary>
            /// Gets the exception handlers registered with this filter.
            /// </summary>
            /// <value>
            /// A <see cref="ConcurrentDictionary{Type, Tuple}"/> collection that contains 
            /// the exception handlers registered with this filter.
            /// </value>
            protected ConcurrentDictionary<Type, Tuple<HttpStatusCode?, Func<Exception, HttpRequestMessage, HttpResponseMessage>>> Handlers
            {
                get
                {
                    return _filterHandlers;
                }
            }
            private readonly ConcurrentDictionary<Type, Tuple<HttpStatusCode?, Func<Exception, HttpRequestMessage, HttpResponseMessage>>> _filterHandlers = new ConcurrentDictionary<Type, Tuple<HttpStatusCode?, Func<Exception, HttpRequestMessage, HttpResponseMessage>>>();
            #endregion
    
            #region OnException(HttpActionExecutedContext actionExecutedContext)
            /// <summary>
            /// Raises the exception event.
            /// </summary>
            /// <param name="actionExecutedContext">The context for the action.</param>
            public override void OnException(HttpActionExecutedContext actionExecutedContext)
            {
                if(actionExecutedContext == null || actionExecutedContext.Exception == null)
                {
                    return;
                }
    
                var type    = actionExecutedContext.Exception.GetType();
    
                Tuple<HttpStatusCode?, Func<Exception, HttpRequestMessage, HttpResponseMessage>> registration = null;
    
                if (this.Handlers.TryGetValue(type, out registration))
                {
                    var statusCode  = registration.Item1;
                    var handler     = registration.Item2;
    
                    var response    = handler(
                        actionExecutedContext.Exception.GetBaseException(), 
                        actionExecutedContext.Request
                    );
    
                    // Use registered status code if available
                    if (statusCode.HasValue)
                    {
                        response.StatusCode = statusCode.Value;
                    }
    
                    actionExecutedContext.Response  = response;
                }
                else
                {
                    // If no exception handler registered for the exception type, fallback to default handler
                    actionExecutedContext.Response  = DefaultHandler(
                        actionExecutedContext.Exception.GetBaseException(), actionExecutedContext.Request
                    );
                }
            }
            #endregion
    
            #region Register<TException>(HttpStatusCode statusCode)
            /// <summary>
            /// Registers an exception handler that returns the specified status code for exceptions of type <typeparamref name="TException"/>.
            /// </summary>
            /// <typeparam name="TException">The type of exception to register a handler for.</typeparam>
            /// <param name="statusCode">The HTTP status code to return for exceptions of type <typeparamref name="TException"/>.</param>
            /// <returns>
            /// This <see cref="UnhandledExceptionFilterAttribute"/> after the exception handler has been added.
            /// </returns>
            public UnhandledExceptionFilterAttribute Register<TException>(HttpStatusCode statusCode) 
                where TException : Exception
            {
    
                var type    = typeof(TException);
                var item    = new Tuple<HttpStatusCode?, Func<Exception, HttpRequestMessage, HttpResponseMessage>>(
                    statusCode, DefaultHandler
                );
    
                if (!this.Handlers.TryAdd(type, item))
                {
                    Tuple<HttpStatusCode?, Func<Exception, HttpRequestMessage, HttpResponseMessage>> oldItem = null;
    
                    if (this.Handlers.TryRemove(type, out oldItem))
                    {
                        this.Handlers.TryAdd(type, item);
                    }
                }
    
                return this;
            }
            #endregion
    
            #region Register<TException>(Func<Exception, HttpRequestMessage, HttpResponseMessage> handler)
            /// <summary>
            /// Registers the specified exception <paramref name="handler"/> for exceptions of type <typeparamref name="TException"/>.
            /// </summary>
            /// <typeparam name="TException">The type of exception to register the <paramref name="handler"/> for.</typeparam>
            /// <param name="handler">The exception handler responsible for exceptions of type <typeparamref name="TException"/>.</param>
            /// <returns>
            /// This <see cref="UnhandledExceptionFilterAttribute"/> after the exception <paramref name="handler"/> 
            /// has been added.
            /// </returns>
            /// <exception cref="ArgumentNullException">The <paramref name="handler"/> is <see langword="null"/>.</exception>
            public UnhandledExceptionFilterAttribute Register<TException>(Func<Exception, HttpRequestMessage, HttpResponseMessage> handler) 
                where TException : Exception
            {
                if(handler == null)
                {
                  throw new ArgumentNullException("handler");
                }
    
                var type    = typeof(TException);
                var item    = new Tuple<HttpStatusCode?, Func<Exception, HttpRequestMessage, HttpResponseMessage>>(
                    null, handler
                );
    
                if (!this.Handlers.TryAdd(type, item))
                {
                    Tuple<HttpStatusCode?, Func<Exception, HttpRequestMessage, HttpResponseMessage>> oldItem = null;
    
                    if (this.Handlers.TryRemove(type, out oldItem))
                    {
                        this.Handlers.TryAdd(type, item);
                    }
                }
    
                return this;
            }
            #endregion
    
            #region Unregister<TException>()
            /// <summary>
            /// Unregisters the exception handler for exceptions of type <typeparamref name="TException"/>.
            /// </summary>
            /// <typeparam name="TException">The type of exception to unregister handlers for.</typeparam>
            /// <returns>
            /// This <see cref="UnhandledExceptionFilterAttribute"/> after the exception handler 
            /// for exceptions of type <typeparamref name="TException"/> has been removed.
            /// </returns>
            public UnhandledExceptionFilterAttribute Unregister<TException>()
                where TException : Exception
            {
                Tuple<HttpStatusCode?, Func<Exception, HttpRequestMessage, HttpResponseMessage>> item = null;
    
                this.Handlers.TryRemove(typeof(TException), out item);
    
                return this;
            }
            #endregion
        }
    }
    

    Source code can also be found here.

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

I have a Web Application (ASP.NET application developed with C# and .NET Framework 3.5)
We just started a new ASP.Net project that uses web services to serialize some
After reviewing A LOT of questions and Internet data, I've solved a problem of
I am having some issues with logging. After reviewing JBoss Seam source code, I
After a long search I'm still confused about it although I found some related
After reviewing this blog by Kirill Osenkov (How to create a generic List of
I am getting started with OO PHP, and after reviewing a variety of classes
in my system i should send notification mail after reviewing a list i am
OK, after reviewing some code with PMD and FindBugs code analyzers, i was able
I'm new to RequestFactory but with generous help of Thomas Broyer and after reviewing

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.