0

I'm currently working with a minimal API in C# and I'm using various extension methods to configure endpoints. In my specific case, I have an endpoint defined like this:

app.MapGet("/newweatherforecast", () =>
{
    var forecast = Enumerable.Range(1, 10).Select(index =>
        new WeatherForecastNew
        (
            DateOnly.FromDateTime(DateTime.Now.AddDays(index)),
            Random.Shared.Next(-20, 55)
        ))
        .ToArray();
    return forecast;
})
.AddFeatureFlag("NewGetWeatherForecast")
.WithName("NewGetWeatherForecast")
.WithOpenApi();

The AddFeatureFlag method is a custom extension method that ultimately calls my FeatureFlagEndpoint filter, which looks like this:

public static class FeatureFlagFilterEndpointExtensions
{
    public static TBuilder AddFeatureFlag<TBuilder>(this TBuilder builder, string _endpointsName) where TBuilder : IEndpointConventionBuilder
    {
        builder.AddEndpointFilter(new FeatureFlagEndpoint(_endpointsName));
        return builder;
    }
}

public class FeatureFlagEndpoint : IEndpointFilter
{
    private readonly string _endpointsName;

    public FeatureFlagEndpoint(string endpointFilter)
    {
        _endpointsName = endpointFilter;
    }

    public async ValueTask<object?> InvokeAsync(EndpointFilterInvocationContext context, EndpointFilterDelegate next)
    {
        var featureFlag = context.HttpContext.RequestServices.GetRequiredService<IFeatureManager>();
        var endpointMethodName = _endpointsName; // Here, I want to retrieve the calling endpoint name using the context.

        // I intend to obtain the name of the calling endpoint, accessible through the context. However, I'm unsure about the precise approach to achieve this.
        // Once I manage to accomplish this, it will simplify case handling and remove the need for an additional parameterized extension method.

        // ...
    }
}

In the FeatureFlagEndpoint class, I'm trying to get the name of the calling endpoint using the context, but I'm unsure about the exact method to achieve this. Once I successfully retrieve this information, I believe it will lead to simpler case management and eliminate the necessity for the extra parameterized extension method.

Could someone provide guidance on how to retrieve the name of the calling endpoint using the provided context or suggest an alternative approach to achieve the same result?

Guru Stron
  • 102,774
  • 10
  • 95
  • 132
Hardipsinh Jadeja
  • 1,180
  • 1
  • 13
  • 30
  • Why do you want this? `AddEndpointFilter` already applies the filter to the endpoint you want. – Panagiotis Kanavos Aug 07 '23 at 13:45
  • Because I wanted to create feature flag names based on the endpoint name – Hardipsinh Jadeja Aug 07 '23 at 13:46
  • Which you've already passed in the constructor. Besides, flags are created *before* a filter starts processing requests. In `InvokeAsync` you check the values stored in those flags. Flags that are rebuilt on every request with default values aren't very useful – Panagiotis Kanavos Aug 07 '23 at 13:48
  • I already passed but in order to achieve that requirement. I have to create addittional extension method named `AddFeatureFlag`. If I can get that value somehow from context, I don't need to create that extension method as well. – Hardipsinh Jadeja Aug 07 '23 at 13:50

1 Answers1

0

WithName adds EndpointNameMetadata to endpoint description which you can try to access with GetEndpoint -> Metadata from the HttpContext:

public class FeatureFlagEndpoint : IEndpointFilter
{
    public async ValueTask<object?> InvokeAsync(EndpointFilterInvocationContext context, EndpointFilterDelegate next)
    {
        var endpointMetadataCollection = context.HttpContext.GetEndpoint()?.Metadata;
        var name = endpointMetadataCollection?.GetMetadata<EndpointNameMetadata>()?.EndpointName;

        return ValueTask.FromResult(new object());
    }
}
Guru Stron
  • 102,774
  • 10
  • 95
  • 132