ASP.NET MVC, throw HttpException vs return HttpStatusCodeResult?

I am developing a RESTful service and I want to return 400 for all unsupported URLs.

My question is when should I choose method 1 over method 2 and vice-versa..

//method 1
public ActionResult Index()
{
    //The url is unsupported
    throw new HttpException(400, "Bad Request");
}

This one seems to be better?

//method 2
public ActionResult Index()
{
    //The url is unsupported
    return new HttpStatusCodeResult(HttpStatusCode.BadRequest, "Bad Request");
}

Solution 1:

The second seems better as it doesn't involve exception throwing which comes at a micro-cost compared to the first example.

Solution 2:

Being in a DevOps team, we are all in the mind-set where throwing more hardware at something to get a slightly better result is always a good cause. So I'm intentionally ignoring the micro-cost of firing a .NET exception.

If you're leveraging a telemetry framework like ApplicationInsights then just returning the status code gives you nothing more than a "failed request". It doesn't give you any useful information that allows you to either compile or get any information on the "why" of the failed request.

Telemetry platforms expect and want you to throw, because error telemetry is usually around .NET exceptions, so if you're not throwing you're creating a problem for operations.

I actually landed here, because I'm in the process of writing a Roslyn analyser and CodeFix for a project where folks love to write try{} catch { return BadRequest("put_the_reason_here"); } and neither DevOps or the Dev teams see nothing useful in the system telemetry in ApplicationInsights.

Solution 3:

In my view you need to consider first if a request is made to the unsupported URLs. Then do you think of it is an exceptional situation or you expect that to happen? If you think of it as an exceptional situation then create and throw an exception (option 1). If you are expecting that you will receive many requests on the unsupported URL then treat it as a function of your application and use method 2.

That's said you will need to think about your clients' again if you are expecting too many requests on the unsupported URLs. In general I would prefer to throw an exception as I don't expect to receive too many requests on the unsupported URLs, and if it does happen then I would like to log it as an exception and investigate the reason.

Solution 4:

Although this question is a bit old I figured I'd give my input since I came across this.

Errors are values. This goes for an HttpException (when unthrown) as well as an HttpStatusCodeResult. Thrown exceptions, however, create new code paths that are hidden away from your coworkers that may be one execution context higher up than yours and have to be given documentation that these code paths will be passed to them without notice. Values, however, tell you everything you need to know through their type. You can use their type in the expected execution path to tell whether an error has occured as well as find associated information with that error and log it.

I sometimes use (lightly extended) Exception's without throwing them to the next execution context to extract the useful debug information that David Rodriguez mentioned. There's never an excuse to be handing thrown exceptions to execution contexts above you that aren't actually exceptional, and this only really applies to things that are actually outside of your code's ability to handle (StackOverflowException, other fatal system exceptions, etc).

In a networked application, such as whatever MVC service you're running, the performance penalty from throwing exceptions is meaningless. The semantics and effects on maintainability, are not.

Network errors are values, and you should handle them like so.