.NET

ASP.NET MVC 4 Beta issues workarounds

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!

public class AuthenticateAndAuthorizeAcsMvcAttribute : System.Web.Mvc.AuthorizeAttribute
    {
        public override void OnAuthorization(System.Web.Mvc.AuthorizationContext filterContext)
        {
            var principal = filterContext.HttpContext.User;
            if (principal == null || !principal.Identity.IsAuthenticated)
            {
                filterContext.Result = new ViewResult()
                {
                    ViewName = "AcsLogin",
                    ViewData = filterContext.Controller.ViewData,
                    TempData = filterContext.Controller.TempData
                };
                return;
            }
            base.OnAuthorization(filterContext);
        }
    }
    public class AuthenticateAndAuthorizeAcsApiAttribute : System.Web.Http.AuthorizeAttribute
    {
        public override void OnAuthorization(System.Web.Http.Controllers.HttpActionContext actionContext)
        {
            var principal = actionContext.Request.GetUserPrincipal();
            if (principal == null || !principal.Identity.IsAuthenticated)
            {
                actionContext.Response = new HttpResponseMessage(HttpStatusCode.Unauthorized);
                return;
            }
            actionContext.Response = new HttpResponseMessage(HttpStatusCode.OK);
        }
 
    }

References: Gotcha again! Workarounds for ASP.NET MVC 4 Beta issues from our NCG partner Josh Elster at the Liquid Electron blog.

Related Articles

Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

0 Comments
Inline Feedbacks
View all comments
Back to top button