diff --git a/src/OpenTelemetry.Instrumentation.AspNet/Implementation/HttpRequestRouteHelper.cs b/src/OpenTelemetry.Instrumentation.AspNet/Implementation/HttpRequestRouteHelper.cs index 982f1b09b7..43b50b7168 100644 --- a/src/OpenTelemetry.Instrumentation.AspNet/Implementation/HttpRequestRouteHelper.cs +++ b/src/OpenTelemetry.Instrumentation.AspNet/Implementation/HttpRequestRouteHelper.cs @@ -28,8 +28,11 @@ internal sealed class HttpRequestRouteHelper { // WebAPI attribute routing flows here. Use reflection to not take a dependency on microsoft.aspnet.webapi.core\[version]\lib\[framework]\System.Web.Http. - if (msSubRoutes is Array attributeRouting && attributeRouting.Length == 1) + if (msSubRoutes is Array attributeRouting && attributeRouting.Length >= 1) { + // There could be more than one subroute, each with a different method. + // But the template is the same across them, so we simply take the template + // from the first route. var subRouteData = attributeRouting.GetValue(0); _ = this.routeFetcher.TryFetch(subRouteData, out var route); diff --git a/test/OpenTelemetry.Instrumentation.AspNet.Tests/HttpInListenerTests.cs b/test/OpenTelemetry.Instrumentation.AspNet.Tests/HttpInListenerTests.cs index b14a987eeb..973d106599 100644 --- a/test/OpenTelemetry.Instrumentation.AspNet.Tests/HttpInListenerTests.cs +++ b/test/OpenTelemetry.Instrumentation.AspNet.Tests/HttpInListenerTests.cs @@ -41,6 +41,7 @@ public enum QueryRedactionDisableBehavior [InlineData("https://localhost:443/about_attr_route/10", "https", "/about_attr_route/10", null, null, "localhost", 443, "HEAD", "HEAD", null, 2, "about_attr_route/{customerId}", "HEAD about_attr_route/{customerId}")] [InlineData("http://localhost:1880/api/weatherforecast", "http", "/api/weatherforecast", null, null, "localhost", 1880, "GET", "GET", null, 3, "api/{controller}/{id}", "GET api/{controller}/{id}")] [InlineData("https://localhost:1843/subroute/10", "https", "/subroute/10", null, null, "localhost", 1843, "GET", "GET", null, 4, "subroute/{customerId}", "GET subroute/{customerId}")] + [InlineData("https://localhost:1843/subroute/10", "https", "/subroute/10", null, null, "localhost", 1843, "GET", "GET", null, 5, "subroute/{customerId}", "GET subroute/{customerId}")] [InlineData("http://localhost/api/value", "http", "/api/value", null, null, "localhost", 80, "GET", "GET", null, 0, null, "GET", false, "/api/value")] // Request will be filtered [InlineData("http://localhost/api/value", "http", "/api/value", null, null, "localhost", 80, "GET", "GET", null, 0, null, "GET", false, "{ThrowException}")] // Filter user code will throw an exception [InlineData("http://localhost/", "http", "/", null, null, "localhost", 80, "GET", "GET", null, 0, null, "GET", false, null, true, "System.InvalidOperationException")] // Test RecordException option diff --git a/test/OpenTelemetry.Instrumentation.AspNet.Tests/RouteTestHelper.cs b/test/OpenTelemetry.Instrumentation.AspNet.Tests/RouteTestHelper.cs index cebdc04598..808d647ac8 100644 --- a/test/OpenTelemetry.Instrumentation.AspNet.Tests/RouteTestHelper.cs +++ b/test/OpenTelemetry.Instrumentation.AspNet.Tests/RouteTestHelper.cs @@ -1,6 +1,7 @@ // Copyright The OpenTelemetry Authors // SPDX-License-Identifier: Apache-2.0 +using System.Net.Http; using System.Web; using System.Web.Routing; @@ -40,6 +41,75 @@ public static HttpContext BuildHttpContext(string url, int routeType, string? ro "MS_SubRoutes", value); break; + case 5: // Multi-method attribute routing WebAPI. + routeData = new RouteData(); + var multiMethodSubroutes = new[] + { + new + { + Route = new + { + RouteTemplate = routeTemplate, + DataTokens = new Dictionary + { + ["actions"] = new[] + { + new + { + SupportedHttpMethods = new[] + { + HttpMethod.Get, + }, + }, + }, + }, + }, + }, + new + { + Route = new + { + RouteTemplate = routeTemplate, + DataTokens = new Dictionary + { + ["actions"] = new[] + { + new + { + SupportedHttpMethods = new[] + { + HttpMethod.Put, + }, + }, + }, + }, + }, + }, + new + { + Route = new + { + RouteTemplate = routeTemplate, + DataTokens = new Dictionary + { + ["actions"] = new[] + { + new + { + SupportedHttpMethods = new[] + { + HttpMethod.Delete, + }, + }, + }, + }, + }, + }, + }; + routeData.Values.Add( + "MS_SubRoutes", + multiMethodSubroutes); + break; default: throw new NotSupportedException(); }