@@ -86,6 +86,97 @@ internal WebApplicationBuilder(WebApplicationOptions options, Action<IHostBuilde
86
86
WebHost = new ConfigureWebHostBuilder ( webHostContext , Configuration , Services ) ;
87
87
}
88
88
89
+ internal WebApplicationBuilder ( WebApplicationOptions options , bool slim , Action < IHostBuilder > ? configureDefaults = null )
90
+ {
91
+ Debug . Assert ( slim , "should only be called with slim: true" ) ;
92
+
93
+ var configuration = new ConfigurationManager ( ) ;
94
+
95
+ configuration . AddEnvironmentVariables ( prefix : "ASPNETCORE_" ) ;
96
+
97
+ // add the default host configuration sources, so they are picked up by the HostApplicationBuilder constructor.
98
+ // These won't be added by HostApplicationBuilder since DisableDefaults = true.
99
+ configuration . AddEnvironmentVariables ( prefix : "DOTNET_" ) ;
100
+ if ( options . Args is { Length : > 0 } args )
101
+ {
102
+ configuration . AddCommandLine ( args ) ;
103
+ }
104
+
105
+ _hostApplicationBuilder = new HostApplicationBuilder ( new HostApplicationBuilderSettings
106
+ {
107
+ DisableDefaults = true ,
108
+ Args = options . Args ,
109
+ ApplicationName = options . ApplicationName ,
110
+ EnvironmentName = options . EnvironmentName ,
111
+ ContentRootPath = options . ContentRootPath ,
112
+ Configuration = configuration ,
113
+ } ) ;
114
+
115
+ // configure the ServiceProviderOptions here since DisableDefaults = true means HostApplicationBuilder won't.
116
+ var serviceProviderFactory = GetServiceProviderFactory ( _hostApplicationBuilder ) ;
117
+ _hostApplicationBuilder . ConfigureContainer ( serviceProviderFactory ) ;
118
+
119
+ // Set WebRootPath if necessary
120
+ if ( options . WebRootPath is not null )
121
+ {
122
+ Configuration . AddInMemoryCollection ( new [ ]
123
+ {
124
+ new KeyValuePair < string , string ? > ( WebHostDefaults . WebRootKey , options . WebRootPath ) ,
125
+ } ) ;
126
+ }
127
+
128
+ // Run methods to configure web host defaults early to populate services
129
+ var bootstrapHostBuilder = new BootstrapHostBuilder ( _hostApplicationBuilder ) ;
130
+
131
+ // This is for testing purposes
132
+ configureDefaults ? . Invoke ( bootstrapHostBuilder ) ;
133
+
134
+ bootstrapHostBuilder . ConfigureSlimWebHost (
135
+ webHostBuilder =>
136
+ {
137
+ AspNetCore . WebHost . UseKestrel ( webHostBuilder ) ;
138
+
139
+ webHostBuilder . Configure ( ConfigureEmptyApplication ) ;
140
+
141
+ webHostBuilder . UseSetting ( WebHostDefaults . ApplicationKey , _hostApplicationBuilder . Environment . ApplicationName ?? "" ) ;
142
+ webHostBuilder . UseSetting ( WebHostDefaults . PreventHostingStartupKey , Configuration [ WebHostDefaults . PreventHostingStartupKey ] ) ;
143
+ webHostBuilder . UseSetting ( WebHostDefaults . HostingStartupAssembliesKey , Configuration [ WebHostDefaults . HostingStartupAssembliesKey ] ) ;
144
+ webHostBuilder . UseSetting ( WebHostDefaults . HostingStartupExcludeAssembliesKey , Configuration [ WebHostDefaults . HostingStartupExcludeAssembliesKey ] ) ;
145
+ } ,
146
+ options =>
147
+ {
148
+ // We've already applied "ASPNETCORE_" environment variables to hosting config
149
+ options . SuppressEnvironmentConfiguration = true ;
150
+ } ) ;
151
+
152
+ // This applies the config from ConfigureWebHostDefaults
153
+ // Grab the GenericWebHostService ServiceDescriptor so we can append it after any user-added IHostedServices during Build();
154
+ _genericWebHostServiceDescriptor = bootstrapHostBuilder . RunDefaultCallbacks ( ) ;
155
+
156
+ // Grab the WebHostBuilderContext from the property bag to use in the ConfigureWebHostBuilder. Then
157
+ // grab the IWebHostEnvironment from the webHostContext. This also matches the instance in the IServiceCollection.
158
+ var webHostContext = ( WebHostBuilderContext ) bootstrapHostBuilder . Properties [ typeof ( WebHostBuilderContext ) ] ;
159
+ Environment = webHostContext . HostingEnvironment ;
160
+
161
+ Host = new ConfigureHostBuilder ( bootstrapHostBuilder . Context , Configuration , Services ) ;
162
+ WebHost = new ConfigureWebHostBuilder ( webHostContext , Configuration , Services ) ;
163
+ }
164
+
165
+ private static DefaultServiceProviderFactory GetServiceProviderFactory ( HostApplicationBuilder hostApplicationBuilder )
166
+ {
167
+ if ( hostApplicationBuilder . Environment . IsDevelopment ( ) )
168
+ {
169
+ return new DefaultServiceProviderFactory (
170
+ new ServiceProviderOptions
171
+ {
172
+ ValidateScopes = true ,
173
+ ValidateOnBuild = true ,
174
+ } ) ;
175
+ }
176
+
177
+ return new DefaultServiceProviderFactory ( ) ;
178
+ }
179
+
89
180
/// <summary>
90
181
/// Provides information about the web hosting environment an application is running.
91
182
/// </summary>
@@ -133,6 +224,46 @@ public WebApplication Build()
133
224
}
134
225
135
226
private void ConfigureApplication ( WebHostBuilderContext context , IApplicationBuilder app )
227
+ {
228
+ ConfigureApplicationCore (
229
+ context ,
230
+ app ,
231
+ processAuthMiddlewares : ( ) =>
232
+ {
233
+ Debug . Assert ( _builtApplication is not null ) ;
234
+
235
+ // Process authorization and authentication middlewares independently to avoid
236
+ // registering middlewares for services that do not exist
237
+ var serviceProviderIsService = _builtApplication . Services . GetService < IServiceProviderIsService > ( ) ;
238
+ if ( serviceProviderIsService ? . IsService ( typeof ( IAuthenticationSchemeProvider ) ) is true )
239
+ {
240
+ // Don't add more than one instance of the middleware
241
+ if ( ! _builtApplication . Properties . ContainsKey ( AuthenticationMiddlewareSetKey ) )
242
+ {
243
+ // The Use invocations will set the property on the outer pipeline,
244
+ // but we want to set it on the inner pipeline as well.
245
+ _builtApplication . Properties [ AuthenticationMiddlewareSetKey ] = true ;
246
+ app . UseAuthentication ( ) ;
247
+ }
248
+ }
249
+
250
+ if ( serviceProviderIsService ? . IsService ( typeof ( IAuthorizationHandlerProvider ) ) is true )
251
+ {
252
+ if ( ! _builtApplication . Properties . ContainsKey ( AuthorizationMiddlewareSetKey ) )
253
+ {
254
+ _builtApplication . Properties [ AuthorizationMiddlewareSetKey ] = true ;
255
+ app . UseAuthorization ( ) ;
256
+ }
257
+ }
258
+ } ) ;
259
+ }
260
+
261
+ private void ConfigureEmptyApplication ( WebHostBuilderContext context , IApplicationBuilder app )
262
+ {
263
+ ConfigureApplicationCore ( context , app , processAuthMiddlewares : null ) ;
264
+ }
265
+
266
+ private void ConfigureApplicationCore ( WebHostBuilderContext context , IApplicationBuilder app , Action ? processAuthMiddlewares )
136
267
{
137
268
Debug . Assert ( _builtApplication is not null ) ;
138
269
@@ -173,29 +304,7 @@ private void ConfigureApplication(WebHostBuilderContext context, IApplicationBui
173
304
}
174
305
}
175
306
176
- // Process authorization and authentication middlewares independently to avoid
177
- // registering middlewares for services that do not exist
178
- var serviceProviderIsService = _builtApplication . Services . GetService < IServiceProviderIsService > ( ) ;
179
- if ( serviceProviderIsService ? . IsService ( typeof ( IAuthenticationSchemeProvider ) ) is true )
180
- {
181
- // Don't add more than one instance of the middleware
182
- if ( ! _builtApplication . Properties . ContainsKey ( AuthenticationMiddlewareSetKey ) )
183
- {
184
- // The Use invocations will set the property on the outer pipeline,
185
- // but we want to set it on the inner pipeline as well.
186
- _builtApplication . Properties [ AuthenticationMiddlewareSetKey ] = true ;
187
- app . UseAuthentication ( ) ;
188
- }
189
- }
190
-
191
- if ( serviceProviderIsService ? . IsService ( typeof ( IAuthorizationHandlerProvider ) ) is true )
192
- {
193
- if ( ! _builtApplication . Properties . ContainsKey ( AuthorizationMiddlewareSetKey ) )
194
- {
195
- _builtApplication . Properties [ AuthorizationMiddlewareSetKey ] = true ;
196
- app . UseAuthorization ( ) ;
197
- }
198
- }
307
+ processAuthMiddlewares ? . Invoke ( ) ;
199
308
200
309
// Wire the source pipeline to run in the destination pipeline
201
310
app . Use ( next =>
0 commit comments