Skip to content

Commit b1a37a3

Browse files
github-actions[bot]halter73eerhardtericstj
authored
[release/7.0] Do not override content root with default (#79411)
* Do not override content root with default * Address PR feedback * Add more test coverage for custom HostApplicationBuilderSettings * Make package authoring changes * Fix failing Hosting tests (#79455) Ensure the temp directory used is always empty, so it doesn't pick up appsettings.json files randomly. Fix #79453 * Add reference to System.Diagnostics.DiagnosticSource Co-authored-by: Stephen Halter <[email protected]> Co-authored-by: Eric Erhardt <[email protected]> Co-authored-by: Eric StJohn <[email protected]>
1 parent 600c612 commit b1a37a3

File tree

4 files changed

+123
-44
lines changed

4 files changed

+123
-44
lines changed

src/libraries/Microsoft.Extensions.Hosting/src/HostApplicationBuilder.cs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,12 @@ public HostApplicationBuilder(HostApplicationBuilderSettings? settings)
8888

8989
if (!settings.DisableDefaults)
9090
{
91-
HostingHostBuilderExtensions.ApplyDefaultHostConfiguration(Configuration, settings.Args);
91+
if (settings.ContentRootPath is null && Configuration[HostDefaults.ContentRootKey] is null)
92+
{
93+
HostingHostBuilderExtensions.SetDefaultContentRoot(Configuration);
94+
}
95+
96+
HostingHostBuilderExtensions.AddDefaultHostConfigurationSources(Configuration, settings.Args);
9297
}
9398

9499
// HostApplicationBuilderSettings override all other config sources.

src/libraries/Microsoft.Extensions.Hosting/src/HostingHostBuilderExtensions.cs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -198,7 +198,13 @@ public static IHostBuilder ConfigureDefaults(this IHostBuilder builder, string[]
198198
.UseServiceProviderFactory(context => new DefaultServiceProviderFactory(CreateDefaultServiceProviderOptions(context)));
199199
}
200200

201-
internal static void ApplyDefaultHostConfiguration(IConfigurationBuilder hostConfigBuilder, string[]? args)
201+
private static void ApplyDefaultHostConfiguration(IConfigurationBuilder hostConfigBuilder, string[]? args)
202+
{
203+
SetDefaultContentRoot(hostConfigBuilder);
204+
AddDefaultHostConfigurationSources(hostConfigBuilder, args);
205+
}
206+
207+
internal static void SetDefaultContentRoot(IConfigurationBuilder hostConfigBuilder)
202208
{
203209
// If we're running anywhere other than C:\Windows\system32, we default to using the CWD for the ContentRoot.
204210
// However, since many things like Windows services and MSIX installers have C:\Windows\system32 as there CWD which is not likely
@@ -216,7 +222,10 @@ internal static void ApplyDefaultHostConfiguration(IConfigurationBuilder hostCon
216222
new KeyValuePair<string, string?>(HostDefaults.ContentRootKey, cwd),
217223
});
218224
}
225+
}
219226

