Skip to content

Commit 572c6b3

Browse files
committed
Ported Endpoint routing to temporary use the legacy router (#326)
1 parent bf3bfd1 commit 572c6b3

File tree

2 files changed

+96
-10
lines changed

2 files changed

+96
-10
lines changed

samples/Blog/Blog.Web/Infrastructure/ApplicationBuilderExtensions.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,13 @@ public static IApplicationBuilder UseMvcWithAreas(this IApplicationBuilder app)
1919
=> app.UseEndpoints(routes =>
2020
{
2121
routes.MapControllerRoute(
22-
name: "default",
23-
pattern: "{controller=Home}/{action=Index}/{id?}"
22+
name: "areas",
23+
pattern: "{area:exists}/{controller=Home}/{action=Index}/{id?}"
2424
);
2525

2626
routes.MapControllerRoute(
27-
name: "areas",
28-
pattern: "{area:exists}/{controller=Home}/{action=Index}/{id?}"
27+
name: "default",
28+
pattern: "{controller=Home}/{action=Index}/{id?}"
2929
);
3030

3131
routes.MapRazorPages();

src/MyTested.AspNetCore.Mvc.Abstractions/Internal/Application/ApplicationBuilderMock.cs

Lines changed: 92 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,11 @@
88
using Microsoft.AspNetCore.Builder;
99
using Microsoft.AspNetCore.Http;
1010
using Microsoft.AspNetCore.Http.Features;
11+
using Microsoft.AspNetCore.Mvc;
1112
using Microsoft.AspNetCore.Routing;
13+
using Microsoft.Extensions.DependencyInjection;
14+
using Microsoft.Extensions.Options;
15+
using Utilities.Extensions;
1216

1317
/// <summary>
1418
/// Mock of <see cref="IApplicationBuilder"/>. Used for extracting registered routes.
@@ -20,6 +24,8 @@ public class ApplicationBuilderMock : IApplicationBuilder
2024

2125
private readonly IList<Func<RequestDelegate, RequestDelegate>> components = new List<Func<RequestDelegate, RequestDelegate>>();
2226

27+
private bool endpointsEnabled = false;
28+
2329
/// <summary>
2430
/// Initializes a new instance of the <see cref="ApplicationBuilderMock"/> class.
2531
/// </summary>
@@ -33,13 +39,15 @@ public ApplicationBuilderMock(IServiceProvider serviceProvider)
3339

3440
this.Routes = new RouteCollection();
3541
this.ApplicationServices = serviceProvider;
42+
43+
this.CheckForEndpointRouting(serviceProvider);
3644
}
3745

3846
/// <summary>
3947
/// Initializes a new instance of the <see cref="ApplicationBuilderMock"/> class.
4048
/// </summary>
4149
/// <param name="builder">Application builder to copy properties from.</param>
42-
public ApplicationBuilderMock(IApplicationBuilder builder)
50+
public ApplicationBuilderMock(IApplicationBuilder builder)
4351
=> this.Properties = builder.Properties;
4452

4553
/// <summary>
@@ -69,15 +77,16 @@ public IServiceProvider ApplicationServices
6977
/// </summary>
7078
/// <value>Result of <see cref="RouteCollection"/> type.</value>
7179
public RouteCollection Routes { get; set; }
72-
80+
7381
/// <summary>
7482
/// Extracts registered routes from the provided middleware, if such are found.
7583
/// </summary>
7684
/// <param name="middleware">Middleware delegate.</param>
7785
/// <returns>The same <see cref="IApplicationBuilder"/>.</returns>
7886
public IApplicationBuilder Use(Func<RequestDelegate, RequestDelegate> middleware)
7987
{
80-
this.ExtractRoutes(middleware);
88+
this.ExtractEndpointRoutes(middleware);
89+
this.ExtractLegacyRoutes(middleware);
8190

8291
this.components.Add(middleware);
8392
return this;
@@ -109,12 +118,89 @@ public RequestDelegate Build()
109118
return app;
110119
}
111120

112-
private T GetProperty<T>(string key)
113-
=> this.Properties.TryGetValue(key, out var value) ? (T)value : default(T);
121+
private T GetProperty<T>(string key)
122+
=> this.Properties.TryGetValue(key, out var value) ? (T)value : default;
114123

115124
private void SetProperty<T>(string key, T value) => this.Properties[key] = value;
116125

117-
private void ExtractRoutes(Func<RequestDelegate, RequestDelegate> middleware)
126+
private void CheckForEndpointRouting(IServiceProvider serviceProvider)
127+
{
128+
var options = serviceProvider.GetService<IOptions<MvcOptions>>()?.Value;
129+
130+
this.endpointsEnabled = options?.EnableEndpointRouting ?? false;
131+
}
132+
133+
private void ExtractEndpointRoutes(Func<RequestDelegate, RequestDelegate> middleware)
134+
{
135+
var middlewareTypeField = middleware
136+
.Target
137+
.GetType()
138+
.GetTypeInfo()
139+
.DeclaredFields
140+
.FirstOrDefault(m => m.Name == "middleware");
141+
142+
if (!(middlewareTypeField?.GetValue(middleware.Target) is Type middlewareType)
143+
|| middlewareType.Name != "EndpointMiddleware")
144+
{
145+
return;
146+
}
147+
148+
var routeOptions = this.ApplicationServices.GetService<IOptions<RouteOptions>>()?.Value;
149+
150+
if (routeOptions == null)
151+
{
152+
return;
153+
}
154+
155+
var routeBuilder = new RouteBuilder(this)
156+
{
157+
DefaultHandler = new RouteHandler(c => Task.CompletedTask)
158+
};
159+
160+
var endpointDataSources = routeOptions.Exposed().EndpointDataSources;
161+
162+
foreach (EndpointDataSource endpointDataSource in endpointDataSources)
163+
{
164+
var routeEndpoints = endpointDataSource
165+
.Endpoints
166+
.OfType<RouteEndpoint>()
167+
.Where(e => e.DisplayName.StartsWith("Route: "))
168+
.OrderBy(e => e.Order);
169+
170+
foreach (var routeEndpoint in routeEndpoints)
171+
{
172+
var routeName = routeEndpoint
173+
.Metadata
174+
.OfType<RouteNameMetadata>()
175+
.FirstOrDefault()
176+
?.RouteName;
177+
178+
if (routeName == null)
179+
{
180+
return;
181+
}
182+
183+
routeBuilder.MapRoute(
184+
name: routeName,
185+
routeEndpoint.RoutePattern.RawText);
186+
}
187+
}
188+
189+
var attributeRoutingType = WebFramework.Internals.AttributeRouting;
190+
var createAttributeMegaRouteMethod = attributeRoutingType.GetMethod("CreateAttributeMegaRoute");
191+
var router = (IRouter)createAttributeMegaRouteMethod.Invoke(null, new[] { this.ApplicationServices });
192+
193+
routeBuilder.Routes.Insert(0, router);
194+
195+
var routes = routeBuilder.Routes;
196+
197+
for (int i = 0; i < routes.Count; i++)
198+
{
199+
this.Routes.Add(routes[i]);
200+
}
201+
}
202+
203+
private void ExtractLegacyRoutes(Func<RequestDelegate, RequestDelegate> middleware)
118204
{
119205
var middlewareArguments = middleware
120206
.Target

0 commit comments

Comments
 (0)