In my last post on HTTP/POX basics, Dave Bettin asked a good question in the comments:
Will you guys have a good story around a programming model for associating HTTP status codes with CLR exceptions? Or are we stuck with the existing fault model?
The short answer is "of course we'll have a good story around programming HTTP status exceptions!" We haven't landed on whether that model will be based on exceptions or not.
Exceptions are a nice control flow abstraction for doing non-local jumps out of a method body (which is sometimes what you want with status codes, but not always). The downside is that they're relatively expensive from a performance perspective -- hence the general guidance of "don't use exceptions for non-exceptional circumstances".
Personally, I don't think that any of the HTTP status codes are truly exceptional (with the possible exception of HTTP 500, which means the server barfed). Everything else (including Endpoint Not Found[1] is pretty de regeur for a server on the Internet.
At small/medium scales, you can get away with making the making a performance tradeoff that optimizes the mainline success path at the expense of the "error path" because you can assume that most people will play by the rules. You can't make that assumption on the Internet -- you can't assume that everyone's going to get the URL right, for example. As such, you'd really like to get mainline performance out of your negative paths if at all possible -- if you don't, you've got what amounts to a potential DOS vector.
So instead of exceptions, we're looking at a slightly different model based around the notion of "setting status" on the current response. We haven't closed on the final form for this yet, but the current thinking is something like the following:
TransferContextThingy.SetStatusOk();
TransferContextThingy.SetStatusCreated( Uri location );
TransferContextThingy.SetStatusRedirected( RedirectType t, Uri u);
TransferContextThingy.SetStatusNotFound();
TransferContextThingt.SetStatus( System.Net.HttpStatusCode status, string description );
...
Obviously, this is not a complete set and TransferContextThingy is a temporary name but you get the picture.
Here's how this might get used in practice:
public Customer GetCustomer(int id)
{
Console.WriteLine("Received GET for " + TransferContextThingy.Request.RequestUri);
Customer customer = null;
customerList.TryGetValue(id, out customer);
if (customer == null)
{
TransferContextThingy.Response.SetStatusNotFound();
}
return customer;
}
How does that look?
[1] Yes, I know we have an EndpointNotFound exception in WCF already. However that's really only thrown on the client, not the server.
