Gotcha again! Workarounds for ASP.NET MVC 4 Beta issues

Tags: postcards, asp-net-mvc-4, asp-net-webapi, development, code

The postcardsfromskyrim.net implementation of the postcardApp has been invaluable in getting down to the nuts and bolts of the new ASP.NET MVC 4 Beta and WebAPI. While in the midst of adding authentication and authorization to the app, I had an interesting discovery regarding Attribute Filters and how the WebAPI fits into MVC 4. I’ll go over the basic issue and provide a link to a gist example of how to create a custom authorization attribute to transparently authenticate users in both scenarios presented.

My custom Authorize attribute wasn’t getting called, and I couldn’t defiancefigure out why. Breakpoints wouldn’t break, promises broken, perhaps there were even some tears. Somehow, I was able to persevere. By persevere, I of course mean that I turned to the internet for help.

Thank god for StackOverflow.com! After a bit of searching (perplexingly, searches matching the title almost exactly were missed by Google and SO’s indexes) I found this.

Long story short, AuthorizeAttribute (from which I’d derived my custom attribute) is present in System.Web.Http as well as System.Web.Mvc namespaces. WebAPI controllers - controllers deriving from ApiController and the ilk – must use the System.Web.Http version. System.Web.Mvc controllers will ignore attributes not derived from the appropriate locally-namespaced class. This is because System.Web.Http (a core WebAPI namespace) is completely decoupled from System.Web.Mvc, allowing the two products to work together and still ship separately. I’m thinking of a couple of ways that the decoupling could be retained, yet made less painful for the developer. I guess a lot would depend on whether it would be OK to create a one-way dependency between System.Web.Mvc and System.Web.Http – after all, couldn’t Mvc be considered a subset of Http?

See, the consequence of this separation is that (for now at least) you’ll need to create two custom attributes – one for API controllers, and one for regular controllers.

Code demonstrating how to accomplish this – in a simple, naïve way – can be found below. Simple and naïve are, of course, another way of saying that I provide no warranties for this code, which is yet another way of saying use at your own risk!