1
1
// Licensed to the .NET Foundation under one or more agreements.
2
2
// The .NET Foundation licenses this file to you under the MIT license.
3
3
4
- using System ;
4
+ using System . Diagnostics ;
5
5
using Microsoft . AspNetCore . Diagnostics ;
6
6
using Microsoft . AspNetCore . Http ;
7
+ using Microsoft . Extensions . DependencyInjection ;
8
+ using Microsoft . Extensions . Logging ;
7
9
using Microsoft . Extensions . Options ;
8
10
9
11
namespace Microsoft . AspNetCore . Builder
@@ -26,7 +28,7 @@ public static IApplicationBuilder UseExceptionHandler(this IApplicationBuilder a
26
28
throw new ArgumentNullException ( nameof ( app ) ) ;
27
29
}
28
30
29
- return app . UseMiddleware < ExceptionHandlerMiddleware > ( ) ;
31
+ return SetExceptionHandlerMiddleware ( app , options : null ) ;
30
32
}
31
33
32
34
/// <summary>
@@ -95,7 +97,50 @@ public static IApplicationBuilder UseExceptionHandler(this IApplicationBuilder a
95
97
throw new ArgumentNullException ( nameof ( options ) ) ;
96
98
}
97
99
98
- return app . UseMiddleware < ExceptionHandlerMiddleware > ( Options . Create ( options ) ) ;
100
+ var iOptions = Options . Create ( options ) ;
101
+ return SetExceptionHandlerMiddleware ( app , iOptions ) ;
102
+ }
103
+
104
+ private static IApplicationBuilder SetExceptionHandlerMiddleware ( IApplicationBuilder app , IOptions < ExceptionHandlerOptions > ? options )
105
+ {
106
+ const string globalRouteBuilderKey = "__GlobalEndpointRouteBuilder" ;
107
+ // Only use this path if there's a global router (in the 'WebApplication' case).
108
+ if ( app . Properties . TryGetValue ( globalRouteBuilderKey , out var routeBuilder ) && routeBuilder is not null )
109
+ {
110
+ return app . Use ( next =>
111
+ {
112
+ var loggerFactory = app . ApplicationServices . GetRequiredService < ILoggerFactory > ( ) ;
113
+ var diagnosticListener = app . ApplicationServices . GetRequiredService < DiagnosticListener > ( ) ;
114
+
115
+ if ( options is null )
116
+ {
117
+ options = app . ApplicationServices . GetRequiredService < IOptions < ExceptionHandlerOptions > > ( ) ;
118
+ }
119
+
120
+ if ( ! string . IsNullOrEmpty ( options . Value . ExceptionHandlingPath ) && options . Value . ExceptionHandler is null )
121
+ {
122
+ // start a new middleware pipeline
123
+ var builder = app . New ( ) ;
124
+ // use the old routing pipeline if it exists so we preserve all the routes and matching logic
125
+ // ((IApplicationBuilder)WebApplication).New() does not copy globalRouteBuilderKey automatically like it does for all other properties.
126
+ builder . Properties [ globalRouteBuilderKey ] = routeBuilder ;
127
+ builder . UseRouting ( ) ;
128
+ // apply the next middleware
129
+ builder . Run ( next ) ;
130
+ // store the pipeline for the error case
131
+ options . Value . ExceptionHandler = builder . Build ( ) ;
132
+ }
133
+
134
+ return new ExceptionHandlerMiddleware ( next , loggerFactory , options , diagnosticListener ) . Invoke ;
135
+ } ) ;
136
+ }
137
+
138
+ if ( options is null )
139
+ {
140
+ return app . UseMiddleware < ExceptionHandlerMiddleware > ( ) ;
141
+ }
142
+
143
+ return app . UseMiddleware < ExceptionHandlerMiddleware > ( options ) ;
99
144
}
100
145
}
101
146
}
0 commit comments