Open YogiBear52 opened 5 years ago
Can you share a runnable sample that reproduces the problem? That way we get an exact repro and can investigate in depth.
It might be worth looking at this issue again but I don't know if we'll have time to fix it. The workaround is to do something like this:
public class Program
{
public static void Main(string[] args)
{
CreateWebHostBuilder(args).Build().Run();
}
public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>()
// Ignore the startup class assembly as the "entry point" and instead point it to this app
.UseSetting(WebHostDefaults.ApplicationKey, typeof(Program).GetTypeInfo().Assembly.FullName);
}
We've had this come up a number of times and it might make sense to handle this somehow.
https://github.com/aspnet/Hosting/issues?q=is%3Aissue+ApplicationKey+is%3Aclosed
We could clean this up a bit by adding a UseEntryPoint
method that sets the entry point assembly. Another thing we should consider doing is splitting application name and entrypoint (but this would be a breaking change for people that originally worked around this issue via the above). The application entry point is used by MVC today to figure out where controllers are so it doubles as both the "application name" and the "entrypoint" assembly.
Seems reasonable. Any reason we can't default the entry point to the assembly containing the Startup type? Also the name UseEntryPoint
is a bit overloaded (especially with some of the generic host stuff I've talked about with @glennc). Perhaps UsePrimaryAssembly
or UseApplicationAssembly
?
Also, does MVC have options to add/change the assembly that's scanned?
Any reason we can't default the entry point to the assembly containing the Startup type?
We do and that's the bug. The Startup class is in the class library and controllers are in the main application.
Also the name UseEntryPoint is a bit overloaded (especially with some of the generic host stuff I've talked about with @glennc). Perhaps UsePrimaryAssembly or UseApplicationAssembly?
Yea, lets bikeshed the name. @khellang Proposed a PR a while back with similar functionality. We could even decide that this doesn't belong in hosting.
Also, does MVC have options to add/change the assembly that's scanned?
Not the primary assembly. This happens very early (during DI setup) https://github.com/aspnet/AspNetCore/blob/258d34e3828a1870a16d13cd3c62d1b7a65acc4a/src/Mvc/Mvc.Core/src/DependencyInjection/MvcCoreServiceCollectionExtensions.cs#L81-L88
We do and that's the bug.
Gotcha, just re-read the issue.
What makes it super confusing is that it's called ApplicationName
with no reference to assemblies.
I remember a couple of issues where people got tripped up because things stopped working by just changing the application name. Giving an instance of your app a pet name is a perfectly valid scenario, and so is changing the "entry point assembly" (not to be confused with an IL entrypoint). I think both should be allowed.
It's also kinda ironic that we're on the third breaking iteration of the IHostingEnvironment/IWebHostEnvironment and haven't used the opportunity to correct the naming mistake 😅
And, for reference: https://github.com/aspnet/Hosting/pull/1180. It's 3.0 season - time to break someone! 😉
It's also kinda ironic that we're on the third breaking iteration of the IHostingEnvironment/IWebHostEnvironment and haven't used the opportunity to correct the naming mistake 😅
We're not though. We haven't broken anything until now. We added new interfaces and it's time to add the new property while we still can (during 3.0).
I'm confused why dotnet/aspnetcore#14183 was closed as "no work to do" - can anyone shed light on that decision? This is the closest issue I can find.
I spent some time digging through the code in this repo trying to figure out why my ASPNETCORE 3.x app was not respecting the APPLICATION_NAME
set up in my app configuration and learned that using the DefaultWebHostBuilder
and configuring a Startup
class injects an additional configuration provider (last so that it overrides my app configuration) and forces the app name to the AssemblyName of the DLL containing the Startup
class.
I'm curious why it does not simply respect the APPLICATION_NAME
as configured by IConfigurationBuilder
instance returned from the ConfigureAppConfiguration
method?
I'm using a Generic Host and then calling ConfigureWebHostDefaults
, so maybe this is a holdover behavior in the Web Host from before the Generic Host was created?
It appears to place the Generic Host guidance for setting ApplicationName
in conflict with the Web Host guidance for setting ApplicationName
Eventually I'm hoping that the responsibility of overriding the ApplicationName
config setting can be removed from the web host responsibility and handled in a consistent way by the Generic Host
This line seems to be the unexpected (to me) behavior after reading this guidance on configuring the ApplicationName in the Generic Host docs - maybe I can reproduce that in a unit test
What makes this worse is that the Identity Templates are using @Environment.ApplicationName
. So the Title and Copyright are now the name of my assembly, not the actual Application Name that I want the public to see.
It's really a shame that this wasn't addressed in 3.0. Maybe 5.0?
Question (and proposal): why are we not using directly Assembly.GetEntryAssembly() as a first choice?
In my case (I don't use a startup class), I just put a line after calling Configure with:
protected override IHostBuilder CreateHostBuilder()
=> new HostBuilder()
.UseServiceProviderFactory(ctx => ServiceProviderFactory)
.ConfigureWebHost(webHostBuilder => webHostBuilder
.UseKestrel(options => { })
.UseContentRoot(Directory.GetCurrentDirectory())
.ConfigureServices(ConfigureServices)
.Configure(ConfigureWebHost)
.UseSetting(WebHostDefaults.ApplicationKey, Assembly.GetEntryAssembly().FullName));
And everything works again. Seems to me it's a pretty reasonable default. Maybe it's not when a Framework launcher is used? I'm on Windows, and using self contained exe, so the whole "deploy a dll" is something I never played with. Maybe a fallback logic could be in place.
Question (and proposal): why are we not using directly Assembly.GetEntryAssembly() as a first choice?
In my case (I don't use a startup class), I just put a line after calling Configure with:
protected override IHostBuilder CreateHostBuilder() => new HostBuilder() .UseServiceProviderFactory(ctx => ServiceProviderFactory) .ConfigureWebHost(webHostBuilder => webHostBuilder .UseKestrel(options => { }) .UseContentRoot(Directory.GetCurrentDirectory()) .ConfigureServices(ConfigureServices) .Configure(ConfigureWebHost) .UseSetting(WebHostDefaults.ApplicationKey, Assembly.GetEntryAssembly().FullName));
And everything works again. Seems to me it's a pretty reasonable default. Maybe it's not when a Framework launcher is used? I'm on Windows, and using self contained exe, so the whole "deploy a dll" is something I never played with. Maybe a fallback logic could be in place.
Using Assembly.GetEntryAssembly().FullName
does not work for us, but Assembly.GetEntryAssembly().GetName().Name
does work. Thanks!
Entry assembly would break things like tests where the test process is the entry assembly and your code is hosted as a library inside of the test process.
Entry assembly would break things like tests where the test process is the entry assembly and your code is hosted as a library inside of the test process.
What kind of a test might be broken by this scenario?
I am running into this issue using the pact contract testing framework.
I am spinning up a separate web server for API contract testing, and I'm spinning it up from a unit testing assembly.
I spent a couple of days trying to figure out why I was only getting 404's when I wrap my test startup class in another one to add some middleware for testing.
@davidfowl's solution above helped me resolve this issue. Thanks a lot :)
Describe the bug
Hey,
I am trying to use a Startup class like that
WebHost.CreateDefaultBuilder(args).UseStartup<Startup>().Build().Run()
When the Startup class is located in the execution assembly everything works fine. When the Startup class is located in a different assembly, the service runs but things go wrong during requests - the service throws a 404 without any explanation.Why is it important for me to put my Startup class in a different assembly? Because I have many services that are using the exact same Startup configuration and I want to prevent duplication.
To Reproduce
Steps to reproduce the behavior:
Thank you :)