-
Notifications
You must be signed in to change notification settings - Fork 10.3k
UsePathBase being ignored #38448
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
@reinux, is that github repo public? I can't access it. |
LOL sorry about that. It's public now. |
Repro:
I think the issue is the implicit call to UseRouting that WebApplication added at the start of the pipeline (@davidfowl @halter73). Routing happens before UsePathBase so that would explain why UsePathBase doesn't apply. Adding UseRouting explicitly should fix it.
If that fixes it then we should add an analyzer to warn about this case. |
I think an analyzer is a good idea here. FWIW, you should be able to just add |
It seems to accept both
|
Something we can document for now and then we can do what we did for the other middleware that rewrites the path. |
In my case, the controllers just worked in this order var app = builder.Build();
app.UsePathBase("/api");
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
});
app.MapControllers();
app.Run();
|
@penihel you dont need the UseEndpoints call |
Nice milestone ;) waiting for .net 7 |
app.UseRouting(); does not seem to work for the new minimal api |
I hit on this today, I was very confused as to what was happening even when inspecting the I have an application that is behind a YARP proxy and my swagger UI paths were working, but the API calls into the controllers were not. Adding the explicit call to |
I'm seconding the issue, I have it too. Also confirming that the .UseRouting() workaround helps sorting things out. |
Just wanted to point out that using `UseRouting` in the correct order solves the problem, at least for us.
Edit: Also just realized you noted that :D
|
I hit this today and I couldn't find it documented anywhere yet. Is there an issue tracking this for the docs? I tried looking at the Minimal APIs page and any page referencing |
I submitted a docs PR at dotnet/AspNetCore.Docs#25769 to add notes mentioning the need to call |
I've hit this issue yesterday and the proposed workaround is not working for me. This was a .net 3.1 mvc that was migrated to use the new web app builder but I retained the StartUp class. Here's the code from Program where the builder and StartUp are created: var builder = WebApplication.CreateBuilder(new WebApplicationOptions
{
ApplicationName = typeof(Program).Assembly.FullName,
Args = args,
EnvironmentName = environment,
});
builder.Configuration.AddConfiguration(config);
builder.Host.UseSerilog();
builder.WebHost.UseUrls("http://*:58471");
builder.WebHost.ConfigureKestrel(serverOptions =>
{
serverOptions.Limits.MinRequestBodyDataRate = new MinDataRate(
bytesPerSecond: 80, gracePeriod: TimeSpan.FromSeconds(20));
serverOptions.Limits.MinResponseDataRate = new MinDataRate(
bytesPerSecond: 80, gracePeriod: TimeSpan.FromSeconds(20));
});
var startup = new Startup(config);
startup.ConfigureServices(builder.Services);
var app = builder.Build();
startup.Configure(app, environment); This is the method in StartUp that is called by Program to initialize the app after it is created: public void Configure(IApplicationBuilder app, string environment)
{
Dapper.DefaultTypeMap.MatchNamesWithUnderscores = true;
// The request path has to be set if the application is running in a
// container and being exposed on a path other than /. In k8s we set
// SiteConfig__PathBase to /sms in most projects.
if (!string.IsNullOrEmpty(Cfg.SiteConfig.PathBase))
{
Log.Information("Setting PathBase to {PathBase}.", Cfg.SiteConfig.PathBase);
app.UsePathBase(Cfg.SiteConfig.PathBase);
app.UseStaticFiles(new StaticFileOptions
{
RequestPath = Cfg.SiteConfig.PathBase
});
app.Use((context, next) =>
{
if (context.Request.Path.StartsWithSegments(Cfg.SiteConfig.PathBase, out var remainder))
{
context.Request.Path = remainder;
context.Request.PathBase = new PathString(Cfg.SiteConfig.PathBase);
}
return next();
});
}
else
{
app.UseStaticFiles();
}
if (environment == "Development")
{
app.UseDeveloperExceptionPage();
// If you want saving views to not require a recompile,
// see https://kmatyaszek.github.io/2020/02/29/how-to-enable-browser-link-in-aspnetcore3-app.html
app.UseBrowserLink();
}
else
{
app.UseExceptionHandler("/Error");
}
app.UseHttpsRedirection();
app.UseRouting();
app.UseCookiePolicy();
app.UseSerilogRequestLogging();
// Must call UseAuthentication between UserRouting and UseEndpoints or will throw an error page
app.UseAuthentication();
app.UseAuthorization();
if (Cfg.SiteConfig.EnableHangfire)
{
Log.Information("Setting up Hangfire dashboard.");
app.UseHangfireDashboard("/hangfire", new DashboardOptions
{
Authorization = new[] { new Extensions.HangfireAuthorizationFilter() },
AppPath = environment == "Development" ? "/" : "/sms"
});
app.UseHangfireDashboard();
if (!string.IsNullOrEmpty(Cfg.SiteConfig.RefreshTargetsCron))
RecurringJob.AddOrUpdate<HangfireHelper>("refresh_targets",
h => h.RefreshTargets(), Cfg.SiteConfig.RefreshTargetsCron);
else
RecurringJob.RemoveIfExists("refresh_targets");
}
app.UseEndpoints(endpoints =>
{
endpoints.MapReverseProxy();
endpoints.MapHub<InboundCallHub>("/hubs/callHub");
endpoints.MapHub<InboundCallHub>("/hubs/inboundCallHub");
endpoints.MapHub<MonitoringHub>("/hubs/monitoringHub");
endpoints.MapHub<OutboundCallHub>($"/hubs/outboundCallHub");
endpoints.MapControllerRoute("default", "{controller=Account}/{action=Index}/{id?}");
endpoints.MapControllerRoute("home", "{controller=Home}/{action=Index}/{id?}");
});
app.UseMvc(routes => {
routes.MapRoute(
name: "Default",
template: "{controller}/{action}/{id?}",
defaults: new { controller = "Home", action = "Index" }
);
routes.MapRoute(
name: "Error404",
template: "{*url}",
defaults: new { controller = "Error", action = "Handle404" }
);
});
}
} |
Here's the log entry from the container showing that it is receiving the configuration value for PathBase:
When I try to navigate to /sms the app redirects to a path off the root and loses the /sms prefix: /Account/Login?ReturnUrl=%2F Where it should have redirected to /sms/Account/Login?ReturnUrl=%2F What I am trying to deal with is an app that is hosted in a container which is exposed via an ingress in a k8s cluster under a path other than root (/sms in this case). This code around UsePathBase() used to work under .NET 3.1 when we validated our plans for going to k8s. We are now trying to actually migrate under .NET 6 and the new web builder and can't get this to work. if I just run this locally with the PathBase configuration it all seems to work ok. But in the k8s cluster it falls back into redirecting to the root of the website. Should we go back to using the older style builder from .NET 5 or .NET 3.1? I've already burned up a whole day with this and would like to know what would be the better course of action here. |
I also had to simplify how I was handling static files and this is how it looks like now: if (!string.IsNullOrEmpty(Cfg.SiteConfig.PathBase))
{
Log.Information("Setting PathBase to {PathBase}.", Cfg.SiteConfig.PathBase);
app.UsePathBase(Cfg.SiteConfig.PathBase);
}
app.UseStaticFiles();
app.UseHttpsRedirection();
app.UseRouting(); Applied this fix to three containers and all is working and happy again. |
Describe the bug
UsePathBase seems to get ignored. I'm not sure what the condition is. In my other project, it works with the Swagger endpoints, but not with the controllers. In this repro, it works with neither. In both cases, it's the first call I make after I build the app.
To Reproduce
app.UsePathBase()
immediately aftervar app = builder.Build()
https://github.com/reinux/UsePathBaseTest
Exceptions (if any)
Further technical details
dotnet --info
:dotnet --info Output
The text was updated successfully, but these errors were encountered: