Skip to content

Commit

Permalink
Fix issues with hosting startups (dotnet#36055)
Browse files Browse the repository at this point in the history
* Fix issues with hosting startups
- When the WebApplications's application name is specified, we need to set the it on the internal web host builder so that hosting startups can see the new name. This allows the logic to find hosting startups in the specified application name instead of the entry assembly. When running inside of test projects, the entry assembly is always the test host, that's why it showed it when running tests.
- Added tests
  • Loading branch information
davidfowl authored Sep 2, 2021
1 parent 916e008 commit 26d4aec
Show file tree
Hide file tree
Showing 3 changed files with 86 additions and 3 deletions.
5 changes: 2 additions & 3 deletions src/DefaultBuilder/src/WebApplicationBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -57,9 +57,8 @@ internal WebApplicationBuilder(WebApplicationOptions options, Action<IHostBuilde
// Runs inline.
webHostBuilder.Configure(ConfigureApplication);

// We need to override the application name since the call to Configure will set it to
// be the calling assembly's name.
webHostBuilder.UseSetting(WebHostDefaults.ApplicationKey, (Assembly.GetEntryAssembly())?.GetName()?.Name ?? string.Empty);
// Attempt to set the application name from options
options.ApplyApplicationName(webHostBuilder);
});

// Apply the args to host configuration last since ConfigureWebHostDefaults overrides a host specific setting (the application name).
Expand Down
36 changes: 36 additions & 0 deletions src/DefaultBuilder/src/WebApplicationOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Hosting;
Expand Down Expand Up @@ -64,5 +65,40 @@ internal void ApplyHostConfiguration(IConfigurationBuilder builder)
builder.AddInMemoryCollection(config);
}
}

internal void ApplyApplicationName(IWebHostBuilder webHostBuilder)
{
string? applicationName = null;

// We need to "parse" the args here since
// we need to set the application name via UseSetting
if (Args is not null)
{
var config = new ConfigurationBuilder()
.AddCommandLine(Args)
.Build();

applicationName = config[WebHostDefaults.ApplicationKey];

// This isn't super important since we're not adding any disposable sources
// but just in case
if (config is IDisposable disposable)
{
disposable.Dispose();
}
}

// Application name overrides args
if (ApplicationName is not null)
{
applicationName = ApplicationName;
}

// We need to override the application name since the call to Configure will set it to
// be the calling assembly's name.
applicationName ??= Assembly.GetEntryAssembly()?.GetName()?.Name ?? string.Empty;

webHostBuilder.UseSetting(WebHostDefaults.ApplicationKey, applicationName);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
using Microsoft.AspNetCore.Routing;
using Microsoft.AspNetCore.TestHost;
using Microsoft.AspNetCore.Testing;
using Microsoft.AspNetCore.Tests;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
Expand All @@ -24,6 +25,8 @@
using Microsoft.Extensions.Options;
using Xunit;

[assembly: HostingStartup(typeof(WebApplicationTests.TestHostingStartup))]

namespace Microsoft.AspNetCore.Tests
{
public class WebApplicationTests
Expand Down Expand Up @@ -1229,6 +1232,38 @@ public async Task DeveloperExceptionPageIsNotOnInProduction()
Assert.Equal("BOOM", ex.Message);
}

[Fact]
public async Task HostingStartupRunsWhenApplicationIsNotEntryPoint()
{
var builder = WebApplication.CreateBuilder(new WebApplicationOptions { ApplicationName = typeof(WebApplicationTests).Assembly.FullName });
await using var app = builder.Build();

Assert.Equal("value", app.Configuration["testhostingstartup:config"]);
}

[Fact]
public async Task HostingStartupRunsWhenApplicationIsNotEntryPointWithArgs()
{
var builder = WebApplication.CreateBuilder(new[] { "--applicationName", typeof(WebApplicationTests).Assembly.FullName });
await using var app = builder.Build();

Assert.Equal("value", app.Configuration["testhostingstartup:config"]);
}

[Fact]
public async Task HostingStartupRunsWhenApplicationIsNotEntryPointApplicationNameWinsOverArgs()
{
var options = new WebApplicationOptions
{
Args = new[] { "--applicationName", typeof(WebApplication).Assembly.FullName },
ApplicationName = typeof(WebApplicationTests).Assembly.FullName,
};
var builder = WebApplication.CreateBuilder(options);
await using var app = builder.Build();

Assert.Equal("value", app.Configuration["testhostingstartup:config"]);
}

class ThrowingStartupFilter : IStartupFilter
{
public Action<IApplicationBuilder> Configure(Action<IApplicationBuilder> next)
Expand All @@ -1245,6 +1280,19 @@ public Action<IApplicationBuilder> Configure(Action<IApplicationBuilder> next)
}
}

public class TestHostingStartup : IHostingStartup
{
public void Configure(IWebHostBuilder builder)
{
builder
.ConfigureAppConfiguration((context, configurationBuilder) => configurationBuilder.AddInMemoryCollection(
new[]
{
new KeyValuePair<string,string>("testhostingstartup:config", "value")
}));
}
}

class PropertyFilter : IStartupFilter
{
public Action<IApplicationBuilder> Configure(Action<IApplicationBuilder> next)
Expand Down

0 comments on commit 26d4aec

Please sign in to comment.