Search code examples
asp.net-mvciisasp.net-coreroutesmiddleware

.NETCore Middleware Redirect Removing Path IIS Sub Application


I have a middleware class that reads the user's cookies and validates them, then redirects to a login URL if they are invalid or missing. The URL that the user is redirected to contains a 'back' parameter. This middleware works perfectly fine on a static-file SPA and when the application is not a nested application within IIS.

My Question, this does not work when using MVC controllers and Views, before the user is redirected to the login page somehow the path (which points to the nested IIS site) is stripped and the back URL does not contain the URL path. Any ideas?

What happens

Go to -> http://test.com/mysite

Redirects to -> http://login.com?back=http://test.com

What should happen

Go to -> http://test.com/mysite

Redirects to -> http://login.com?back=http://test.com/mysite

public class MyMiddleware
  {

    private readonly RequestDelegate _next;

    private readonly ILogger _logger;

    private readonly IOptions<MyMiddlewareOptions> _options;


    public MyMiddleware(RequestDelegate next, IOptions<MyMiddlewareOptions> options, ILoggerFactory logger)
    {
      _next    = next;
      _options = options;
      _logger = logger.CreateLogger("My Middleware");
    }


      public async Task Invoke(HttpContext context)
    {
      var middlewareCookieValidator = context.RequestServices.GetService<IMiddlewareCookieValidator>();

      await new CookieRequestCultureProvider().DetermineProviderCultureResult(context);

      if (!_options.Value.Bypass && !Path.HasExtension(context.Request.Path.Value))
      {
        try
        {
            if (wslCookieValidator.HasCreatedCookies(context) || await middlewareCookieValidator.ValidateCookiesAsync())
            {
              context.Response.OnStarting(async () => await middlewareCookieValidator.GenerateAndApplyCookiesToResponse(context));

              await _next(context);
            }
            else
            {
              var location = new Uri($"{context.Request.Scheme}://{context.Request.Host}{context.Request.Path}{context.Request.QueryString}");

              context.Response.Redirect($"{_options.Value.Url}?back={location}");
            }

        }
        catch (Exception exception)
        {
          throw new Exception($"RequestDelegate '_next' = {_next}.  {exception.Message}");
        }
      }
      else
      {
        await _next(context);
      }
    }

  }

}

Solution

  • @Lex Li

    Thank you for your answer, turns out due to IIS running with sub-applications.

    I needed the following for it to work.

    var location = new Uri($"{context.Request.Scheme}://{context.Request.Host}{context.Request.PathBase}{context.Request.Path}{context.Request.QueryString}");