Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/dotnet/aspnetcore.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPranav K <prkrishn@hotmail.com>2022-03-31 02:29:17 +0300
committerJames Newton-King <james@newtonking.com>2022-03-31 11:20:32 +0300
commit6b6b39b857e2b2602e8f089e0fab8713a409c6e8 (patch)
treec326dffb3fd7c6475e7dd37679f5648251a108a4
parentcef52ffd679ff3a1966cce3f9782f13496fff672 (diff)
Trim Microsoft.AspNetCore.Hostingjamesnk/trimming-hosting-full
-rw-r--r--eng/TrimmableProjects.props3
-rw-r--r--src/Hosting/Abstractions/src/HostingAbstractionsWebHostBuilderExtensions.cs2
-rw-r--r--src/Hosting/Hosting.slnf3
-rw-r--r--src/Hosting/Hosting/src/GenericHost/GenericWebHostBuilder.cs58
-rw-r--r--src/Hosting/Hosting/src/GenericHost/HostingStartupWebHostBuilder.cs3
-rw-r--r--src/Hosting/Hosting/src/Infrastructure/ISupportsStartup.cs3
-rw-r--r--src/Hosting/Hosting/src/Internal/HostingApplicationDiagnostics.cs85
-rw-r--r--src/Hosting/Hosting/src/Internal/UseStartupState.cs18
-rw-r--r--src/Hosting/Hosting/src/Microsoft.AspNetCore.Hosting.csproj3
-rw-r--r--src/Hosting/Hosting/src/StaticWebAssets/StaticWebAssetsLoader.cs2
-rw-r--r--src/Hosting/Hosting/src/WebHostBuilder.cs59
-rw-r--r--src/Hosting/Hosting/src/WebHostBuilderExtensions.cs20
-rw-r--r--src/Http/Http/src/Microsoft.AspNetCore.Http.csproj1
-rw-r--r--src/Servers/Connections.Abstractions/src/Microsoft.AspNetCore.Connections.Abstractions.csproj1
-rw-r--r--src/Shared/StackTrace/StackFrame/StackTraceHelper.cs16
-rw-r--r--src/Shared/StaticWebAssets/ManifestStaticWebAssetFileProvider.cs24
-rw-r--r--src/Tools/Tools.slnf2
17 files changed, 213 insertions, 90 deletions
diff --git a/eng/TrimmableProjects.props b/eng/TrimmableProjects.props
index f6db6bf40d..46255cf5f6 100644
--- a/eng/TrimmableProjects.props
+++ b/eng/TrimmableProjects.props
@@ -8,14 +8,17 @@
<Project>
<ItemGroup>
<TrimmableProject Include="Microsoft.AspNetCore.Hosting.Abstractions" />
+ <TrimmableProject Include="Microsoft.AspNetCore.Hosting" />
<TrimmableProject Include="Microsoft.AspNetCore.Hosting.Server.Abstractions" />
<TrimmableProject Include="Microsoft.Net.Http.Headers" />
<TrimmableProject Include="Microsoft.AspNetCore.Http.Abstractions" />
<TrimmableProject Include="Microsoft.AspNetCore.Http.Extensions" />
<TrimmableProject Include="Microsoft.AspNetCore.Http.Features" />
+ <TrimmableProject Include="Microsoft.AspNetCore.Http" />
<TrimmableProject Include="Microsoft.AspNetCore.Metadata" />
<TrimmableProject Include="Microsoft.AspNetCore.Routing.Abstractions" />
<TrimmableProject Include="Microsoft.AspNetCore.WebUtilities" />
+ <TrimmableProject Include="Microsoft.AspNetCore.Connections.Abstractions" />
<TrimmableProject Include="Microsoft.AspNetCore.Authorization" />
<TrimmableProject Include="Microsoft.AspNetCore.Components.Authorization" />
<TrimmableProject Include="Microsoft.AspNetCore.Components" />
diff --git a/src/Hosting/Abstractions/src/HostingAbstractionsWebHostBuilderExtensions.cs b/src/Hosting/Abstractions/src/HostingAbstractionsWebHostBuilderExtensions.cs
index 1645ddd3fb..36ce56ce49 100644
--- a/src/Hosting/Abstractions/src/HostingAbstractionsWebHostBuilderExtensions.cs
+++ b/src/Hosting/Abstractions/src/HostingAbstractionsWebHostBuilderExtensions.cs
@@ -49,7 +49,7 @@ public static class HostingAbstractionsWebHostBuilderExtensions
/// <param name="hostBuilder">The <see cref="IWebHostBuilder"/> to configure.</param>
/// <param name="startupAssemblyName">The name of the assembly containing the startup type.</param>
/// <returns>The <see cref="IWebHostBuilder"/>.</returns>
- [RequiresUnreferencedCode("Types and members the loaded assembly depends on might be removed.")]
+ [RequiresUnreferencedCode("Finding the startup type in an assembly isn't support. Specify the startup type explicitly in configuration.")]
public static IWebHostBuilder UseStartup(this IWebHostBuilder hostBuilder, string startupAssemblyName)
{
if (startupAssemblyName == null)
diff --git a/src/Hosting/Hosting.slnf b/src/Hosting/Hosting.slnf
index 5c7fc50293..0ef4e18cea 100644
--- a/src/Hosting/Hosting.slnf
+++ b/src/Hosting/Hosting.slnf
@@ -2,6 +2,7 @@
"solution": {
"path": "..\\..\\AspNetCore.sln",
"projects": [
+ "src\\Extensions\\Features\\src\\Microsoft.Extensions.Features.csproj",
"src\\FileProviders\\Embedded\\src\\Microsoft.Extensions.FileProviders.Embedded.csproj",
"src\\Hosting\\Abstractions\\src\\Microsoft.AspNetCore.Hosting.Abstractions.csproj",
"src\\Hosting\\Hosting\\src\\Microsoft.AspNetCore.Hosting.csproj",
@@ -17,7 +18,6 @@
"src\\Hosting\\test\\FunctionalTests\\Microsoft.AspNetCore.Hosting.FunctionalTests.csproj",
"src\\Hosting\\test\\testassets\\IStartupInjectionAssemblyName\\IStartupInjectionAssemblyName.csproj",
"src\\Hosting\\test\\testassets\\TestStartupAssembly1\\TestStartupAssembly1.csproj",
- "src\\Extensions\\Features\\src\\Microsoft.Extensions.Features.csproj",
"src\\Http\\Headers\\src\\Microsoft.Net.Http.Headers.csproj",
"src\\Http\\Http.Abstractions\\src\\Microsoft.AspNetCore.Http.Abstractions.csproj",
"src\\Http\\Http.Extensions\\src\\Microsoft.AspNetCore.Http.Extensions.csproj",
@@ -30,6 +30,7 @@
"src\\Servers\\Connections.Abstractions\\src\\Microsoft.AspNetCore.Connections.Abstractions.csproj",
"src\\Servers\\Kestrel\\Core\\src\\Microsoft.AspNetCore.Server.Kestrel.Core.csproj",
"src\\Servers\\Kestrel\\Kestrel\\src\\Microsoft.AspNetCore.Server.Kestrel.csproj",
+ "src\\Servers\\Kestrel\\Transport.Quic\\src\\Microsoft.AspNetCore.Server.Kestrel.Transport.Quic.csproj",
"src\\Servers\\Kestrel\\Transport.Sockets\\src\\Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets.csproj",
"src\\Testing\\src\\Microsoft.AspNetCore.Testing.csproj"
]
diff --git a/src/Hosting/Hosting/src/GenericHost/GenericWebHostBuilder.cs b/src/Hosting/Hosting/src/GenericHost/GenericWebHostBuilder.cs
index ac601aab49..9998cf8da0 100644
--- a/src/Hosting/Hosting/src/GenericHost/GenericWebHostBuilder.cs
+++ b/src/Hosting/Hosting/src/GenericHost/GenericWebHostBuilder.cs
@@ -97,28 +97,34 @@ internal sealed class GenericWebHostBuilder : IWebHostBuilder, ISupportsStartup,
// Support UseStartup(assemblyName)
if (!string.IsNullOrEmpty(webHostOptions.StartupAssembly))
{
- try
- {
- var startupType = StartupLoader.FindStartupType(webHostOptions.StartupAssembly, webhostContext.HostingEnvironment.EnvironmentName);
- UseStartup(startupType, context, services);
- }
- catch (Exception ex) when (webHostOptions.CaptureStartupErrors)
- {
- var capture = ExceptionDispatchInfo.Capture(ex);
-
- services.Configure<GenericWebHostServiceOptions>(options =>
- {
- options.ConfigureApplication = app =>
- {
- // Throw if there was any errors initializing startup
- capture.Throw();
- };
- });
- }
+ ScanAssemblyAndRegisterStartup(context, services, webhostContext, webHostOptions);
}
});
}
+ [UnconditionalSuppressMessage("Trimmer", "IL2072", Justification = "Finding startup type in assembly requires unreferenced code. Surfaced to user in UseStartup(assemblyName).")]
+ private void ScanAssemblyAndRegisterStartup(HostBuilderContext context, IServiceCollection services, WebHostBuilderContext webhostContext, WebHostOptions webHostOptions)
+ {
+ try
+ {
+ var startupType = StartupLoader.FindStartupType(webHostOptions.StartupAssembly!, webhostContext.HostingEnvironment.EnvironmentName);
+ UseStartup(startupType, context, services);
+ }
+ catch (Exception ex) when (webHostOptions.CaptureStartupErrors)
+ {
+ var capture = ExceptionDispatchInfo.Capture(ex);
+
+ services.Configure<GenericWebHostServiceOptions>(options =>
+ {
+ options.ConfigureApplication = app =>
+ {
+ // Throw if there was any errors initializing startup
+ capture.Throw();
+ };
+ });
+ }
+ }
+
private void ExecuteHostingStartups()
{
var webHostOptions = new WebHostOptions(_config);
@@ -219,19 +225,22 @@ internal sealed class GenericWebHostBuilder : IWebHostBuilder, ISupportsStartup,
// UseStartup can be called multiple times. Only run the last one.
_startupObject = startupType;
+ var state = new UseStartupState(startupType);
+
_builder.ConfigureServices((context, services) =>
{
// Run this delegate if the startup type matches
- if (object.ReferenceEquals(_startupObject, startupType))
+ if (object.ReferenceEquals(_startupObject, state.StartupType))
{
- UseStartup(startupType, context, services);
+ UseStartup(state.StartupType, context, services);
}
});
return this;
}
- public IWebHostBuilder UseStartup<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)] TStartup>(Func<WebHostBuilderContext, TStartup> startupFactory)
+ [RequiresUnreferencedCode("Startup type created by factory can't be determined statically. Specify the startup type explicitly in configuration.")]
+ public IWebHostBuilder UseStartup<TStartup>(Func<WebHostBuilderContext, TStartup> startupFactory)
{
var startupAssemblyName = startupFactory.GetMethodInfo().DeclaringType!.Assembly.GetName().Name;
@@ -240,7 +249,10 @@ internal sealed class GenericWebHostBuilder : IWebHostBuilder, ISupportsStartup,
// Clear the startup type
_startupObject = startupFactory;
- _builder.ConfigureServices((context, services) =>
+ _builder.ConfigureServices(ConfigureStartup);
+
+ [UnconditionalSuppressMessage("Trimmer", "IL2072", Justification = "Startup type created by factory can't be determined statically.")]
+ void ConfigureStartup(HostBuilderContext context, IServiceCollection services)
{
// UseStartup can be called multiple times. Only run the last one.
if (object.ReferenceEquals(_startupObject, startupFactory))
@@ -249,7 +261,7 @@ internal sealed class GenericWebHostBuilder : IWebHostBuilder, ISupportsStartup,
var instance = startupFactory(webHostBuilderContext) ?? throw new InvalidOperationException("The specified factory returned null startup instance.");
UseStartup(instance.GetType(), context, services, instance);
}
- });
+ }
return this;
}
diff --git a/src/Hosting/Hosting/src/GenericHost/HostingStartupWebHostBuilder.cs b/src/Hosting/Hosting/src/GenericHost/HostingStartupWebHostBuilder.cs
index 54b1271bcc..294e3ca6b8 100644
--- a/src/Hosting/Hosting/src/GenericHost/HostingStartupWebHostBuilder.cs
+++ b/src/Hosting/Hosting/src/GenericHost/HostingStartupWebHostBuilder.cs
@@ -83,7 +83,8 @@ internal sealed class HostingStartupWebHostBuilder : IWebHostBuilder, ISupportsS
return _builder.UseStartup(startupType);
}
- public IWebHostBuilder UseStartup<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)] TStartup>(Func<WebHostBuilderContext, TStartup> startupFactory)
+ [RequiresUnreferencedCode("Startup type created by factory can't be determined statically. Specify the startup type explicitly in configuration.")]
+ public IWebHostBuilder UseStartup<TStartup>(Func<WebHostBuilderContext, TStartup> startupFactory)
{
return _builder.UseStartup(startupFactory);
}
diff --git a/src/Hosting/Hosting/src/Infrastructure/ISupportsStartup.cs b/src/Hosting/Hosting/src/Infrastructure/ISupportsStartup.cs
index cf4dedf93e..bc67d4a8ee 100644
--- a/src/Hosting/Hosting/src/Infrastructure/ISupportsStartup.cs
+++ b/src/Hosting/Hosting/src/Infrastructure/ISupportsStartup.cs
@@ -41,5 +41,6 @@ public interface ISupportsStartup
/// <param name="startupFactory">A delegate that specifies a factory for the startup class.</param>
/// <returns>The <see cref="IWebHostBuilder"/>.</returns>
/// <remarks>When using the IL linker, all public methods of <typeparamref name="TStartup"/> are preserved. This should match the Startup type directly (and not a base type).</remarks>
- IWebHostBuilder UseStartup<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)] TStartup>(Func<WebHostBuilderContext, TStartup> startupFactory);
+ [RequiresUnreferencedCode("Startup type created by factory can't be determined statically. Specify the startup type explicitly in configuration.")]
+ IWebHostBuilder UseStartup<TStartup>(Func<WebHostBuilderContext, TStartup> startupFactory);
}
diff --git a/src/Hosting/Hosting/src/Internal/HostingApplicationDiagnostics.cs b/src/Hosting/Hosting/src/Internal/HostingApplicationDiagnostics.cs
index 2085fd970b..32183ebc84 100644
--- a/src/Hosting/Hosting/src/Internal/HostingApplicationDiagnostics.cs
+++ b/src/Hosting/Hosting/src/Internal/HostingApplicationDiagnostics.cs
@@ -3,6 +3,7 @@
using System.Collections;
using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.Runtime.CompilerServices;
using Microsoft.AspNetCore.Http;
@@ -221,41 +222,83 @@ internal class HostingApplicationDiagnostics
}
}
+ [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026",
+ Justification = "The values being passed into Write have the commonly used properties being preserved with DynamicDependency.")]
+ private static void WriteDiagnosticEvent<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties)] TValue>(
+ DiagnosticSource diagnosticSource, string name, TValue value)
+ {
+ diagnosticSource.Write(name, value);
+ }
+
[MethodImpl(MethodImplOptions.NoInlining)]
private void RecordBeginRequestDiagnostics(HttpContext httpContext, long startTimestamp)
{
- _diagnosticListener.Write(
+ WriteDiagnosticEvent(
+ _diagnosticListener,
DeprecatedDiagnosticsBeginRequestKey,
- new
- {
- httpContext = httpContext,
- timestamp = startTimestamp
- });
+ new DeprecatedRequestData(httpContext, startTimestamp));
}
[MethodImpl(MethodImplOptions.NoInlining)]
private void RecordEndRequestDiagnostics(HttpContext httpContext, long currentTimestamp)
{
- _diagnosticListener.Write(
+ WriteDiagnosticEvent(
+ _diagnosticListener,
DeprecatedDiagnosticsEndRequestKey,
- new
- {
- httpContext = httpContext,
- timestamp = currentTimestamp
- });
+ new DeprecatedRequestData(httpContext, currentTimestamp));
}
[MethodImpl(MethodImplOptions.NoInlining)]
private void RecordUnhandledExceptionDiagnostics(HttpContext httpContext, long currentTimestamp, Exception exception)
{
- _diagnosticListener.Write(
+ WriteDiagnosticEvent(
+ _diagnosticListener,
DiagnosticsUnhandledExceptionKey,
- new
- {
- httpContext = httpContext,
- timestamp = currentTimestamp,
- exception = exception
- });
+ new UnhandledExceptionData(httpContext, currentTimestamp, exception));
+ }
+
+ private sealed class DeprecatedRequestData
+ {
+ // Common properties. Properties not in this list could be trimmed.
+ [DynamicDependency(nameof(HttpContext.Request), typeof(HttpContext))]
+ [DynamicDependency(nameof(HttpContext.Response), typeof(HttpContext))]
+ [DynamicDependency(nameof(HttpRequest.Path), typeof(HttpRequest))]
+ [DynamicDependency(nameof(HttpRequest.Method), typeof(HttpRequest))]
+ [DynamicDependency(nameof(HttpResponse.StatusCode), typeof(HttpResponse))]
+ internal DeprecatedRequestData(HttpContext httpContext, long timestamp)
+ {
+ this.httpContext = httpContext;
+ this.timestamp = timestamp;
+ }
+
+ // Compatibility with anonymous object property names
+ public HttpContext httpContext { get; }
+ public long timestamp { get; }
+
+ public override string ToString() => $"{{ {nameof(httpContext)} = {httpContext}, {nameof(timestamp)} = {timestamp} }}";
+ }
+
+ private sealed class UnhandledExceptionData
+ {
+ // Common properties. Properties not in this list could be trimmed.
+ [DynamicDependency(nameof(HttpContext.Request), typeof(HttpContext))]
+ [DynamicDependency(nameof(HttpContext.Response), typeof(HttpContext))]
+ [DynamicDependency(nameof(HttpRequest.Path), typeof(HttpRequest))]
+ [DynamicDependency(nameof(HttpRequest.Method), typeof(HttpRequest))]
+ [DynamicDependency(nameof(HttpResponse.StatusCode), typeof(HttpResponse))]
+ internal UnhandledExceptionData(HttpContext httpContext, long timestamp, Exception exception)
+ {
+ this.httpContext = httpContext;
+ this.timestamp = timestamp;
+ this.exception = exception;
+ }
+
+ // Compatibility with anonymous object property names
+ public HttpContext httpContext { get; }
+ public long timestamp { get; }
+ public Exception exception { get; }
+
+ public override string ToString() => $"{{ {nameof(httpContext)} = {httpContext}, {nameof(timestamp)} = {timestamp}, {nameof(exception)} = {exception} }}";
}
[MethodImpl(MethodImplOptions.NoInlining)]
@@ -347,7 +390,7 @@ internal class HostingApplicationDiagnostics
private Activity StartActivity(Activity activity, HttpContext httpContext)
{
activity.Start();
- _diagnosticListener.Write(ActivityStartKey, httpContext);
+ WriteDiagnosticEvent(_diagnosticListener, ActivityStartKey, httpContext);
return activity;
}
@@ -359,7 +402,7 @@ internal class HostingApplicationDiagnostics
{
activity.SetEndTime(DateTime.UtcNow);
}
- _diagnosticListener.Write(ActivityStopKey, httpContext);
+ WriteDiagnosticEvent(_diagnosticListener, ActivityStopKey, httpContext);
activity.Stop(); // Resets Activity.Current (we want this after the Write)
}
diff --git a/src/Hosting/Hosting/src/Internal/UseStartupState.cs b/src/Hosting/Hosting/src/Internal/UseStartupState.cs
new file mode 100644
index 0000000000..954feaea4d
--- /dev/null
+++ b/src/Hosting/Hosting/src/Internal/UseStartupState.cs
@@ -0,0 +1,18 @@
+// 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;
+
+namespace Microsoft.AspNetCore.Hosting.Internal;
+
+// Workaround for linker bug: https://github.com/dotnet/linker/issues/1981
+internal readonly struct UseStartupState
+{
+ public UseStartupState([DynamicallyAccessedMembers(StartupLinkerOptions.Accessibility)] Type startupType)
+ {
+ StartupType = startupType;
+ }
+
+ [DynamicallyAccessedMembers(StartupLinkerOptions.Accessibility)]
+ public Type StartupType { get; }
+}
diff --git a/src/Hosting/Hosting/src/Microsoft.AspNetCore.Hosting.csproj b/src/Hosting/Hosting/src/Microsoft.AspNetCore.Hosting.csproj
index ffd5b45ef3..3d90a8102d 100644
--- a/src/Hosting/Hosting/src/Microsoft.AspNetCore.Hosting.csproj
+++ b/src/Hosting/Hosting/src/Microsoft.AspNetCore.Hosting.csproj
@@ -1,4 +1,4 @@
-<Project Sdk="Microsoft.NET.Sdk">
+<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<Description>ASP.NET Core hosting infrastructure and startup logic for web applications.</Description>
@@ -8,6 +8,7 @@
<PackageTags>aspnetcore;hosting</PackageTags>
<IsPackable>false</IsPackable>
<Nullable>enable</Nullable>
+ <Trimmable>true</Trimmable>
</PropertyGroup>
<ItemGroup>
diff --git a/src/Hosting/Hosting/src/StaticWebAssets/StaticWebAssetsLoader.cs b/src/Hosting/Hosting/src/StaticWebAssets/StaticWebAssetsLoader.cs
index f71b8f65c7..ff097eca5e 100644
--- a/src/Hosting/Hosting/src/StaticWebAssets/StaticWebAssetsLoader.cs
+++ b/src/Hosting/Hosting/src/StaticWebAssets/StaticWebAssetsLoader.cs
@@ -46,7 +46,7 @@ public class StaticWebAssetsLoader
{
try
{
- var candidate = configuration.GetValue<string>(WebHostDefaults.StaticWebAssetsKey) ?? ResolveRelativeToAssembly(environment);
+ var candidate = configuration[WebHostDefaults.StaticWebAssetsKey] ?? ResolveRelativeToAssembly(environment);
if (candidate != null && File.Exists(candidate))
{
return File.OpenRead(candidate);
diff --git a/src/Hosting/Hosting/src/WebHostBuilder.cs b/src/Hosting/Hosting/src/WebHostBuilder.cs
index 0fb6538653..2598ae6f08 100644
--- a/src/Hosting/Hosting/src/WebHostBuilder.cs
+++ b/src/Hosting/Hosting/src/WebHostBuilder.cs
@@ -301,38 +301,47 @@ public class WebHostBuilder : IWebHostBuilder
if (!string.IsNullOrEmpty(_options.StartupAssembly))
{
- try
+ ScanAssemblyAndRegisterStartup(services, _options.StartupAssembly);
+ }
+
+ _configureServices?.Invoke(_context, services);
+
+ return services;
+ }
+
+ [UnconditionalSuppressMessage("Trimmer", "IL2077", Justification = "Finding startup type in assembly requires unreferenced code. Surfaced to user in UseStartup(startupAssemblyName).")]
+ private void ScanAssemblyAndRegisterStartup(ServiceCollection services, string startupAssemblyName)
+ {
+ try
+ {
+ var startupType = StartupLoader.FindStartupType(startupAssemblyName, _hostingEnvironment.EnvironmentName);
+
+ if (typeof(IStartup).IsAssignableFrom(startupType))
+ {
+ services.AddSingleton(typeof(IStartup), startupType);
+ }
+ else
{
- var startupType = StartupLoader.FindStartupType(_options.StartupAssembly, _hostingEnvironment.EnvironmentName);
+ services.AddSingleton(typeof(IStartup), RegisterStartup);
- if (typeof(IStartup).IsAssignableFrom(startupType))
- {
- services.AddSingleton(typeof(IStartup), startupType);
- }
- else
+ [UnconditionalSuppressMessage("Trimmer", "IL2077", Justification = "Finding startup type in assembly requires unreferenced code. Surfaced to user in UseStartup(startupAssemblyName).")]
+ object RegisterStartup(IServiceProvider serviceProvider)
{
- services.AddSingleton(typeof(IStartup), sp =>
- {
- var hostingEnvironment = sp.GetRequiredService<IHostEnvironment>();
- var methods = StartupLoader.LoadMethods(sp, startupType, hostingEnvironment.EnvironmentName);
- return new ConventionBasedStartup(methods);
- });
+ var hostingEnvironment = serviceProvider.GetRequiredService<IHostEnvironment>();
+ var methods = StartupLoader.LoadMethods(serviceProvider, startupType, hostingEnvironment.EnvironmentName);
+ return new ConventionBasedStartup(methods);
}
}
- catch (Exception ex)
+ }
+ catch (Exception ex)
+ {
+ var capture = ExceptionDispatchInfo.Capture(ex);
+ services.AddSingleton<IStartup>(_ =>
{
- var capture = ExceptionDispatchInfo.Capture(ex);
- services.AddSingleton<IStartup>(_ =>
- {
- capture.Throw();
- return null;
- });
- }
+ capture.Throw();
+ return null;
+ });
}
-
- _configureServices?.Invoke(_context, services);
-
- return services;
}
private static void AddApplicationServices(IServiceCollection services, IServiceProvider hostingServiceProvider)
diff --git a/src/Hosting/Hosting/src/WebHostBuilderExtensions.cs b/src/Hosting/Hosting/src/WebHostBuilderExtensions.cs
index 1e5ddb6efc..1a67283754 100644
--- a/src/Hosting/Hosting/src/WebHostBuilderExtensions.cs
+++ b/src/Hosting/Hosting/src/WebHostBuilderExtensions.cs
@@ -93,6 +93,7 @@ public static class WebHostBuilderExtensions
/// <param name="startupFactory">A delegate that specifies a factory for the startup class.</param>
/// <returns>The <see cref="IWebHostBuilder"/>.</returns>
/// <remarks>When using the il linker, all public methods of <typeparamref name="TStartup"/> are preserved. This should match the Startup type directly (and not a base type).</remarks>
+ [RequiresUnreferencedCode("Startup type created by factory can't be determined statically. Specify the startup type explicitly in configuration.")]
public static IWebHostBuilder UseStartup<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)] TStartup>(this IWebHostBuilder hostBuilder, Func<WebHostBuilderContext, TStartup> startupFactory) where TStartup : class
{
if (startupFactory == null)
@@ -113,11 +114,14 @@ public static class WebHostBuilderExtensions
return hostBuilder
.ConfigureServices((context, services) =>
{
- services.AddSingleton(typeof(IStartup), sp =>
+ services.AddSingleton(typeof(IStartup), GetStartupInstance);
+
+ [UnconditionalSuppressMessage("Trimmer", "IL2072", Justification = "Startup type created by factory can't be determined statically.")]
+ object GetStartupInstance(IServiceProvider serviceProvider)
{
var instance = startupFactory(context) ?? throw new InvalidOperationException("The specified factory returned null startup instance.");
- var hostingEnvironment = sp.GetRequiredService<IHostEnvironment>();
+ var hostingEnvironment = serviceProvider.GetRequiredService<IHostEnvironment>();
// Check if the instance implements IStartup before wrapping
if (instance is IStartup startup)
@@ -125,8 +129,8 @@ public static class WebHostBuilderExtensions
return startup;
}
- return new ConventionBasedStartup(StartupLoader.LoadMethods(sp, instance.GetType(), hostingEnvironment.EnvironmentName, instance));
- });
+ return new ConventionBasedStartup(StartupLoader.LoadMethods(serviceProvider, instance.GetType(), hostingEnvironment.EnvironmentName, instance));
+ }
});
}
@@ -153,19 +157,21 @@ public static class WebHostBuilderExtensions
hostBuilder.UseSetting(WebHostDefaults.ApplicationKey, startupAssemblyName);
+ var state = new UseStartupState(startupType);
+
return hostBuilder
.ConfigureServices(services =>
{
- if (typeof(IStartup).IsAssignableFrom(startupType))
+ if (typeof(IStartup).IsAssignableFrom(state.StartupType))
{
- services.AddSingleton(typeof(IStartup), startupType);
+ services.AddSingleton(typeof(IStartup), state.StartupType);
}
else
{
services.AddSingleton(typeof(IStartup), sp =>
{
var hostingEnvironment = sp.GetRequiredService<IHostEnvironment>();
- return new ConventionBasedStartup(StartupLoader.LoadMethods(sp, startupType, hostingEnvironment.EnvironmentName));
+ return new ConventionBasedStartup(StartupLoader.LoadMethods(sp, state.StartupType, hostingEnvironment.EnvironmentName));
});
}
});
diff --git a/src/Http/Http/src/Microsoft.AspNetCore.Http.csproj b/src/Http/Http/src/Microsoft.AspNetCore.Http.csproj
index 6213aca587..d03f2d43cf 100644
--- a/src/Http/Http/src/Microsoft.AspNetCore.Http.csproj
+++ b/src/Http/Http/src/Microsoft.AspNetCore.Http.csproj
@@ -9,6 +9,7 @@
<PackageTags>aspnetcore</PackageTags>
<IsPackable>false</IsPackable>
<Nullable>enable</Nullable>
+ <Trimmable>true</Trimmable>
</PropertyGroup>
<ItemGroup>
diff --git a/src/Servers/Connections.Abstractions/src/Microsoft.AspNetCore.Connections.Abstractions.csproj b/src/Servers/Connections.Abstractions/src/Microsoft.AspNetCore.Connections.Abstractions.csproj
index 3617380371..8a853af7a4 100644
--- a/src/Servers/Connections.Abstractions/src/Microsoft.AspNetCore.Connections.Abstractions.csproj
+++ b/src/Servers/Connections.Abstractions/src/Microsoft.AspNetCore.Connections.Abstractions.csproj
@@ -8,6 +8,7 @@
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<PackageTags>aspnetcore</PackageTags>
<Nullable>enable</Nullable>
+ <Trimmable>true</Trimmable>
</PropertyGroup>
<ItemGroup>
diff --git a/src/Shared/StackTrace/StackFrame/StackTraceHelper.cs b/src/Shared/StackTrace/StackFrame/StackTraceHelper.cs
index 93b3b667d0..4c0ce8c3c7 100644
--- a/src/Shared/StackTrace/StackFrame/StackTraceHelper.cs
+++ b/src/Shared/StackTrace/StackFrame/StackTraceHelper.cs
@@ -5,6 +5,7 @@ using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
@@ -16,6 +17,7 @@ namespace Microsoft.Extensions.StackTrace.Sources;
internal class StackTraceHelper
{
+ [UnconditionalSuppressMessage("Trimmer", "IL2026", Justification = "MethodInfo for a stack frame might be incomplete or removed. GetFrames does the best it can to provide frame details.")]
public static IList<StackFrameInfo> GetFrames(Exception exception, out AggregateException? error)
{
if (exception == null)
@@ -43,13 +45,20 @@ internal class StackTraceHelper
var frame = stackFrames[i];
var method = frame.GetMethod();
+ // It seems like a MethodInfo should always be available for methods in the stack,
+ // but double check we have one for trimmed apps.
+ if (method == null)
+ {
+ continue;
+ }
+
// Always show last stackFrame
if (!ShowInStackTrace(method) && i < stackFrames.Length - 1)
{
continue;
}
- var stackFrame = new StackFrameInfo(frame.GetFileLineNumber(), frame.GetFileName(), frame, GetMethodDisplayString(frame.GetMethod()));
+ var stackFrame = new StackFrameInfo(frame.GetFileLineNumber(), frame.GetFileName(), frame, GetMethodDisplayString(method));
frames.Add(stackFrame);
}
@@ -140,10 +149,8 @@ internal class StackTraceHelper
return methodDisplayInfo;
}
- private static bool ShowInStackTrace(MethodBase? method)
+ private static bool ShowInStackTrace(MethodBase method)
{
- Debug.Assert(method != null);
-
// Don't show any methods marked with the StackTraceHiddenAttribute
// https://github.com/dotnet/coreclr/pull/14652
if (HasStackTraceHiddenAttribute(method))
@@ -185,6 +192,7 @@ internal class StackTraceHelper
return true;
}
+ [UnconditionalSuppressMessage("Trimmer", "IL2075", Justification = "Unable to require a method has all information on it to resolve state machine.")]
private static bool TryResolveStateMachineMethod(ref MethodBase method, out Type? declaringType)
{
Debug.Assert(method != null);
diff --git a/src/Shared/StaticWebAssets/ManifestStaticWebAssetFileProvider.cs b/src/Shared/StaticWebAssets/ManifestStaticWebAssetFileProvider.cs
index 65cd301d67..45aa301118 100644
--- a/src/Shared/StaticWebAssets/ManifestStaticWebAssetFileProvider.cs
+++ b/src/Shared/StaticWebAssets/ManifestStaticWebAssetFileProvider.cs
@@ -11,7 +11,7 @@ using Microsoft.Extensions.Primitives;
namespace Microsoft.AspNetCore.StaticWebAssets;
-internal sealed class ManifestStaticWebAssetFileProvider : IFileProvider
+internal sealed partial class ManifestStaticWebAssetFileProvider : IFileProvider
{
private static readonly StringComparison _fsComparison = OperatingSystem.IsWindows() ?
StringComparison.OrdinalIgnoreCase :
@@ -322,10 +322,23 @@ internal sealed class ManifestStaticWebAssetFileProvider : IFileProvider
internal static StaticWebAssetManifest Parse(Stream manifest)
{
- return JsonSerializer.Deserialize<StaticWebAssetManifest>(manifest)!;
+ return JsonSerializer.Deserialize(
+ manifest,
+ SourceGenerationContext.DefaultWithConverter.StaticWebAssetManifest)!;
}
}
+ [JsonSourceGenerationOptions]
+ [JsonSerializable(typeof(StaticWebAssetManifest))]
+ [JsonSerializable(typeof(IDictionary<string, StaticWebAssetNode>))]
+ internal partial class SourceGenerationContext : JsonSerializerContext
+ {
+ public static readonly SourceGenerationContext DefaultWithConverter = new SourceGenerationContext(new JsonSerializerOptions
+ {
+ Converters = { new OSBasedCaseConverter() }
+ });
+ }
+
internal sealed class StaticWebAssetNode
{
[JsonPropertyName("Asset")]
@@ -366,7 +379,10 @@ internal sealed class ManifestStaticWebAssetFileProvider : IFileProvider
{
public override Dictionary<string, StaticWebAssetNode> Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
- var parsed = JsonSerializer.Deserialize<IDictionary<string, StaticWebAssetNode>>(ref reader, options)!;
+ // Need to recursively deserialize `Dictionary<string, StaticWebAssetNode>` but can't deserialize
+ // that type directly because this converter will call into itself and stackoverflow.
+ // Workaround is to deserialize to IDictionary, and then perform custom convert logic on the result.
+ var parsed = JsonSerializer.Deserialize(ref reader, SourceGenerationContext.DefaultWithConverter.IDictionaryStringStaticWebAssetNode)!;
var result = new Dictionary<string, StaticWebAssetNode>(StaticWebAssetManifest.PathComparer);
MergeChildren(parsed, result);
return result;
@@ -422,7 +438,7 @@ internal sealed class ManifestStaticWebAssetFileProvider : IFileProvider
public override void Write(Utf8JsonWriter writer, Dictionary<string, StaticWebAssetNode> value, JsonSerializerOptions options)
{
- JsonSerializer.Serialize(writer, value, options);
+ throw new NotSupportedException();
}
}
}
diff --git a/src/Tools/Tools.slnf b/src/Tools/Tools.slnf
index 3db571352b..3b15716bb2 100644
--- a/src/Tools/Tools.slnf
+++ b/src/Tools/Tools.slnf
@@ -12,9 +12,11 @@
"src\\Components\\Web\\src\\Microsoft.AspNetCore.Components.Web.csproj",
"src\\Extensions\\Features\\src\\Microsoft.Extensions.Features.csproj",
"src\\Hosting\\Abstractions\\src\\Microsoft.AspNetCore.Hosting.Abstractions.csproj",
+ "src\\Hosting\\Hosting\\src\\Microsoft.AspNetCore.Hosting.csproj",
"src\\Hosting\\Server.Abstractions\\src\\Microsoft.AspNetCore.Hosting.Server.Abstractions.csproj",
"src\\Http\\Headers\\src\\Microsoft.Net.Http.Headers.csproj",
"src\\Http\\Http.Abstractions\\src\\Microsoft.AspNetCore.Http.Abstractions.csproj",
+ "src\\Http\\Http.Extensions\\src\\Microsoft.AspNetCore.Http.Extensions.csproj",
"src\\Http\\Http.Features\\src\\Microsoft.AspNetCore.Http.Features.csproj",
"src\\Http\\Http\\src\\Microsoft.AspNetCore.Http.csproj",
"src\\Http\\Metadata\\src\\Microsoft.AspNetCore.Metadata.csproj",