// Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; using System.Collections.Generic; using System.Threading.Tasks; using Microsoft.AspNetCore.Dispatcher; namespace DispatcherSample { public class HttpMethodEndpointSelector : EndpointSelector { public override async Task SelectAsync(EndpointSelectorContext context) { if (context == null) { throw new ArgumentNullException(nameof(context)); } var snapshot = context.CreateSnapshot(); var fallback = new List(); for (var i = context.Endpoints.Count - 1; i >= 0; i--) { var endpoint = context.Endpoints[i]; IHttpMethodMetadata metadata = null; for (var j = endpoint.Metadata.Count - 1; j >= 0; j--) { metadata = endpoint.Metadata[j] as IHttpMethodMetadata; if (metadata != null) { break; } } if (metadata == null) { // No metadata. fallback.Add(endpoint); context.Endpoints.RemoveAt(i); } else if (Matches(metadata, context.HttpContext.Request.Method)) { // Do thing, this one matches } else { // Not a match. context.Endpoints.RemoveAt(i); } } // Now the list of endpoints only contains those that have an HTTP method preference AND match the current // request. await context.InvokeNextAsync(); if (context.Endpoints.Count == 0) { // Nothing matched, do the fallback. context.RestoreSnapshot(snapshot); context.Endpoints.Clear(); for (var i = 0; i < fallback.Count; i++) { context.Endpoints.Add(fallback[i]); } await context.InvokeNextAsync(); } } private bool Matches(IHttpMethodMetadata metadata, string httpMethod) { for (var i = 0; i < metadata.AllowedMethods.Count; i++) { if (string.Equals(metadata.AllowedMethods[i], httpMethod, StringComparison.OrdinalIgnoreCase)) { return true; } } return false; } } }