|
2 | 2 | // The .NET Foundation licenses this file to you under the MIT license.
|
3 | 3 |
|
4 | 4 | using System.Diagnostics.CodeAnalysis;
|
5 |
| -using System.Linq; |
6 |
| -using System.Reflection; |
7 | 5 | using Microsoft.AspNetCore.Http;
|
8 | 6 | using Microsoft.AspNetCore.Routing;
|
9 | 7 | using Microsoft.AspNetCore.Routing.Patterns;
|
@@ -152,10 +150,7 @@ public static IEndpointConventionBuilder MapMethods(
|
152 | 150 | {
|
153 | 151 | ArgumentNullException.ThrowIfNull(httpMethods);
|
154 | 152 |
|
155 |
| - var builder = endpoints.Map(RoutePatternFactory.Parse(pattern), requestDelegate); |
156 |
| - builder.WithDisplayName($"{pattern} HTTP: {string.Join(", ", httpMethods)}"); |
157 |
| - builder.WithMetadata(new HttpMethodMetadata(httpMethods)); |
158 |
| - return builder; |
| 153 | + return endpoints.Map(RoutePatternFactory.Parse(pattern), requestDelegate, httpMethods); |
159 | 154 | }
|
160 | 155 |
|
161 | 156 | /// <summary>
|
@@ -186,41 +181,21 @@ public static IEndpointConventionBuilder Map(
|
186 | 181 | this IEndpointRouteBuilder endpoints,
|
187 | 182 | RoutePattern pattern,
|
188 | 183 | RequestDelegate requestDelegate)
|
| 184 | + { |
| 185 | + return Map(endpoints, pattern, requestDelegate, httpMethods: null); |
| 186 | + } |
| 187 | + |
| 188 | + private static IEndpointConventionBuilder Map( |
| 189 | + this IEndpointRouteBuilder endpoints, |
| 190 | + RoutePattern pattern, |
| 191 | + RequestDelegate requestDelegate, |
| 192 | + IEnumerable<string>? httpMethods) |
189 | 193 | {
|
190 | 194 | ArgumentNullException.ThrowIfNull(endpoints);
|
191 | 195 | ArgumentNullException.ThrowIfNull(pattern);
|
192 | 196 | ArgumentNullException.ThrowIfNull(requestDelegate);
|
193 | 197 |
|
194 |
| - const int defaultOrder = 0; |
195 |
| - |
196 |
| - var builder = new RouteEndpointBuilder( |
197 |
| - requestDelegate, |
198 |
| - pattern, |
199 |
| - defaultOrder) |
200 |
| - { |
201 |
| - DisplayName = pattern.RawText ?? pattern.DebuggerToString(), |
202 |
| - }; |
203 |
| - |
204 |
| - // Add delegate attributes as metadata |
205 |
| - var attributes = requestDelegate.Method.GetCustomAttributes(); |
206 |
| - |
207 |
| - // This can be null if the delegate is a dynamic method or compiled from an expression tree |
208 |
| - if (attributes != null) |
209 |
| - { |
210 |
| - foreach (var attribute in attributes) |
211 |
| - { |
212 |
| - builder.Metadata.Add(attribute); |
213 |
| - } |
214 |
| - } |
215 |
| - |
216 |
| - var dataSource = endpoints.DataSources.OfType<ModelEndpointDataSource>().FirstOrDefault(); |
217 |
| - if (dataSource == null) |
218 |
| - { |
219 |
| - dataSource = new ModelEndpointDataSource(); |
220 |
| - endpoints.DataSources.Add(dataSource); |
221 |
| - } |
222 |
| - |
223 |
| - return dataSource.AddEndpointBuilder(builder); |
| 198 | + return endpoints.GetOrAddRouteEndpointDataSource().AddRequestDelegate(pattern, requestDelegate, httpMethods); |
224 | 199 | }
|
225 | 200 |
|
226 | 201 | /// <summary>
|
@@ -429,18 +404,38 @@ private static RouteHandlerBuilder Map(
|
429 | 404 | ArgumentNullException.ThrowIfNull(pattern);
|
430 | 405 | ArgumentNullException.ThrowIfNull(handler);
|
431 | 406 |
|
432 |
| - var dataSource = endpoints.DataSources.OfType<RouteEndpointDataSource>().FirstOrDefault(); |
433 |
| - if (dataSource is null) |
| 407 | + return endpoints.GetOrAddRouteEndpointDataSource().AddRouteHandler(pattern, handler, httpMethods, isFallback); |
| 408 | + } |
| 409 | + |
| 410 | + private static RouteEndpointDataSource GetOrAddRouteEndpointDataSource(this IEndpointRouteBuilder endpoints) |
| 411 | + { |
| 412 | + RouteEndpointDataSource? routeEndpointDataSource = null; |
| 413 | + |
| 414 | + foreach (var dataSource in endpoints.DataSources) |
434 | 415 | {
|
435 |
| - var routeHandlerOptions = endpoints.ServiceProvider.GetService<IOptions<RouteHandlerOptions>>(); |
| 416 | + if (dataSource is RouteEndpointDataSource foundDataSource) |
| 417 | + { |
| 418 | + routeEndpointDataSource = foundDataSource; |
| 419 | + break; |
| 420 | + } |
| 421 | + } |
| 422 | + |
| 423 | + if (routeEndpointDataSource is null) |
| 424 | + { |
| 425 | + // ServiceProvider isn't nullable, but it is being called by methods that historically did not access this property, so we null check anyway. |
| 426 | + var routeHandlerOptions = endpoints.ServiceProvider?.GetService<IOptions<RouteHandlerOptions>>(); |
436 | 427 | var throwOnBadRequest = routeHandlerOptions?.Value.ThrowOnBadRequest ?? false;
|
437 | 428 |
|
438 |
| - dataSource = new RouteEndpointDataSource(endpoints.ServiceProvider, throwOnBadRequest); |
439 |
| - endpoints.DataSources.Add(dataSource); |
| 429 | + routeEndpointDataSource = new RouteEndpointDataSource(endpoints.ServiceProvider ?? EmptyServiceProvider.Instance, throwOnBadRequest); |
| 430 | + endpoints.DataSources.Add(routeEndpointDataSource); |
440 | 431 | }
|
441 | 432 |
|
442 |
| - var conventions = dataSource.AddEndpoint(pattern, handler, httpMethods, isFallback); |
| 433 | + return routeEndpointDataSource; |
| 434 | + } |
443 | 435 |
|
444 |
| - return new RouteHandlerBuilder(conventions); |
| 436 | + private sealed class EmptyServiceProvider : IServiceProvider |
| 437 | + { |
| 438 | + public static EmptyServiceProvider Instance { get; } = new EmptyServiceProvider(); |
| 439 | + public object? GetService(Type serviceType) => null; |
445 | 440 | }
|
446 | 441 | }
|
0 commit comments