The cool thing I find about MVC.Net is that it takes you back to the basics of HTTP instead of worming your way around it. It also shows you how much you take for granted when using webforms, which one could also lead to decide not to use it.
For the last months my college Patrick and myself have been working on and off on a small side project using MVC.net. Using MVC.net has been at times wonderful but also very cumbersome, although that could be a lack of experience speaking. When we started we where using the first beta and one of the things we couldn’t find were guidelines one how to do “stuff”. So we have been flying on blog fuel, articles and common sense. Many obstacles we faced were overcome by embracing the web and using it as it was meant to be used.
One of our latest obstacles we had was getting a proper http 404 statuscode out of our application when a resource couldn´t be found within a controller action. After a lot of tinkering and searching we finally found the answer to our problems via a post by Richard Dingwall. His code probably worked on the technical previews, but it did work for us directly so with a small alteration it also worked for us.
1: public class HandleResourceNotFoundAttribute : HandleErrorAttribute
2: {
3: public override void OnException(ExceptionContext filterContext)
4: {
5: Controller controller = filterContext.Controller as Controller;
6: if (controller == null || filterContext.ExceptionHandled)
7: return;
8:
9: Exception exception = filterContext.Exception;
10: if (exception == null)
11: return;
12:
13: // Action method exceptions will be wrapped in a
14: // TargetInvocationException since they're invoked using
15: // reflection, so we have to unwrap it.
16: if (exception is TargetInvocationException)
17: exception = exception.InnerException;
18:
19: // If this is not a ResourceNotFoundException error, ignore it.
20: if (!(exception is ResourceNotFoundException))
21: return;
22:
23: filterContext.Result = new ViewResult()
24: {
25: TempData = controller.TempData,
26: ViewName = View
27: };
28:
29: filterContext.ExceptionHandled = true;
30: filterContext.HttpContext.Response.Clear();
31: filterContext.HttpContext.Response.StatusCode = 404;
32: }
33: }
I don’t know if this is the best way to handle http errors but I do know this, the customErrors section in the web.config isn’t worth the bytes it takes up. As mentioned in Richard Dingwall’s post, the url path gets changed and worse there is no 404 error shown instead, it uses a 302 and then a 200.
Further digging around shows that .net 3.5 SP1 offers up a new attribute redirectMode:
1: <customErrors mode="RemoteOnly" redirectMode="ResponseRewrite">
2: <error statusCode="404" redirect="404.html" />
3: </customErrors>
The new attribute ensures the url path stays the same unfortunally this attribute only works when you leave out line 2 and let IIS serve it’s default 404 errorpage. Otherwise the html gets served up as a normal 200 OK.
Look out for more MVC.net post soon!!
Hans