0

I'm having one of those "I can't believe it's this difficult moments". In .NET Framework I used to sometimes create custom Authorization filters and, if I needed to, I could redirect the user using

context.Result = new RedirectToActionResult("ChooseAuthenticationMethod", "Account");

Now I'm using the latest versions of .NET more (specifically, in this case, .NET 7), I'm trying to get to grips with the Authorization Middleware, which seems like the preferred way to go for a lot of what I would have previously used a custom Authorize attribute for.

I have this code, which works perfectly:

public class TestAuthorizationMiddleware : IAuthorizationMiddlewareResultHandler
{
    private readonly AuthorizationMiddlewareResultHandler defaultHandler = new();

    public async Task HandleAsync(RequestDelegate next, HttpContext context, AuthorizationPolicy policy, PolicyAuthorizationResult authorizeResult)
    {
        if (authorizeResult.Challenged && policy.AuthenticationSchemes.Count == 0)
        {
            context.Response.Redirect("Account/ChooseAuthenticationMethod");
        }
        else
        {
            await defaultHandler.HandleAsync(next, context, policy, authorizeResult);
        }
    }
}

However, I'm trying to figure out how to replace the hard-coded, relative URL ("Account/ChooseAuthenticationMethod") with an absolute one which ASP.NET generates. If I was inside a controller I could just use Url.Action, but I'm not. I've been reading through Stack Overflow questions similar to this for the past hour and can't find anything that seems to do the job. Surely, especially with access to HttpContext and the Request, this should be easy?

Philip Stratford
  • 4,513
  • 4
  • 45
  • 71
  • I don't know which url you want to get, but if you want to get current request's url, I suggest you could try this `context.Request.GetDisplayUrl();`. – Brando Zhang Jun 26 '23 at 09:37
  • I want to get the absolute URL to a particular action on a controller - in this case _Account/ChooseAuthenticationMethod_. – Philip Stratford Jun 26 '23 at 09:43

1 Answers1

0

According to your description, if you want to get the url for a specific action, you could use urlhelper.

This could help you get it.

More details, you could refer to below codes:

public class TestAuthorizationMiddleware : IAuthorizationMiddlewareResultHandler
{
    private readonly IUrlHelper _urlHelper;

    private readonly AuthorizationMiddlewareResultHandler defaultHandler = new();

    public TestAuthorizationMiddleware(IUrlHelper urlHelper) {

        _urlHelper = urlHelper;
    }

    public async Task HandleAsync(RequestDelegate next, HttpContext context, AuthorizationPolicy policy, PolicyAuthorizationResult authorizeResult)
    {
     
        if (authorizeResult.Challenged && policy.AuthenticationSchemes.Count == 0)
        {
            //here you could get the url by using controller name and action name
            _urlHelper.Action("ChooseAuthenticationMethod", "Account");
            context.Response.Redirect("Account/ChooseAuthenticationMethod");
        }
        else
        {
            await defaultHandler.HandleAsync(next, context, policy, authorizeResult);
        }
    }
}
Brando Zhang
  • 22,586
  • 6
  • 37
  • 65
  • I tried this solution, but when I build the application I get an error saying that the service couldn't be resolved. I presume there's some additional configuration required in `Program.cs`? In any case, this solution put me on the right track and I've ended up using the `LinkGenerator` class instead, per [this answer](https://stackoverflow.com/a/59791439/1483190). – Philip Stratford Jul 01 '23 at 16:20