public override void RegisterEndpoints(IEndpointBuilder endpoints) { endpoints.MapControllers(); endpoints.MapApiDocument( name: "sample", title: "Sample Module", description: "The API for sample module", version: "1.0"); endpoints.WithErrorHandler("Sample", "Main") .MapFallbackNotFound("/sample/{**slug}") .MapStatusCode("/sample/{**slug}") .MapFallbackNotFound("/route-test/{id:int}") .MapFallbackNotFound("/route-test/{id:alpha}"); endpoints.MapRequestDelegate("/weather/checker", async context => { await context.Response.WriteAsync("Hello World!"); }); endpoints.MapRequestDelegate("/sample/world", context => { context.Response.StatusCode = 402; return(Task.CompletedTask); }); }
/// <summary> /// Maps incoming requests with the specified path to the provided connection pipeline. /// </summary> /// <param name="endpoints">The <see cref="IEndpointBuilder"/> to add the route to.</param> /// <param name="pattern">The route pattern.</param> /// <param name="options">Options used to configure the connection.</param> /// <param name="configure">A callback to configure the connection.</param> /// <returns>An <see cref="ConnectionEndpointRouteBuilder"/> for endpoints associated with the connections.</returns> public static ConnectionEndpointRouteBuilder MapConnections(this IEndpointBuilder endpoints, string pattern, HttpConnectionDispatcherOptions options, Action <IConnectionBuilder> configure) { var dispatcher = endpoints.ServiceProvider.GetRequiredService(_httpConnectionDispatcherType); var ExecuteNegotiateAsync = (Func <HttpContext, HttpConnectionDispatcherOptions, Task>) _httpConnectionDispatcherType .GetMethod("ExecuteNegotiateAsync") ! .CreateDelegate(typeof(Func <HttpContext, HttpConnectionDispatcherOptions, Task>), dispatcher); var ExecuteAsync = (Func <HttpContext, HttpConnectionDispatcherOptions, ConnectionDelegate, Task>) _httpConnectionDispatcherType .GetMethod("ExecuteAsync") ! .CreateDelegate(typeof(Func <HttpContext, HttpConnectionDispatcherOptions, ConnectionDelegate, Task>), dispatcher); var connectionBuilder = new ConnectionBuilder(endpoints.ServiceProvider); configure(connectionBuilder); var connectionDelegate = connectionBuilder.Build(); // REVIEW: Consider expanding the internals of the dispatcher as endpoint routes instead of // using if statements we can let the matcher handle var conventionBuilders = new List <IEndpointConventionBuilder>(); // Build the negotiate application var app = endpoints.CreateApplicationBuilder(); app.UseWebSockets(); app.Run(c => ExecuteNegotiateAsync(c, options)); var negotiateHandler = app.Build(); var negotiateBuilder = endpoints.MapRequestDelegate(pattern + "/negotiate", negotiateHandler); conventionBuilders.Add(negotiateBuilder); // Add the negotiate metadata so this endpoint can be identified negotiateBuilder.WithMetadata(new NegotiateMetadata()); // build the execute handler part of the protocol app = endpoints.CreateApplicationBuilder(); app.UseWebSockets(); app.Run(c => ExecuteAsync(c, options, connectionDelegate)); var executehandler = app.Build(); var executeBuilder = endpoints.MapRequestDelegate(pattern, executehandler); conventionBuilders.Add(executeBuilder); var compositeConventionBuilder = new CompositeEndpointConventionBuilder(conventionBuilders); // Add metadata to all of Endpoints compositeConventionBuilder.Add(e => { // Add the authorization data as metadata foreach (var data in options.AuthorizationData) { e.Metadata.Add(data); } }); return((ConnectionEndpointRouteBuilder) typeof(ConnectionEndpointRouteBuilder) .GetTypeInfo().DeclaredConstructors .Single() .Invoke(new object[] { compositeConventionBuilder })); }