aspnet / Mvc

[Archived] ASP.NET Core MVC is a model view controller framework for building dynamic web sites with clean separation of concerns, including the merged MVC, Web API, and Web Pages w/ Razor. Project moved to https://github.com/aspnet/AspNetCore
Apache License 2.0
5.61k stars 2.14k forks source link

Providing a base path from "outside" does no longer work (migration from 1.1.x to 2.1.x) #8398

Closed drauch closed 6 years ago

drauch commented 6 years ago

In our web tests we host a Kestrel server for our web assembly, in 1.x we did it in the following way:

var webHost = new WebHostBuilder()
  .UseContentRoot(webClientProjectDirectory)
  .UseEnvironment("WebTesting")
  .UseSetting(WebHostDefaults.ApplicationKey, applicationAssemblyName)
  .UseStartup<TStartup>()
  .UseUrls(url)
  .UseKestrel()
  .Build();

Moving to 2.x we used the new program pattern instead:

var host = WebHost.CreateDefaultBuilder()
  .UseContentRoot(webClientProjectDirectory)
  .UseEnvironment("WebTesting")
  .UseStartup<TStartup>()
  .UseUrls(url)
  .Build();

However, now we run into the following problem:

System.InvalidOperationException : A path base can only be configured using IApplicationBuilder.UsePathBase().

What's the correct way to do this?

drauch commented 6 years ago

It looks like the problem is with UseUrls() if the URL contains a base path. If we remove the base path it works. However, we want to apply such a base path FROM OUTSIDE - how to do so? (please don't tell me to call UseBasePath inside Startup.Configure, that's not from outside)

pranavkm commented 6 years ago

@JunTaoLuo is this the same issue as https://github.com/aspnet/Home/issues/3495?

JunTaoLuo commented 6 years ago

Though this is the same error, I think the scenario is different.

@drauch what do you mean by "from outside"? Is the requirement here to set the base path based on an environment variable? If so, I think it would be easiest to set two separate environment variables, one for the url and one for the path base and call UseUrls and UseBasePath on the two environment variables. While we have an explicit configuration key for urls: https://github.com/aspnet/Hosting/blob/master/src/Microsoft.AspNetCore.Hosting.Abstractions/WebHostDefaults.cs#L17, we don't have one for base path: https://github.com/aspnet/Hosting/issues/1120. You'll need to set and read your own environment variable with a custom name.

drauch commented 6 years ago

@JunTaoLuo : "from outside" = "without touching the Startup class or its Configure method". It should be set from the WebHostBuilder.

JunTaoLuo commented 6 years ago

Unfortunately we don't have a first class way of doing this on the WebHostBuilder. The issue I linked https://github.com/aspnet/Hosting/issues/1120 is the enhancement that would address this. Closing as dupe cc @Tratcher @davidfowl.

@drauch The closest thing I can think of to what you want to do is to create a StartupFilter that adds the call to UsePathBase:

    public class PathBaseStartupFilter : IStartupFilter
    {
        public Action<IApplicationBuilder> Configure(Action<IApplicationBuilder> next)
        {
            return builder =>
            {
                builder.UsePathBase(Environment.GetEnvironmentVariable("CUSTOM_PATH_BASE"));
                next(builder);
            };
        }
    }

    public class Program
    {
        public static void Main(string[] args)
        {
            CreateWebHostBuilder(args).Build().Run();
        }

        public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
            WebHost.CreateDefaultBuilder(args)
                .ConfigureServices(services =>
                {
                    services.AddTransient<IStartupFilter, PathBaseStartupFilter>();
                })
                .UseStartup<Startup>();
    }
drauch commented 6 years ago

@JunTaoLuo : Thank you for the workaround! Hope that https://github.com/aspnet/Hosting/issues/1120 will be implemented!