I work in an MVC project where user roles and permissions for each of the action methods are stored in a database. What I want to achieve is to use the authorization filter function in mvc by overriding AuthorizeAttribute . This way I can register my custom authorization filter worldwide.
Here is what I am trying to do by following this method . I follow this article to handle ajax requests.
protected override bool AuthorizeCore(HttpContextBase httpContext) { //Custom permission checking logic return false;//no permission for all methods-Just for testing } public override void OnAuthorization(AuthorizationContext filterContext) { base.OnAuthorization(filterContext); CheckIfUserIsAuthenticated(filterContext);} } private void CheckIfUserIsAuthenticated(AuthorizationContext filterContext) { // If Result is null, we're OK: the user is authenticated and authorized. if (filterContext.Result == null) return; var httpContext = filterContext.HttpContext; var request = httpContext.Request; var response = httpContext.Response; var user = httpContext.User; // If here, you're getting an HTTP 401 status code. In particular, // filterContext.Result is of HttpUnauthorizedResult type. Check Ajax here. if (request.IsAjaxRequest()) { if (user.Identity.IsAuthenticated == false) response.StatusCode = (int)HttpStatusCode.Unauthorized;//401 else response.StatusCode = (int)HttpStatusCode.Forbidden;//403 response.SuppressFormsAuthenticationRedirect = true; response.End();// This line is causing the problems return; } if (user.Identity.IsAuthenticated) { //Redirect to customerror page } }
The problem is that when I call the method using the ajax message, my custom exception filter throws the error "Server cannot set status after HTTP headers have been sent " If I delete response.End (), I get a 401 response in the ajax error handler method instead of 403. I tried
HttpContext.Current.ApplicationInstance.CompleteRequest()
instead of response.end, but then also I get error 401
Anyway, to avoid this exception?
Update I use this general javascript error handler method to catch all ajax request errors (I need the correct status code for the response):
function ajaxFailed(xhr, textstatus, errorthrown) { debugger; if (textstatus == "error") { if (xhr.status == 401) { window.location = "/Account/Login"; } if (xhr.status == 403) { $("#divoutput").html("you don't have permission."); } } if (xhr.status == 500) { $("#divoutput").append("<br/> internal servererror." + xhr.responseText); } }
Update 2: My current solution: Check the Exception.Message property of the raised exception in my custom exception handler and ignore it if the message: "Server cannot set status after sending HTTP headers . "
I know this is an inefficient method, but I have no other solution yet. Waiting for a good decision :)