Working on an observability middleware in dotnet. I have a utility method to extract the template path representing the operation to use in tracing / metrics etc.
private static string DeriveTemplate(HttpContext context)
{
// attempt to fetch the actual template path.
var endpointBeingHit = context.Features.Get<IEndpointFeature>()?.Endpoint;
var actionDescriptor =
endpointBeingHit?.Metadata?.GetMetadata<ControllerActionDescriptor>();
var urlPath = actionDescriptor?.AttributeRouteInfo?.Template;
if (urlPath != null)
{
if (!urlPath.StartsWith("/"))
{
urlPath = $"/{urlPath}";
}
return urlPath;
}
// if for whatever reason one could not be found use this as a fallback.
var routeData = context.GetRouteData().Values;
return $"{routeData?["controller"]}-{routeData?["action"]}";
}
I'd like to expand the version:apiVersion
out in the template (without expanding any path placeholders). I am not familiar with aspnet internals -- how would I achieve this ?
CodePudding user response:
I know that the api versioning project was handling something like this, and they were replacing the api version in the urls, so I took a look at their source code. The pipeline is different (since they're working on the api descriptors, and your code is running within the request pipeline), but the principle looks to be the same - you'd have to get the request's api version, and run a string replacement to substitute it :)
You could use something like this:
var apiVersioning = context.Features.Get<IApiVersioningFeature>();
if (apiVersioning != null)
{
urlPath = Regex.Replace(urlPath, $@"{{{apiVersioning.RouteParameter}(?:\b[^}}] )?}}", apiVersioning.RequestedApiVersion.ToString());
}
Ref: Here's the method that runs the substitution in the api versioning project: https://github.com/dotnet/aspnet-api-versioning/blob/88cb5468fc64ef6c1d5497047753955d58d293f3/src/Microsoft.AspNetCore.Mvc.Versioning.ApiExplorer/ApiDescriptionExtensions.cs#L59