开发者

Best way to abort/cancel action and response from ActionFilter

开发者 https://www.devze.com 2023-02-14 12:27 出处:网络
Best way to abort/cancel action from ActionFilter I\'ve got this Acti开发者_JS百科onFilter, and it\'s suppose to end the connection immediately and return a 401 Unauthroized:

Best way to abort/cancel action from ActionFilter

I've got this Acti开发者_JS百科onFilter, and it's suppose to end the connection immediately and return a 401 Unauthroized:

public class SignInRequired : ActionFilterAttribute 
{
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        // User is verified, continue executing action

        if (Acme.Web.CurrentUser != null)
        {
            return;
        }

        // End response with 401 Unauthorized

        var response = HttpContext.Current.Response;
        response.StatusCode = (int)HttpStatusCode.Unauthorized;
        response.End();

        // Prevent the action from actually being executed

        filterContext.Result = new EmptyResult();
    }
}

I learned how you can cancel the action from executing by setting 'context.Result = new EmptyResult()` here, but I'm not sure if this is the best way to flush the response and close the connection.


Setting the response will mean the action doesn't get called.

public override void OnActionExecuting(HttpActionContext actionContext)    
{ 
    actionContext.Response = new HttpResponseMessage(HttpStatusCode.Unauthorized);
}

As other answers have said, though, authentication should be done with an AuthorizeAttribute (Docs for Web.API or for MVC).


On .net core 2.2, 3.0 and 3.1 and .net 5 the below example works fine

public override void OnActionExecuting(ActionExecutingContext context)
{
  context.Result = new UnauthorizedObjectResult("user is unauthorized");
}


The answer that @OdeyinkaOlubunmi is correct for Web API or specifically System.Web.Http.Filters.ActionFilterAttribute but it can't be used for System.Web.Mvc.ActionFilterAttribute. AuthorizeAttribute and overriding AuthorizeCore is a good way to go but if you use @Vadim's example for a GlobalFilter you will end up with the following error in a standard configuration:

HTTP Error 404.15 - Not Found The request filtering module is configured to deny a request where the query string is too long.

This is because the default /Login?ReturnUrl= will keep appending new values until the query string causes an exception.

The way I have solved it for MVC is like this:

public class DebugActionFilter : System.Web.Mvc.ActionFilterAttribute
{
  public override void OnActionExecuting(System.Web.Mvc.ActionExecutingContext actionContext)
  {
    actionContext.Result = new HttpStatusCodeResult(HttpStatusCode.Unauthorized);
    return;
  }
}


You can set the result of filterContext for the Exception page like this:

filterContext.Result = new RedirectResult("~/Error/Unauthorized");

See more details here on section Canceling Filter Execution


You probably want to make it an AuthorizeAttribute. That will set the result to be an UnAuthorizedResult automatically, plus it has the benefit of being run before any other filters. Alternatively you can set the Result to be a new HttpUnauthorizedResult

public class SignInRequiredAttribute : AuthorizeAttribute
{
    protected override bool AuthorizeCore(HttpContextBase httpContext)
    {
        return !Acme.Web.CurrentUser != null;
    }
}


using .net core 2.1 the solutions above did not work for me , so i tried this and it worked :-

 context.HttpContext.Response.StatusCode = 401;
 return;

if there is better solutions for .net core 2.1 i am open for suggestions

0

精彩评论

暂无评论...
验证码 换一张
取 消