ASP.NET MVC 4 Beta issues workarounds
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.