Skip to content

Commit 0fa7c01

Browse files
authored
Don't allow modifying WebRootPath after initialization (#37147) (#37325)
* Don't allow modifying WebRootPath after initialization * Address feedback from review * Clean up directory handling in tests * Add tests for WebRootPath resolution
1 parent 7e85e31 commit 0fa7c01

File tree

9 files changed

+263
-163
lines changed

9 files changed

+263
-163
lines changed

src/DefaultBuilder/src/BootstrapHostBuilder.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ public IHostBuilder UseServiceProviderFactory<TContainerBuilder>(Func<HostBuilde
105105
{
106106
ApplicationName = hostConfiguration[HostDefaults.ApplicationKey],
107107
EnvironmentName = hostConfiguration[HostDefaults.EnvironmentKey] ?? Environments.Production,
108-
ContentRootPath = ContentRootResolver.ResolvePath(hostConfiguration[HostDefaults.ContentRootKey]),
108+
ContentRootPath = HostingPathResolver.ResolvePath(hostConfiguration[HostDefaults.ContentRootKey]),
109109
};
110110

111111
hostingEnvironment.ContentRootFileProvider = new PhysicalFileProvider(hostingEnvironment.ContentRootPath);

src/DefaultBuilder/src/ConfigureHostBuilder.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,9 +74,9 @@ public IHostBuilder ConfigureHostConfiguration(Action<IConfigurationBuilder> con
7474
throw new NotSupportedException($"The application name changed from \"{previousApplicationName}\" to \"{_configuration[HostDefaults.ApplicationKey]}\". Changing the host configuration using WebApplicationBuilder.Host is not supported. Use WebApplication.CreateBuilder(WebApplicationOptions) instead.");
7575
}
7676

77-
if (!string.Equals(previousContentRoot, ContentRootResolver.ResolvePath(_configuration[HostDefaults.ContentRootKey]), StringComparison.OrdinalIgnoreCase))
77+
if (!string.Equals(previousContentRoot, HostingPathResolver.ResolvePath(_configuration[HostDefaults.ContentRootKey]), StringComparison.OrdinalIgnoreCase))
7878
{
79-
throw new NotSupportedException($"The content root changed from \"{previousContentRoot}\" to \"{ContentRootResolver.ResolvePath(_configuration[HostDefaults.ContentRootKey])}\". Changing the host configuration using WebApplicationBuilder.Host is not supported. Use WebApplication.CreateBuilder(WebApplicationOptions) instead.");
79+
throw new NotSupportedException($"The content root changed from \"{previousContentRoot}\" to \"{HostingPathResolver.ResolvePath(_configuration[HostDefaults.ContentRootKey])}\". Changing the host configuration using WebApplicationBuilder.Host is not supported. Use WebApplication.CreateBuilder(WebApplicationOptions) instead.");
8080
}
8181

8282
if (!string.Equals(previousEnvironment, _configuration[HostDefaults.EnvironmentKey], StringComparison.OrdinalIgnoreCase))

src/DefaultBuilder/src/ConfigureWebHostBuilder.cs

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ IWebHost IWebHostBuilder.Build()
3939
public IWebHostBuilder ConfigureAppConfiguration(Action<WebHostBuilderContext, IConfigurationBuilder> configureDelegate)
4040
{
4141
var previousContentRoot = _context.HostingEnvironment.ContentRootPath;
42-
var previousWebRoot = _configuration[WebHostDefaults.ContentRootKey];
42+
var previousWebRoot = _context.HostingEnvironment.WebRootPath;
4343
var previousApplication = _configuration[WebHostDefaults.ApplicationKey];
4444
var previousEnvironment = _configuration[WebHostDefaults.EnvironmentKey];
4545
var previousHostingStartupAssemblies = _configuration[WebHostDefaults.HostingStartupAssembliesKey];
@@ -48,21 +48,20 @@ public IWebHostBuilder ConfigureAppConfiguration(Action<WebHostBuilderContext, I
4848
// Run these immediately so that they are observable by the imperative code
4949
configureDelegate(_context, _configuration);
5050

51-
if (_configuration[WebHostDefaults.WebRootKey] is string value && !string.Equals(previousWebRoot, value, StringComparison.OrdinalIgnoreCase))
51+
if (!string.Equals(HostingPathResolver.ResolvePath(previousWebRoot, previousContentRoot), HostingPathResolver.ResolvePath(_configuration[WebHostDefaults.WebRootKey], previousContentRoot), StringComparison.OrdinalIgnoreCase))
5252
{
53-
// We allow changing the web root since it's based off the content root and typically
54-
// read after the host is built.
55-
_environment.WebRootPath = Path.Combine(_environment.ContentRootPath, value);
53+
// Diasllow changing the web root for consistency with other types.
54+
throw new NotSupportedException($"The web root changed from \"{HostingPathResolver.ResolvePath(previousWebRoot, previousContentRoot)}\" to \"{HostingPathResolver.ResolvePath(_configuration[WebHostDefaults.WebRootKey], previousContentRoot)}\". Changing the host configuration using WebApplicationBuilder.WebHost is not supported. Use WebApplication.CreateBuilder(WebApplicationOptions) instead.");
5655
}
5756
else if (!string.Equals(previousApplication, _configuration[WebHostDefaults.ApplicationKey], StringComparison.OrdinalIgnoreCase))
5857
{
5958
// Disallow changing any host configuration
6059
throw new NotSupportedException($"The application name changed from \"{previousApplication}\" to \"{_configuration[WebHostDefaults.ApplicationKey]}\". Changing the host configuration using WebApplicationBuilder.WebHost is not supported. Use WebApplication.CreateBuilder(WebApplicationOptions) instead.");
6160
}
62-
else if (!string.Equals(previousContentRoot, ContentRootResolver.ResolvePath(_configuration[WebHostDefaults.ContentRootKey]), StringComparison.OrdinalIgnoreCase))
61+
else if (!string.Equals(previousContentRoot, HostingPathResolver.ResolvePath(_configuration[WebHostDefaults.ContentRootKey]), StringComparison.OrdinalIgnoreCase))
6362
{
6463
// Disallow changing any host configuration
65-
throw new NotSupportedException($"The content root changed from \"{previousContentRoot}\" to \"{ContentRootResolver.ResolvePath(_configuration[WebHostDefaults.ContentRootKey])}\". Changing the host configuration using WebApplicationBuilder.WebHost is not supported. Use WebApplication.CreateBuilder(WebApplicationOptions) instead.");
64+
throw new NotSupportedException($"The content root changed from \"{previousContentRoot}\" to \"{HostingPathResolver.ResolvePath(_configuration[WebHostDefaults.ContentRootKey])}\". Changing the host configuration using WebApplicationBuilder.WebHost is not supported. Use WebApplication.CreateBuilder(WebApplicationOptions) instead.");
6665
}
6766
else if (!string.Equals(previousEnvironment, _configuration[WebHostDefaults.EnvironmentKey], StringComparison.OrdinalIgnoreCase))
6867
{
@@ -113,16 +112,18 @@ public IWebHostBuilder UseSetting(string key, string? value)
113112
}
114113

115114
var previousContentRoot = _context.HostingEnvironment.ContentRootPath;
115+
var previousWebRoot = _context.HostingEnvironment.WebRootPath;
116116
var previousApplication = _configuration[WebHostDefaults.ApplicationKey];
117117
var previousEnvironment = _configuration[WebHostDefaults.EnvironmentKey];
118118
var previousHostingStartupAssemblies = _configuration[WebHostDefaults.HostingStartupAssembliesKey];
119119
var previousHostingStartupAssembliesExclude = _configuration[WebHostDefaults.HostingStartupExcludeAssembliesKey];
120120

121-
if (string.Equals(key, WebHostDefaults.WebRootKey, StringComparison.OrdinalIgnoreCase))
121+
if (string.Equals(key, WebHostDefaults.WebRootKey, StringComparison.OrdinalIgnoreCase) &&
122+
!string.Equals(HostingPathResolver.ResolvePath(previousWebRoot, previousContentRoot), HostingPathResolver.ResolvePath(value, previousContentRoot), StringComparison.OrdinalIgnoreCase))
122123
{
123-
// We allow changing the web root since it's based off the content root and typically
124-
// read after the host is built.
125-
_environment.WebRootPath = Path.Combine(_environment.ContentRootPath, value);
124+
// Disallow changing any host configuration
125+
throw new NotSupportedException($"The web root changed from \"{HostingPathResolver.ResolvePath(previousWebRoot, previousContentRoot)}\" to \"{HostingPathResolver.ResolvePath(value, previousContentRoot)}\". Changing the host configuration using WebApplicationBuilder.WebHost is not supported. Use WebApplication.CreateBuilder(WebApplicationOptions) instead.");
126+
126127
}
127128
else if (string.Equals(key, WebHostDefaults.ApplicationKey, StringComparison.OrdinalIgnoreCase) &&
128129
!string.Equals(previousApplication, value, StringComparison.OrdinalIgnoreCase))
@@ -131,10 +132,10 @@ public IWebHostBuilder UseSetting(string key, string? value)
131132
throw new NotSupportedException($"The application name changed from \"{previousApplication}\" to \"{value}\". Changing the host configuration using WebApplicationBuilder.WebHost is not supported. Use WebApplication.CreateBuilder(WebApplicationOptions) instead.");
132133
}
133134
else if (string.Equals(key, WebHostDefaults.ContentRootKey, StringComparison.OrdinalIgnoreCase) &&
134-
!string.Equals(previousContentRoot, ContentRootResolver.ResolvePath(value), StringComparison.OrdinalIgnoreCase))
135+
!string.Equals(previousContentRoot, HostingPathResolver.ResolvePath(value), StringComparison.OrdinalIgnoreCase))
135136
{
136137
// Disallow changing any host configuration
137-
throw new NotSupportedException($"The content root changed from \"{previousContentRoot}\" to \"{ContentRootResolver.ResolvePath(value)}\". Changing the host configuration using WebApplicationBuilder.WebHost is not supported. Use WebApplication.CreateBuilder(WebApplicationOptions) instead.");
138+
throw new NotSupportedException($"The content root changed from \"{previousContentRoot}\" to \"{HostingPathResolver.ResolvePath(value)}\". Changing the host configuration using WebApplicationBuilder.WebHost is not supported. Use WebApplication.CreateBuilder(WebApplicationOptions) instead.");
138139
}
139140
else if (string.Equals(key, WebHostDefaults.EnvironmentKey, StringComparison.OrdinalIgnoreCase) &&
140141
!string.Equals(previousEnvironment, value, StringComparison.OrdinalIgnoreCase))

src/DefaultBuilder/src/ContentRootResolver.cs renamed to src/DefaultBuilder/src/HostingPathResolver.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,15 @@
33

44
namespace Microsoft.AspNetCore
55
{
6-
internal static class ContentRootResolver
6+
internal static class HostingPathResolver
77
{
88
public static string ResolvePath(string contentRootPath)
99
{
1010
var canonicalPath = ResolvePath(contentRootPath, AppContext.BaseDirectory);
1111
return Path.EndsInDirectorySeparator(canonicalPath) ? canonicalPath : canonicalPath + Path.DirectorySeparatorChar;
1212
}
1313

14-
private static string ResolvePath(string contentRootPath, string basePath)
14+
public static string ResolvePath(string contentRootPath, string basePath)
1515
{
1616
if (string.IsNullOrEmpty(contentRootPath))
1717
{

src/DefaultBuilder/src/PublicAPI.Unshipped.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@ Microsoft.AspNetCore.Builder.WebApplicationOptions.ContentRootPath.get -> string
4242
Microsoft.AspNetCore.Builder.WebApplicationOptions.ContentRootPath.init -> void
4343
Microsoft.AspNetCore.Builder.WebApplicationOptions.EnvironmentName.get -> string?
4444
Microsoft.AspNetCore.Builder.WebApplicationOptions.EnvironmentName.init -> void
45+
Microsoft.AspNetCore.Builder.WebApplicationOptions.WebRootPath.get -> string?
46+
Microsoft.AspNetCore.Builder.WebApplicationOptions.WebRootPath.init -> void
4547
Microsoft.AspNetCore.Builder.WebApplicationOptions.WebApplicationOptions() -> void
4648
static Microsoft.AspNetCore.Builder.WebApplication.Create(string![]? args = null) -> Microsoft.AspNetCore.Builder.WebApplication!
4749
static Microsoft.AspNetCore.Builder.WebApplication.CreateBuilder() -> Microsoft.AspNetCore.Builder.WebApplicationBuilder!

src/DefaultBuilder/src/WebApplicationOptions.cs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,11 @@ public class WebApplicationOptions
3838
/// </summary>
3939
public string? ContentRootPath { get; init; }
4040

41+
/// <summary>
42+
/// The web root path.
43+
/// </summary>
44+
public string? WebRootPath { get; init; }
45+
4146
internal void ApplyHostConfiguration(IConfigurationBuilder builder)
4247
{
4348
Dictionary<string, string>? config = null;
@@ -60,6 +65,12 @@ internal void ApplyHostConfiguration(IConfigurationBuilder builder)
6065
config[HostDefaults.ContentRootKey] = ContentRootPath;
6166
}
6267

68+
if (WebRootPath is not null)
69+
{
70+
config ??= new();
71+
config[WebHostDefaults.WebRootKey] = WebRootPath;
72+
}
73+
6374
if (config is not null)
6475
{
6576
builder.AddInMemoryCollection(config);

0 commit comments

Comments
 (0)