227+
internal static void AddDefaultHostConfigurationSources(IConfigurationBuilder hostConfigBuilder, string[]? args)
228+
{
220229
hostConfigBuilder.AddEnvironmentVariables(prefix: "DOTNET_");
221230
if (args is { Length: > 0 })
222231
{

src/libraries/Microsoft.Extensions.Hosting/src/Microsoft.Extensions.Hosting.csproj

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
<EnableAOTAnalyzer>true</EnableAOTAnalyzer>
77
<IsPackable>true</IsPackable>
88
<PackageDescription>Hosting and startup infrastructures for applications.</PackageDescription>
9+
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
10+
<ServicingVersion>1</ServicingVersion>
911
</PropertyGroup>
1012

1113
<ItemGroup>
@@ -51,6 +53,7 @@
5153
<ProjectReference Include="$(LibrariesProjectRoot)Microsoft.Extensions.Logging.EventLog\src\Microsoft.Extensions.Logging.EventLog.csproj" />
5254
<ProjectReference Include="$(LibrariesProjectRoot)Microsoft.Extensions.Logging.EventSource\src\Microsoft.Extensions.Logging.EventSource.csproj" />
5355
<ProjectReference Include="$(LibrariesProjectRoot)Microsoft.Extensions.Options\src\Microsoft.Extensions.Options.csproj" />
56+
<ProjectReference Include="$(LibrariesProjectRoot)System.Diagnostics.DiagnosticSource\src\System.Diagnostics.DiagnosticSource.csproj" />
5457
</ItemGroup>
5558

5659
<ItemGroup Condition="!$([MSBuild]::IsTargetFrameworkCompatible('$(TargetFramework)', 'netstandard2.1'))">

src/libraries/Microsoft.Extensions.Hosting/tests/UnitTests/HostApplicationBuilderTests.cs

Lines changed: 104 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -229,66 +229,128 @@ public void DisableDefaultIHostEnvironmentValues()
229229
Assert.IsAssignableFrom<PhysicalFileProvider>(env.ContentRootFileProvider);
230230
}
231231

232-
[Fact]
233-
public void ConfigurationSettingCanInfluenceEnvironment()
232+
[Theory]
233+
[InlineData(true)]
234+
[InlineData(false)]
235+
public void ConfigurationSettingCanInfluenceEnvironment(bool disableDefaults)
234236
{
235-
using var config = new ConfigurationManager();
237+
var tempPath = CreateTempSubdirectory();
236238

237-
config.AddInMemoryCollection(new KeyValuePair<string, string>[]
239+
try
238240
{
239-
new(HostDefaults.ApplicationKey, "AppA" ),
240-
new(HostDefaults.EnvironmentKey, "EnvA" ),
241-
});
241+
using var config = new ConfigurationManager();
242242

243-
var builder = new HostApplicationBuilder(new HostApplicationBuilderSettings
244-
{
245-
DisableDefaults = true,
246-
Configuration = config,
247-
});
243+
config.AddInMemoryCollection(new KeyValuePair<string, string>[]
244+
{
245+
new(HostDefaults.ApplicationKey, "AppA" ),
246+
new(HostDefaults.EnvironmentKey, "EnvA" ),
247+
new(HostDefaults.ContentRootKey, tempPath)
248+
});
249+
250+
var builder = new HostApplicationBuilder(new HostApplicationBuilderSettings
251+
{
252+
DisableDefaults = disableDefaults,
253+
Configuration = config,
254+
});
248255

249-
Assert.Equal("AppA", builder.Configuration[HostDefaults.ApplicationKey]);
250-
Assert.Equal("EnvA", builder.Configuration[HostDefaults.EnvironmentKey]);
256+
Assert.Equal("AppA", builder.Configuration[HostDefaults.ApplicationKey]);
257+
Assert.Equal("EnvA", builder.Configuration[HostDefaults.EnvironmentKey]);
258+
Assert.Equal(tempPath, builder.Configuration[HostDefaults.ContentRootKey]);
251259

252-
Assert.Equal("AppA", builder.Environment.ApplicationName);
253-
Assert.Equal("EnvA", builder.Environment.EnvironmentName);
260+
Assert.Equal("AppA", builder.Environment.ApplicationName);
261+
Assert.Equal("EnvA", builder.Environment.EnvironmentName);
262+
Assert.Equal(tempPath, builder.Environment.ContentRootPath);
263+
var fileProviderFromBuilder = Assert.IsType<PhysicalFileProvider>(builder.Environment.ContentRootFileProvider);
264+
Assert.Equal(tempPath, fileProviderFromBuilder.Root);
254265

255-
using IHost host = builder.Build();
266+
using IHost host = builder.Build();
256267

257-
var hostEnvironmentFromServices = host.Services.GetRequiredService<IHostEnvironment>();
258-
Assert.Equal("AppA", hostEnvironmentFromServices.ApplicationName);
259-
Assert.Equal("EnvA", hostEnvironmentFromServices.EnvironmentName);
268+
var hostEnvironmentFromServices = host.Services.GetRequiredService<IHostEnvironment>();
269+
Assert.Equal("AppA", hostEnvironmentFromServices.ApplicationName);
270+
Assert.Equal("EnvA", hostEnvironmentFromServices.EnvironmentName);
271+
Assert.Equal(tempPath, hostEnvironmentFromServices.ContentRootPath);
272+
var fileProviderFromServices = Assert.IsType<PhysicalFileProvider>(hostEnvironmentFromServices.ContentRootFileProvider);
273+
Assert.Equal(tempPath, fileProviderFromServices.Root);
274+
}
275+
finally
276+
{
277+
Directory.Delete(tempPath);
278+
}
260279
}
261280

262-
[Fact]
263-
public void DirectSettingsOverrideConfigurationSetting()
281+
[Theory]
282+
[InlineData(true)]
283+
[InlineData(false)]
284+
public void DirectSettingsOverrideConfigurationSetting(bool disableDefaults)
264285
{
265-
using var config = new ConfigurationManager();
286+
var tempPath = CreateTempSubdirectory();
266287

267-
config.AddInMemoryCollection(new KeyValuePair<string, string>[]
288+
try
268289
{
269-
new(HostDefaults.ApplicationKey, "AppA" ),
270-
new(HostDefaults.EnvironmentKey, "EnvA" ),
271-
});
290+
using var config = new ConfigurationManager();
272291

273-
var builder = new HostApplicationBuilder(new HostApplicationBuilderSettings
274-
{
275-
DisableDefaults = true,
276-
Configuration = config,
277-
ApplicationName = "AppB",
278-
EnvironmentName = "EnvB",
279-
});
292+
config.AddInMemoryCollection(new KeyValuePair<string, string>[]
293+
{
294+
new(HostDefaults.ApplicationKey, "AppA" ),
295+
new(HostDefaults.EnvironmentKey, "EnvA" ),
296+
});
280297

281-
Assert.Equal("AppB", builder.Configuration[HostDefaults.ApplicationKey]);
282-
Assert.Equal("EnvB", builder.Configuration[HostDefaults.EnvironmentKey]);
298+
var builder = new HostApplicationBuilder(new HostApplicationBuilderSettings
299+
{
300+
DisableDefaults = disableDefaults,
301+
Configuration = config,
302+
ApplicationName = "AppB",
303+
EnvironmentName = "EnvB",
304+
ContentRootPath = tempPath,
305+
});
283306

284-
Assert.Equal("AppB", builder.Environment.ApplicationName);
285-
Assert.Equal("EnvB", builder.Environment.EnvironmentName);
307+
Assert.Equal("AppB", builder.Configuration[HostDefaults.ApplicationKey]);
308+
Assert.Equal("EnvB", builder.Configuration[HostDefaults.EnvironmentKey]);
309+
Assert.Equal(tempPath, builder.Configuration[HostDefaults.ContentRootKey]);
286310

287-
using IHost host = builder.Build();
311+
Assert.Equal("AppB", builder.Environment.ApplicationName);
312+
Assert.Equal("EnvB", builder.Environment.EnvironmentName);
313+
Assert.Equal(tempPath, builder.Environment.ContentRootPath);
314+
var fileProviderFromBuilder = Assert.IsType<PhysicalFileProvider>(builder.Environment.ContentRootFileProvider);
315+
Assert.Equal(tempPath, fileProviderFromBuilder.Root);
288316

289-
var hostEnvironmentFromServices = host.Services.GetRequiredService<IHostEnvironment>();
290-
Assert.Equal("AppB", hostEnvironmentFromServices.ApplicationName);
291-
Assert.Equal("EnvB", hostEnvironmentFromServices.EnvironmentName);
317+
using IHost host = builder.Build();
318+
319+
var hostEnvironmentFromServices = host.Services.GetRequiredService<IHostEnvironment>();
320+
Assert.Equal("AppB", hostEnvironmentFromServices.ApplicationName);
321+
Assert.Equal("EnvB", hostEnvironmentFromServices.EnvironmentName);
322+
Assert.Equal(tempPath, hostEnvironmentFromServices.ContentRootPath);
323+
var fileProviderFromServices = Assert.IsType<PhysicalFileProvider>(hostEnvironmentFromServices.ContentRootFileProvider);
324+
Assert.Equal(tempPath, fileProviderFromServices.Root);
325+
}
326+
finally
327+
{
328+
Directory.Delete(tempPath);
329+
}
330+
}
331+
332+
private static string CreateTempSubdirectory()
333+
{
334+
#if NETCOREAPP
335+
DirectoryInfo directoryInfo = Directory.CreateTempSubdirectory();
336+
#else
337+
DirectoryInfo directoryInfo = new DirectoryInfo(Path.Combine(Path.GetTempPath(), Path.GetRandomFileName()));
338+
directoryInfo.Create();
339+
#endif
340+
341+
// PhysicalFileProvider will always ensure the path has a trailing slash
342+
return EnsureTrailingSlash(directoryInfo.FullName);
343+
}
344+
345+
private static string EnsureTrailingSlash(string path)
346+
{
347+
if (!string.IsNullOrEmpty(path) &&
348+
path[path.Length - 1] != Path.DirectorySeparatorChar)
349+
{
350+
return path + Path.DirectorySeparatorChar;
351+
}
352+
353+
return path;
292354
}
293355

294356
[Fact]

0 commit comments

Comments
 (0)