Add `EndpointNameAttribute` to enable setting endpoint name declaratively
DamianEdwards opened this issue · 2 comments
Endpoint names are used to lookup endpoints when generating links using LinkGenerator, and as their unique per application are a good candidate for using as the operationId for an endpoint in OpenAPI (Swagger) documents.
Endpoint names are set using the Microsoft.AspNetCore.Routing.IEndpointNameMetadata interface. In the framework today this can only be set imperatively by adding an instance of Microsoft.AspNetCore.Routing.EndpointNameMetadata to the endpoint's metadata, e.g. builder.WithMetadata(new EndpointNameMetadata("GetTodoById")). (#33924 includes adding a new extension method to allow adding the name in a more first-class fashion, e.g. builder.WithName("GetTodoById")).
To support declaratively setting an endpoint name we should add an attribute:
+ namespace Microsoft.AspNetCore.Routing;
+
+ /// <summary>
+ /// Specifies the endpoint name in Microsoft.AspNetCore.Http.Endpoint.Metadata.
+ /// </summary>
+ /// <remarks>
+ /// Endpoint names must be unique within an application, and can be used to unambiguously
+ /// identify a desired endpoint for URI generation using Microsoft.AspNetCore.Routing.LinkGenerator.
+ /// </remarks>
+ [AttributeUsage(AttributeTargets.Method | AttributeTargets.Delegate, Inherited = false, AllowMultiple = false)]
+ public sealed class EndpointNameAttribute : Attribute, IEndpointNameMetadata
+ {
+ /// <summary>
+ /// Initializes an instance of the EndpointNameAttribute.
+ /// </summary>
+ /// <param name="endpointName">The endpoint name.</param>
+ public EndpointNameAttribute(string endpointName)
+ {
+ if (endpointName == null)
+ {
+ throw new ArgumentNullException(nameof(endpointName));
+ }
+
+ EndpointName = endpointName;
+ }
+
+ /// <summary>
+ /// The endpoint name.
+ /// </summary>
+ public string EndpointName { get; }
+ }The attribute could be used as following:
app.MapGet("/todos/{id}",
+ [EndpointName("GetTodoById")
async (int id, TodoDb db) =>
{
return await db.Todos.FindAsync(id)
is Todo todo
? Results.Ok(todo)
: Results.NotFound();
});
app.MapPost("/todos",
+ [EndpointName("AddTodo")
async (Todo todo, TodoDb db) =>
{
db.Todos.Add(todo);
await db.SaveChangesAsync();
return Results.CreatedAtRoute("GetTodoById", new { todo.Id }, todo);
});
);Thanks for contacting us.
We're moving this issue to the Next sprint planning milestone for future evaluation / consideration. We would like to keep this around to collect more feedback, which can help us with prioritizing this work. We will re-evaluate this issue, during our next planning meeting(s).
If we later determine, that the issue has no community involvement, or it's very rare and low-impact issue, we will close it - so that the team can focus on more important and high impact issues.
To learn more about what to expect next and how this issue will be handled you can read more about our triage process here.
Closed in #34906