-
Notifications
You must be signed in to change notification settings - Fork 10.3k
Allow endpoint filter factories to manipulate endpoint metadata #41722
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
Thanks for contacting us. We're moving this issue to the |
How useful is this in general? Are there analogues to what this is in MVC (application model)? I'd like to see more use cases before we do this feature. |
When we talked about it today it turned out this was a simple oversight, i.e. when the filter factories were implemented it was intended that they could manipulate endpoint metadata, but it just wasn't implemented correctly. WRT how useful this is in general, this enables a filter to now intercept/modify any metadata-driven aspects of endpoints, so any system that relies on metadata can now be enabled, disabled, modified, etc. by filters (CORS, authz, OpenAPI, etc.). |
Sure I know what it can do I just want to see more examples of how it would be used. |
Is the idea that this customers would use this to mutate the metdata while just leave the filter as purely passthrough? |
That wasn't the intent I had in mind, but indeed that could be a scenario it enables, which is a scenario we've discussed a few times in the past (central manipulation of endpoint metadata). This feels to me like a building block level capability, esp. given the fact that filters, by design, can effectively manipulate the original spec/behavior of a route handler. |
Thinking about this more, It occurred to me that one can easily create an extension method to encapsulate the adding of a filter factory and an endpoint convention builder delegate that mutates endpoint metadata, resulting in a single method-call experience that achieves the desired outcome, which somewhat reduces the importance of filter factories being able to manipulate endpoint metadata directly: app.MapGet("/todos", async Task<Ok<Todo[]>> (TodoDb db) => TypedResults.Ok(await db.Todos.ToArrayAsync())
.WithXmlFormatter();
public static class XmlFormatterExtensions
{
public static RouteHandlerBuilder WithXmlFormatter(this RouteHandlerBuilder builder) =>
builder.AddFilter((context, next) =>
{
var returnType = context.MethodInfo.ReturnType;
if (returnType.IsAssignableTo(typeof(Ok<Todo[]>)))
{
// Return an "XML formatter" filter
return async c =>
{
var result = await next(c);
if (!c.HttpContext.Request.Headers.Accepts.Contains("text/xml")
{
// Client doesn't support XML, just return original result
return result;
}
return result switch
{
Ok<Todo[]> ok => CustomResults.OkXml(ok.Value),
_ => throw new InvalidOperationException("Result type cannot be formatted as XML.")
};
}
}
}
.WithMetadata(new ProducesResponseTypeAttribute(typeof(Todo), 200, "text/xml"));
} |
In practice this is still kinda awkward as the filter factory delegate itself can't see the metadata, both the callbacks (endpoint builder and filter itself) need to look at metadata and no-op (in this case) independently. Would be much more convenient to just do this in the filter factory delegate itself. |
Thank you for submitting this for API review. This will be reviewed by @dotnet/aspnet-api-review at the next meeting of the ASP.NET Core API Review group. Please ensure you take a look at the API review process documentation and ensure that:
|
API review notes from @captainsafia :
|
When adding endpoint filters via a filter factory delegate, it would sometimes be useful to be able to manipulate the endpoint's metadata too, in the case where the filter will impact the effective endpoint operation.
For example, below shows a rudimentary XML formatting filter that adds the ability for an endpoint to format its response as XML if the client supports it, instead of the usual JSON. This filter should be able to update the endpoint metadata to indicate that it can now return XML as well, so that it's described as such in
ApiExplorer
and OpenAPI/Swagger.The suggested API diff:
Ordering considerations
Imagine the above example is extended so that other methods on the
IEndpointConventionBuilder
are called that also manipulate endpoint metadata, e.g.:What is the order of operations WRT to the buildup of the endpoint metadata collection?
Will the filter factory delegate see:
EndpointNameAttribute("GetTodos"), TagsAttribute("FirstTag")
), and not that for the methods declared after it; orIdeally I think, it would see the endpoint metadata added by any methods declared before it in the endpoint builder (point 1), along with any metadata added by
RequestDelegateFactory
it self for the endpoint delegate.The text was updated successfully, but these errors were encountered: