Skip to content

Add EndpointNameAttribute to enable setting endpoint name declaratively #34539

Closed
@DamianEdwards

Description

@DamianEdwards

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);
    });
);

Metadata

Metadata

Assignees

No one assigned

    Labels

    Priority:1Work that is critical for the release, but we could probably ship withoutarea-minimalIncludes minimal APIs, endpoint filters, parameter binding, request delegate generator etcenhancementThis issue represents an ask for new feature or an enhancement to an existing onefeature-minimal-actionsController-like actions for endpoint routingold-area-web-frameworks-do-not-use*DEPRECATED* This label is deprecated in favor of the area-mvc and area-minimal labels

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions