Skip to content
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

Unable to override IHostEnvironment.ApplicationName using env variables or the command line using ConfigureWebHost/Defaults #34914

Open
davidfowl opened this issue Aug 1, 2021 · 3 comments
Labels
area-hosting Includes Hosting area-networking Includes servers, yarp, json patch, bedrock, websockets, http client factory, and http abstractions severity-nice-to-have This label is used by an internal tool
Milestone

Comments

@davidfowl
Copy link
Member

davidfowl commented Aug 1, 2021

Describe the bug

The generic web host always overrides the application name and sets it as the Startup type's assembly or the configure delegate's container type's assembly name. This means its impossible to override it from the outside. This may not be a big deal generally but with the WebApplicationBuilder and the WebApplicationFactory<TEntryPoint>, we're currently using the command line args to specify any host configuration. This generally works for everything except the application name.

To Reproduce

var host = Host.CreateDefaultBuilder(new[]{ "--applicationName=RandomName" })
       .ConfigureWebHostDefaults(builder => builder.Configure(app => {}))
       .Build();

Assert.Equal("RandomName", host.Services.GetService<IHostEnvironment>().ApplicationName);

This test will fail if the project name isn't RandomName.

cc @halter73

@pranavkm pranavkm added the area-web-frameworks *DEPRECATED* This label is deprecated in favor of the area-mvc and area-minimal labels label Aug 1, 2021
@davidfowl davidfowl added area-runtime feature-minimal-hosting and removed area-web-frameworks *DEPRECATED* This label is deprecated in favor of the area-mvc and area-minimal labels feature-minimal-hosting labels Aug 1, 2021
@adityamandaleeka adityamandaleeka added this to the Backlog milestone Aug 2, 2021
@ghost
Copy link

ghost commented Aug 2, 2021

We've moved this issue to the Backlog milestone. This means that it is not going to be worked on for the coming release. We will reassess the backlog following the current release and consider this item at that time. To learn more about our issue management process and to have better expectation regarding different types of issues you can read our Triage Process.

@adityamandaleeka adityamandaleeka added the severity-nice-to-have This label is used by an internal tool label Aug 2, 2021
@Tratcher
Copy link
Member

Related: #11085

@theo-albers
Copy link

theo-albers commented Nov 21, 2021

Last week I spent some time preparing our .NET 5 solution for .NET 6. We have 3 API projects with similar base setup like Application Insights, Azure App Configuration, Masstransit, Azure BLOB Storage, OpenId Connect, Logging. To eliminate Sonar complaints about duplicate code, we moved some setup to a base class in a library project. In the original .NET 5 setup I placed the code in a StartUp class in the API projects.

When I prepared the code for .NET 6, I started by eliminating the StartUp class: I put everyting in a simple AppBase class. The IHost is constructed in the base class and we have some virtual members which can be overridden in the API projects. One project uses Razor views, since that's the Identity project. The other API projects are pure Controller projects.

When swapping out the StartUp class I ran into the first problem: 404 on every REST call. Ah, since the AddControllers class is now in the library project, the controllers are no longer discovered. The solution was to place this snippet in the library project, under the assumption that the extended App class would be in the API project:

services.AddControllers().AddApplicationPart(GetType().Assembly);

Now I'm able to run the solution and everything works as expected. I deploy the solution to Azure and try to login. Problem: 404 on every Razor page. When I look at the logs via Kudu in Azure at the Linux App Service, I see an exception:

Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware[1]
An unhandled exception has occurred while executing the request.
System.InvalidOperationException: The default Identity UI layout requires a partial view '_LoginPartial' usually located at '/Pages/_LoginPartial' or at '/Views/Shared/_LoginPartial' to work.

This error is misleading, but put me on the right track: I have no _LoginPartial in my code, so there must be something wrong with views. After investigating the ASP.NET 5 hostbuilder code on GitHub, I figured out what the differences were between my local environment and the production environment. Locally I have this setting in my launch settings:

"ASPNETCORE_HOSTINGSTARTUPASSEMBLIES": "Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation"

The local environment finds the views, but deployed environment doesn't. I can fix this by explicitly loading the views via the following snippet:

 public static IMvcCoreBuilder AddControllersAndRazorViewParts(this IMvcCoreBuilder me, Type type)
{
    me.AddApplicationPart(type.Assembly);

    // Load the *.Views.dll compiled Razor assembly which is marked via the RelatedAssemblyAttribute in the main assembly.
    foreach (var relatedAssembly in RelatedAssemblyAttribute.GetRelatedAssemblies(type.Assembly, false))
    {
        me.AddApplicationPart(relatedAssembly);
    }

    return me;
}

I invoke this in my AppBase class.

I can't be the only one with this problem, so I search and find some discussions around the ApplicationName being used by AddMvcCore when it adds the PartManager. When I check out the dotnet repor I see it implicitly loads the parts from the assembly inferred by the ApplicationName. I found more issues related to this stuff:

It's only now, after having hit this problem, I find my problem mentioned the documentation and things start making sense:

https://docs.microsoft.com/en-us/aspnet/core/release-notes/aspnetcore-6.0?view=aspnetcore-6.0
"...
Razor compiler no longer produces a separate Views assembly
..."

Finally I run into this gist https://gist.github.com/davidfowl/0e0372c3c1d895c3ce195ba983b1e03d

"...
The application name always defaults to the entry point assembly's name Assembly.GetEntryAssembly().GetName().FullName. When using the WebApplicationBuilder in a library, you will need to explicitly change the application name to the library's assembly to allow MVC's application part discovery to work (finding controllers, views etc) (see the Cheatsheet for instructions on how to do this).
..."

So I should set the ApplicationName:

    webBuilder..UseSetting(WebHostDefaults.ApplicationKey, typeof(Program).Assembly.FullName);

Mmm... but what does " something arbitrary mean" in aspnet/Mvc#6685:
"...
The doc does needs an update. We should remove that configuring the application name to something arbitrary.
..."

OK, so it has to be an assembly name.

Long story short: when removing the StartUp class in ASP.NET 5 to prepare for .NET 6 you hit runtime issues when you still use .NET 5. The documentation is only useful, after you solved the problems. On top of that .NET 6 has an optimization to no longer place Razor views in a separate View.dll. This makes it very hard to see why your .NET 5 code won't work.

@amcasey amcasey added area-hosting Includes Hosting and removed feature-hosting labels Jun 1, 2023
@amcasey amcasey added area-networking Includes servers, yarp, json patch, bedrock, websockets, http client factory, and http abstractions and removed area-runtime labels Aug 24, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-hosting Includes Hosting area-networking Includes servers, yarp, json patch, bedrock, websockets, http client factory, and http abstractions severity-nice-to-have This label is used by an internal tool
Projects
None yet
Development

No branches or pull requests

6 participants