From cfcc23614a5353c9dccc0079e192cb0d1da7e967 Mon Sep 17 00:00:00 2001 From: Jacob Bundgaard Date: Fri, 18 Jul 2025 18:12:07 +0200 Subject: [PATCH 1/7] Update UseSolutionRelativeContentRoot to support sln and slnx files by default --- .../TestHost/src/PublicAPI.Shipped.txt | 6 +- .../TestHost/src/WebHostBuilderExtensions.cs | 56 ++++- .../UseSolutionRelativeContentRootTests.cs | 196 ++++++++++++++++++ .../WebApplicationFactorySlnxTests.cs | 74 +++++++ 4 files changed, 322 insertions(+), 10 deletions(-) create mode 100644 src/Hosting/TestHost/test/UseSolutionRelativeContentRootTests.cs create mode 100644 src/Mvc/test/Mvc.FunctionalTests/WebApplicationFactorySlnxTests.cs diff --git a/src/Hosting/TestHost/src/PublicAPI.Shipped.txt b/src/Hosting/TestHost/src/PublicAPI.Shipped.txt index 4333342f4f5d..cd5a4bbda9b7 100644 --- a/src/Hosting/TestHost/src/PublicAPI.Shipped.txt +++ b/src/Hosting/TestHost/src/PublicAPI.Shipped.txt @@ -56,8 +56,10 @@ static Microsoft.AspNetCore.TestHost.WebHostBuilderExtensions.ConfigureTestConta static Microsoft.AspNetCore.TestHost.WebHostBuilderExtensions.ConfigureTestServices(this Microsoft.AspNetCore.Hosting.IWebHostBuilder! webHostBuilder, System.Action! servicesConfiguration) -> Microsoft.AspNetCore.Hosting.IWebHostBuilder! static Microsoft.AspNetCore.TestHost.WebHostBuilderExtensions.GetTestClient(this Microsoft.AspNetCore.Hosting.IWebHost! host) -> System.Net.Http.HttpClient! static Microsoft.AspNetCore.TestHost.WebHostBuilderExtensions.GetTestServer(this Microsoft.AspNetCore.Hosting.IWebHost! host) -> Microsoft.AspNetCore.TestHost.TestServer! -static Microsoft.AspNetCore.TestHost.WebHostBuilderExtensions.UseSolutionRelativeContentRoot(this Microsoft.AspNetCore.Hosting.IWebHostBuilder! builder, string! solutionRelativePath, string! applicationBasePath, string! solutionName = "*.sln") -> Microsoft.AspNetCore.Hosting.IWebHostBuilder! -static Microsoft.AspNetCore.TestHost.WebHostBuilderExtensions.UseSolutionRelativeContentRoot(this Microsoft.AspNetCore.Hosting.IWebHostBuilder! builder, string! solutionRelativePath, string! solutionName = "*.sln") -> Microsoft.AspNetCore.Hosting.IWebHostBuilder! +static Microsoft.AspNetCore.TestHost.WebHostBuilderExtensions.UseSolutionRelativeContentRoot(this Microsoft.AspNetCore.Hosting.IWebHostBuilder! builder, string! solutionRelativePath) -> Microsoft.AspNetCore.Hosting.IWebHostBuilder! +static Microsoft.AspNetCore.TestHost.WebHostBuilderExtensions.UseSolutionRelativeContentRoot(this Microsoft.AspNetCore.Hosting.IWebHostBuilder! builder, string! solutionRelativePath, string! applicationBasePath, string! solutionName) -> Microsoft.AspNetCore.Hosting.IWebHostBuilder! +static Microsoft.AspNetCore.TestHost.WebHostBuilderExtensions.UseSolutionRelativeContentRoot(this Microsoft.AspNetCore.Hosting.IWebHostBuilder! builder, string! solutionRelativePath, string! applicationBasePath, System.ReadOnlySpan solutionNames = default(System.ReadOnlySpan)) -> Microsoft.AspNetCore.Hosting.IWebHostBuilder! +static Microsoft.AspNetCore.TestHost.WebHostBuilderExtensions.UseSolutionRelativeContentRoot(this Microsoft.AspNetCore.Hosting.IWebHostBuilder! builder, string! solutionRelativePath, string! solutionName) -> Microsoft.AspNetCore.Hosting.IWebHostBuilder! static Microsoft.AspNetCore.TestHost.WebHostBuilderExtensions.UseTestServer(this Microsoft.AspNetCore.Hosting.IWebHostBuilder! builder) -> Microsoft.AspNetCore.Hosting.IWebHostBuilder! static Microsoft.AspNetCore.TestHost.WebHostBuilderExtensions.UseTestServer(this Microsoft.AspNetCore.Hosting.IWebHostBuilder! builder, System.Action! configureOptions) -> Microsoft.AspNetCore.Hosting.IWebHostBuilder! static Microsoft.AspNetCore.TestHost.WebHostBuilderFactory.CreateFromAssemblyEntryPoint(System.Reflection.Assembly! assembly, string![]! args) -> Microsoft.AspNetCore.Hosting.IWebHostBuilder? diff --git a/src/Hosting/TestHost/src/WebHostBuilderExtensions.cs b/src/Hosting/TestHost/src/WebHostBuilderExtensions.cs index cbdb7e06e989..e38f390326a2 100644 --- a/src/Hosting/TestHost/src/WebHostBuilderExtensions.cs +++ b/src/Hosting/TestHost/src/WebHostBuilderExtensions.cs @@ -16,6 +16,8 @@ namespace Microsoft.AspNetCore.TestHost; /// public static class WebHostBuilderExtensions { + private static readonly string[] _defaultSolutionNames = ["*.sln", "*.slnx"]; + /// /// Enables the service. /// @@ -115,6 +117,19 @@ public static IWebHostBuilder ConfigureTestContainer(this IWebHostBu return webHostBuilder; } + /// + /// Sets the content root of relative to the . + /// + /// The . + /// The directory of the solution file. + /// The . + public static IWebHostBuilder UseSolutionRelativeContentRoot( + this IWebHostBuilder builder, + string solutionRelativePath) + { + return builder.UseSolutionRelativeContentRoot(solutionRelativePath, AppContext.BaseDirectory, _defaultSolutionNames); + } + /// /// Sets the content root of relative to the . /// @@ -122,13 +137,12 @@ public static IWebHostBuilder ConfigureTestContainer(this IWebHostBu /// The directory of the solution file. /// The name of the solution file to make the content root relative to. /// The . - [SuppressMessage("ApiDesign", "RS0026:Do not add multiple public overloads with optional parameters", Justification = "Required to maintain compatibility")] public static IWebHostBuilder UseSolutionRelativeContentRoot( this IWebHostBuilder builder, string solutionRelativePath, - string solutionName = "*.sln") + string solutionName) { - return builder.UseSolutionRelativeContentRoot(solutionRelativePath, AppContext.BaseDirectory, solutionName); + return builder.UseSolutionRelativeContentRoot(solutionRelativePath, AppContext.BaseDirectory, [solutionName]); } /// @@ -144,19 +158,45 @@ public static IWebHostBuilder UseSolutionRelativeContentRoot( this IWebHostBuilder builder, string solutionRelativePath, string applicationBasePath, - string solutionName = "*.sln") + string solutionName) + { + return builder.UseSolutionRelativeContentRoot(solutionRelativePath, applicationBasePath, [solutionName]); + } + + /// + /// Sets the content root of relative to the . + /// + /// The . + /// The directory of the solution file. + /// The root of the app's directory. + /// The names of the solution files to make the content root relative to. If empty, defaults to *.sln and *.slnx. + /// The . + [SuppressMessage("ApiDesign", "RS0026:Do not add multiple public overloads with optional parameters", Justification = "Required to maintain compatibility")] + public static IWebHostBuilder UseSolutionRelativeContentRoot( + this IWebHostBuilder builder, + string solutionRelativePath, + string applicationBasePath, + ReadOnlySpan solutionNames = default) { ArgumentNullException.ThrowIfNull(solutionRelativePath); ArgumentNullException.ThrowIfNull(applicationBasePath); + if (solutionNames.IsEmpty) + { + solutionNames = _defaultSolutionNames; + } + var directoryInfo = new DirectoryInfo(applicationBasePath); do { - var solutionPath = Directory.EnumerateFiles(directoryInfo.FullName, solutionName).FirstOrDefault(); - if (solutionPath != null) + foreach (var solutionName in solutionNames) { - builder.UseContentRoot(Path.GetFullPath(Path.Combine(directoryInfo.FullName, solutionRelativePath))); - return builder; + var solutionPath = Directory.EnumerateFiles(directoryInfo.FullName, solutionName).FirstOrDefault(); + if (solutionPath != null) + { + builder.UseContentRoot(Path.GetFullPath(Path.Combine(directoryInfo.FullName, solutionRelativePath))); + return builder; + } } directoryInfo = directoryInfo.Parent; diff --git a/src/Hosting/TestHost/test/UseSolutionRelativeContentRootTests.cs b/src/Hosting/TestHost/test/UseSolutionRelativeContentRootTests.cs new file mode 100644 index 000000000000..26ce35e10f1a --- /dev/null +++ b/src/Hosting/TestHost/test/UseSolutionRelativeContentRootTests.cs @@ -0,0 +1,196 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using Microsoft.AspNetCore.Hosting; +using Microsoft.Extensions.DependencyInjection; + +namespace Microsoft.AspNetCore.TestHost; + +public class UseSolutionRelativeContentRootTests : IDisposable +{ + private readonly string _tempDirectory; + private readonly string _contentDirectory; + + public UseSolutionRelativeContentRootTests() + { + _tempDirectory = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString("N")[..8]); + _contentDirectory = Path.Combine(_tempDirectory, "src"); + Directory.CreateDirectory(_contentDirectory); + } + + [Fact] + public void UseSolutionRelativeContentRoot_FindsSlnFile() + { + var solutionFile = Path.Combine(_tempDirectory, "TestApp.sln"); + File.WriteAllText(solutionFile, "Microsoft Visual Studio Solution File, Format Version 12.00"); + + var builder = new WebHostBuilder() + .UseTestServer() + .Configure(app => { }); + + builder.UseSolutionRelativeContentRoot("src", applicationBasePath: _tempDirectory); + + using var host = builder.Build(); + var environment = host.Services.GetRequiredService(); + + Assert.Equal(_contentDirectory, environment.ContentRootPath); + } + + [Fact] + public void UseSolutionRelativeContentRoot_FindsSlnxFile() + { + var solutionFile = Path.Combine(_tempDirectory, "TestApp.slnx"); + File.WriteAllText(solutionFile, """ + + + + + + + """); + + var builder = new WebHostBuilder() + .UseTestServer() + .Configure(app => { }); + + builder.UseSolutionRelativeContentRoot("src", applicationBasePath: _tempDirectory); + + using var host = builder.Build(); + var environment = host.Services.GetRequiredService(); + + Assert.Equal(_contentDirectory, environment.ContentRootPath); + } + + [Fact] + public void UseSolutionRelativeContentRoot_WithSolutionName_FindsSpecifiedFile() + { + var subDirectory = Path.Combine(_tempDirectory, "sub"); + Directory.CreateDirectory(subDirectory); + + var slnFile = Path.Combine(subDirectory, "TestApp.sln"); + var slnxFile = Path.Combine(_tempDirectory, "TestApp.slnx"); + File.WriteAllText(slnFile, "Microsoft Visual Studio Solution File, Format Version 12.00"); + File.WriteAllText(slnxFile, """ + + + + + + """); + + var builder = new WebHostBuilder() + .UseTestServer() + .Configure(app => { }); + + builder.UseSolutionRelativeContentRoot("src", _tempDirectory, "*.slnx"); + + using var host = builder.Build(); + var environment = host.Services.GetRequiredService(); + + Assert.Equal(_contentDirectory, environment.ContentRootPath); + } + + [Fact] + public void UseSolutionRelativeContentRoot_WithMultipleSolutionNames_FindsInCurrentDirectoryFirst() + { + var expectedPath = Path.Combine(_contentDirectory, "sub"); + Directory.CreateDirectory(expectedPath); + + var slnFile = Path.Combine(_tempDirectory, "TestApp.sln"); + var slnxFile = Path.Combine(_contentDirectory, "TestApp.slnx"); + File.WriteAllText(slnFile, "Microsoft Visual Studio Solution File, Format Version 12.00"); + File.WriteAllText(slnxFile, """ + + + + + + """); + + var builder = new WebHostBuilder() + .UseTestServer() + .Configure(app => { }); + + builder.UseSolutionRelativeContentRoot("sub", _contentDirectory, ["*.sln", "*.slnx"]); + + using var host = builder.Build(); + var environment = host.Services.GetRequiredService(); + + Assert.Equal(expectedPath, environment.ContentRootPath); + } + + [Fact] + public void UseSolutionRelativeContentRoot_WithMultipleSolutionNames_WorksWithMultipleFiles() + { + var slnFile = Path.Combine(_tempDirectory, "TestApp.sln"); + var slnxFile = Path.Combine(_tempDirectory, "TestApp.slnx"); + File.WriteAllText(slnFile, "Microsoft Visual Studio Solution File, Format Version 12.00"); + File.WriteAllText(slnxFile, """ + + + + + + """); + + var builder = new WebHostBuilder() + .UseTestServer() + .Configure(app => { }); + + builder.UseSolutionRelativeContentRoot("src", applicationBasePath: _tempDirectory, solutionNames: ["*.sln", "*.slnx"]); + + using var host = builder.Build(); + var environment = host.Services.GetRequiredService(); + + Assert.Equal(_contentDirectory, environment.ContentRootPath); + } + + [Fact] + public void UseSolutionRelativeContentRoot_ThrowsWhenSolutionNotFound() + { + var builder = new WebHostBuilder() + .UseTestServer() + .Configure(app => { }); + + var exception = Assert.Throws(() => + builder.UseSolutionRelativeContentRoot("src", applicationBasePath: _tempDirectory)); + + Assert.Contains("Solution root could not be located", exception.Message); + Assert.Contains(_tempDirectory, exception.Message); + } + + [Fact] + public void UseSolutionRelativeContentRoot_WithSolutionName_SearchesParentDirectories() + { + var subDirectory = Path.Combine(_tempDirectory, "sub", "folder"); + Directory.CreateDirectory(subDirectory); + + var solutionFile = Path.Combine(_tempDirectory, "TestApp.slnx"); + File.WriteAllText(solutionFile, """ + + + + + + """); + + var builder = new WebHostBuilder() + .UseTestServer() + .Configure(app => { }); + + builder.UseSolutionRelativeContentRoot("src", subDirectory, "*.slnx"); + + using var host = builder.Build(); + var environment = host.Services.GetRequiredService(); + + Assert.Equal(_contentDirectory, environment.ContentRootPath); + } + + public void Dispose() + { + if (Directory.Exists(_tempDirectory)) + { + Directory.Delete(_tempDirectory, recursive: true); + } + } +} diff --git a/src/Mvc/test/Mvc.FunctionalTests/WebApplicationFactorySlnxTests.cs b/src/Mvc/test/Mvc.FunctionalTests/WebApplicationFactorySlnxTests.cs new file mode 100644 index 000000000000..60de72aa2e55 --- /dev/null +++ b/src/Mvc/test/Mvc.FunctionalTests/WebApplicationFactorySlnxTests.cs @@ -0,0 +1,74 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using Microsoft.AspNetCore.Hosting; +using Microsoft.AspNetCore.Mvc.Testing; +using Microsoft.AspNetCore.TestHost; +using Microsoft.Extensions.DependencyInjection; +using BasicWebSite; + +namespace Microsoft.AspNetCore.Mvc.FunctionalTests; + +public class WebApplicationFactorySlnxTests : IClassFixture>, IDisposable +{ + private readonly string _tempDirectory; + private readonly string _contentDirectory; + + public WebApplicationFactorySlnxTests(WebApplicationFactory factory) + { + Factory = factory; + _tempDirectory = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString("N")[..8]); + _contentDirectory = Path.Combine(_tempDirectory, "BasicWebSite"); + + Directory.CreateDirectory(_tempDirectory); + Directory.CreateDirectory(_contentDirectory); + + // Create a minimal wwwroot directory to satisfy content root expectations + var wwwrootDir = Path.Combine(_contentDirectory, "wwwroot"); + Directory.CreateDirectory(wwwrootDir); + } + + public WebApplicationFactory Factory { get; } + + [Fact] + public async Task WebApplicationFactory_UsesSlnxForSolutionRelativeContentRoot() + { + // Create .slnx file in temp directory + var slnxFile = Path.Combine(_tempDirectory, "TestSolution.slnx"); + File.WriteAllText(slnxFile, """ + + + + + + + + + + """); + + var factory = Factory.WithWebHostBuilder(builder => + { + builder.UseSolutionRelativeContentRoot("BasicWebSite", _tempDirectory, "TestSolution.slnx"); + }); + + using var client = factory.CreateClient(); + + // Verify that the content root was set correctly by accessing the environment + var environment = factory.Services.GetRequiredService(); + Assert.Equal(_contentDirectory, environment.ContentRootPath); + Assert.True(Directory.Exists(environment.ContentRootPath)); + + // Verify the factory is functional with the .slnx-resolved content root + var response = await client.GetAsync("/"); + Assert.True(response.IsSuccessStatusCode); + } + + public void Dispose() + { + if (Directory.Exists(_tempDirectory)) + { + Directory.Delete(_tempDirectory, recursive: true); + } + } +} From 6bfe28fc56431bf3bb92bb474df92162fac1852a Mon Sep 17 00:00:00 2001 From: Stephen Halter Date: Fri, 15 Aug 2025 12:57:50 -0700 Subject: [PATCH 2/7] Remove unnecessary suppressions --- src/Hosting/TestHost/src/WebHostBuilderExtensions.cs | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/Hosting/TestHost/src/WebHostBuilderExtensions.cs b/src/Hosting/TestHost/src/WebHostBuilderExtensions.cs index e38f390326a2..ca2e1f20862a 100644 --- a/src/Hosting/TestHost/src/WebHostBuilderExtensions.cs +++ b/src/Hosting/TestHost/src/WebHostBuilderExtensions.cs @@ -1,7 +1,6 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Net.Http; using Microsoft.AspNetCore.Hosting; @@ -153,7 +152,6 @@ public static IWebHostBuilder UseSolutionRelativeContentRoot( /// The root of the app's directory. /// The name of the solution file to make the content root relative to. /// The . - [SuppressMessage("ApiDesign", "RS0026:Do not add multiple public overloads with optional parameters", Justification = "Required to maintain compatibility")] public static IWebHostBuilder UseSolutionRelativeContentRoot( this IWebHostBuilder builder, string solutionRelativePath, @@ -171,7 +169,6 @@ public static IWebHostBuilder UseSolutionRelativeContentRoot( /// The root of the app's directory. /// The names of the solution files to make the content root relative to. If empty, defaults to *.sln and *.slnx. /// The . - [SuppressMessage("ApiDesign", "RS0026:Do not add multiple public overloads with optional parameters", Justification = "Required to maintain compatibility")] public static IWebHostBuilder UseSolutionRelativeContentRoot( this IWebHostBuilder builder, string solutionRelativePath, From b7f3586eca5a62d9fb2a23a9c424a6261081c682 Mon Sep 17 00:00:00 2001 From: Stephen Halter Date: Fri, 15 Aug 2025 13:04:14 -0700 Subject: [PATCH 3/7] Move PublicAPI.Shipped.txt changes to PublicAPI.Unshipped.txt --- src/Hosting/TestHost/src/PublicAPI.Shipped.txt | 6 ++---- src/Hosting/TestHost/src/PublicAPI.Unshipped.txt | 7 +++++++ 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/src/Hosting/TestHost/src/PublicAPI.Shipped.txt b/src/Hosting/TestHost/src/PublicAPI.Shipped.txt index cd5a4bbda9b7..4333342f4f5d 100644 --- a/src/Hosting/TestHost/src/PublicAPI.Shipped.txt +++ b/src/Hosting/TestHost/src/PublicAPI.Shipped.txt @@ -56,10 +56,8 @@ static Microsoft.AspNetCore.TestHost.WebHostBuilderExtensions.ConfigureTestConta static Microsoft.AspNetCore.TestHost.WebHostBuilderExtensions.ConfigureTestServices(this Microsoft.AspNetCore.Hosting.IWebHostBuilder! webHostBuilder, System.Action! servicesConfiguration) -> Microsoft.AspNetCore.Hosting.IWebHostBuilder! static Microsoft.AspNetCore.TestHost.WebHostBuilderExtensions.GetTestClient(this Microsoft.AspNetCore.Hosting.IWebHost! host) -> System.Net.Http.HttpClient! static Microsoft.AspNetCore.TestHost.WebHostBuilderExtensions.GetTestServer(this Microsoft.AspNetCore.Hosting.IWebHost! host) -> Microsoft.AspNetCore.TestHost.TestServer! -static Microsoft.AspNetCore.TestHost.WebHostBuilderExtensions.UseSolutionRelativeContentRoot(this Microsoft.AspNetCore.Hosting.IWebHostBuilder! builder, string! solutionRelativePath) -> Microsoft.AspNetCore.Hosting.IWebHostBuilder! -static Microsoft.AspNetCore.TestHost.WebHostBuilderExtensions.UseSolutionRelativeContentRoot(this Microsoft.AspNetCore.Hosting.IWebHostBuilder! builder, string! solutionRelativePath, string! applicationBasePath, string! solutionName) -> Microsoft.AspNetCore.Hosting.IWebHostBuilder! -static Microsoft.AspNetCore.TestHost.WebHostBuilderExtensions.UseSolutionRelativeContentRoot(this Microsoft.AspNetCore.Hosting.IWebHostBuilder! builder, string! solutionRelativePath, string! applicationBasePath, System.ReadOnlySpan solutionNames = default(System.ReadOnlySpan)) -> Microsoft.AspNetCore.Hosting.IWebHostBuilder! -static Microsoft.AspNetCore.TestHost.WebHostBuilderExtensions.UseSolutionRelativeContentRoot(this Microsoft.AspNetCore.Hosting.IWebHostBuilder! builder, string! solutionRelativePath, string! solutionName) -> Microsoft.AspNetCore.Hosting.IWebHostBuilder! +static Microsoft.AspNetCore.TestHost.WebHostBuilderExtensions.UseSolutionRelativeContentRoot(this Microsoft.AspNetCore.Hosting.IWebHostBuilder! builder, string! solutionRelativePath, string! applicationBasePath, string! solutionName = "*.sln") -> Microsoft.AspNetCore.Hosting.IWebHostBuilder! +static Microsoft.AspNetCore.TestHost.WebHostBuilderExtensions.UseSolutionRelativeContentRoot(this Microsoft.AspNetCore.Hosting.IWebHostBuilder! builder, string! solutionRelativePath, string! solutionName = "*.sln") -> Microsoft.AspNetCore.Hosting.IWebHostBuilder! static Microsoft.AspNetCore.TestHost.WebHostBuilderExtensions.UseTestServer(this Microsoft.AspNetCore.Hosting.IWebHostBuilder! builder) -> Microsoft.AspNetCore.Hosting.IWebHostBuilder! static Microsoft.AspNetCore.TestHost.WebHostBuilderExtensions.UseTestServer(this Microsoft.AspNetCore.Hosting.IWebHostBuilder! builder, System.Action! configureOptions) -> Microsoft.AspNetCore.Hosting.IWebHostBuilder! static Microsoft.AspNetCore.TestHost.WebHostBuilderFactory.CreateFromAssemblyEntryPoint(System.Reflection.Assembly! assembly, string![]! args) -> Microsoft.AspNetCore.Hosting.IWebHostBuilder? diff --git a/src/Hosting/TestHost/src/PublicAPI.Unshipped.txt b/src/Hosting/TestHost/src/PublicAPI.Unshipped.txt index 7dc5c58110bf..38d66595d1b9 100644 --- a/src/Hosting/TestHost/src/PublicAPI.Unshipped.txt +++ b/src/Hosting/TestHost/src/PublicAPI.Unshipped.txt @@ -1 +1,8 @@ #nullable enable +*REMOVED*static Microsoft.AspNetCore.TestHost.WebHostBuilderExtensions.UseSolutionRelativeContentRoot(this Microsoft.AspNetCore.Hosting.IWebHostBuilder! builder, string! solutionRelativePath, string! applicationBasePath, string! solutionName = "*.sln") -> Microsoft.AspNetCore.Hosting.IWebHostBuilder! +*REMOVED*static Microsoft.AspNetCore.TestHost.WebHostBuilderExtensions.UseSolutionRelativeContentRoot(this Microsoft.AspNetCore.Hosting.IWebHostBuilder! builder, string! solutionRelativePath, string! solutionName = "*.sln") -> Microsoft.AspNetCore.Hosting.IWebHostBuilder! +static Microsoft.AspNetCore.TestHost.WebHostBuilderExtensions.UseSolutionRelativeContentRoot(this Microsoft.AspNetCore.Hosting.IWebHostBuilder! builder, string! solutionRelativePath) -> Microsoft.AspNetCore.Hosting.IWebHostBuilder! +static Microsoft.AspNetCore.TestHost.WebHostBuilderExtensions.UseSolutionRelativeContentRoot(this Microsoft.AspNetCore.Hosting.IWebHostBuilder! builder, string! solutionRelativePath, string! applicationBasePath, string! solutionName) -> Microsoft.AspNetCore.Hosting.IWebHostBuilder! +static Microsoft.AspNetCore.TestHost.WebHostBuilderExtensions.UseSolutionRelativeContentRoot(this Microsoft.AspNetCore.Hosting.IWebHostBuilder! builder, string! solutionRelativePath, string! applicationBasePath, System.ReadOnlySpan solutionNames = default(System.ReadOnlySpan)) -> Microsoft.AspNetCore.Hosting.IWebHostBuilder! +static Microsoft.AspNetCore.TestHost.WebHostBuilderExtensions.UseSolutionRelativeContentRoot(this Microsoft.AspNetCore.Hosting.IWebHostBuilder! builder, string! solutionRelativePath, string! solutionName) -> Microsoft.AspNetCore.Hosting.IWebHostBuilder! + From ed40bdacbb3e57da40aa2a648617705971a7d2db Mon Sep 17 00:00:00 2001 From: Stephen Halter Date: Fri, 15 Aug 2025 13:08:07 -0700 Subject: [PATCH 4/7] Add RS0027 suppression --- src/Hosting/TestHost/src/WebHostBuilderExtensions.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Hosting/TestHost/src/WebHostBuilderExtensions.cs b/src/Hosting/TestHost/src/WebHostBuilderExtensions.cs index ca2e1f20862a..9f4bff6a7f2b 100644 --- a/src/Hosting/TestHost/src/WebHostBuilderExtensions.cs +++ b/src/Hosting/TestHost/src/WebHostBuilderExtensions.cs @@ -169,7 +169,9 @@ public static IWebHostBuilder UseSolutionRelativeContentRoot( /// The root of the app's directory. /// The names of the solution files to make the content root relative to. If empty, defaults to *.sln and *.slnx. /// The . +#pragma warning disable RS0027 // Public API with optional parameter(s) should have the most parameters amongst its public overloads public static IWebHostBuilder UseSolutionRelativeContentRoot( +#pragma warning restore RS0027 // Public API with optional parameter(s) should have the most parameters amongst its public overloads this IWebHostBuilder builder, string solutionRelativePath, string applicationBasePath, From 6d790f12119abe92d14c5289561bdaead576a1ca Mon Sep 17 00:00:00 2001 From: Stephen Halter Date: Fri, 15 Aug 2025 13:14:20 -0700 Subject: [PATCH 5/7] Use attribute for suppression instead like before --- src/Hosting/TestHost/src/WebHostBuilderExtensions.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Hosting/TestHost/src/WebHostBuilderExtensions.cs b/src/Hosting/TestHost/src/WebHostBuilderExtensions.cs index 9f4bff6a7f2b..43dccd172d08 100644 --- a/src/Hosting/TestHost/src/WebHostBuilderExtensions.cs +++ b/src/Hosting/TestHost/src/WebHostBuilderExtensions.cs @@ -1,6 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Net.Http; using Microsoft.AspNetCore.Hosting; @@ -169,9 +170,8 @@ public static IWebHostBuilder UseSolutionRelativeContentRoot( /// The root of the app's directory. /// The names of the solution files to make the content root relative to. If empty, defaults to *.sln and *.slnx. /// The . -#pragma warning disable RS0027 // Public API with optional parameter(s) should have the most parameters amongst its public overloads + [SuppressMessage("ApiDesign", "RS0027:Public API with optional parameter(s) should have the most parameters amongst its public overloads", Justification = "Required to maintain compatibility")] public static IWebHostBuilder UseSolutionRelativeContentRoot( -#pragma warning restore RS0027 // Public API with optional parameter(s) should have the most parameters amongst its public overloads this IWebHostBuilder builder, string solutionRelativePath, string applicationBasePath, From 8e167542d7d2c8210382b160a969702a44e681ef Mon Sep 17 00:00:00 2001 From: Stephen Halter Date: Fri, 15 Aug 2025 14:53:58 -0700 Subject: [PATCH 6/7] Suppress WebHostBuilder obsoletion warnings in UseSolutionRelativeContentRootTests --- .../TestHost/test/UseSolutionRelativeContentRootTests.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Hosting/TestHost/test/UseSolutionRelativeContentRootTests.cs b/src/Hosting/TestHost/test/UseSolutionRelativeContentRootTests.cs index 26ce35e10f1a..40a57a378614 100644 --- a/src/Hosting/TestHost/test/UseSolutionRelativeContentRootTests.cs +++ b/src/Hosting/TestHost/test/UseSolutionRelativeContentRootTests.cs @@ -6,6 +6,7 @@ namespace Microsoft.AspNetCore.TestHost; +#pragma warning disable ASPDEPR004 // Type or member is obsolete public class UseSolutionRelativeContentRootTests : IDisposable { private readonly string _tempDirectory; @@ -194,3 +195,4 @@ public void Dispose() } } } +#pragma warning restore ASPDEPR004 // Type or member is obsolete From a9f95ad0b5581f9550b12d0e422d18a572ea3ad3 Mon Sep 17 00:00:00 2001 From: Stephen Halter Date: Fri, 15 Aug 2025 15:18:47 -0700 Subject: [PATCH 7/7] Suppress WebHost obsoletion warnings in UseSolutionRelativeContentRootTests --- .../TestHost/test/UseSolutionRelativeContentRootTests.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/Hosting/TestHost/test/UseSolutionRelativeContentRootTests.cs b/src/Hosting/TestHost/test/UseSolutionRelativeContentRootTests.cs index 40a57a378614..96a6466b72ad 100644 --- a/src/Hosting/TestHost/test/UseSolutionRelativeContentRootTests.cs +++ b/src/Hosting/TestHost/test/UseSolutionRelativeContentRootTests.cs @@ -6,7 +6,8 @@ namespace Microsoft.AspNetCore.TestHost; -#pragma warning disable ASPDEPR004 // Type or member is obsolete +#pragma warning disable ASPDEPR004 // WebHostBuilder is obsolete +#pragma warning disable ASPDEPR008 // WebHost is obsolete public class UseSolutionRelativeContentRootTests : IDisposable { private readonly string _tempDirectory; @@ -195,4 +196,5 @@ public void Dispose() } } } -#pragma warning restore ASPDEPR004 // Type or member is obsolete +#pragma warning restore ASPDEPR008 // WebHost is obsolete +#pragma warning disable ASPDEPR004 // WebHostBuilder is obsolete