Description
APIs described by Microsoft.AspNetCore.Mvc.ApiExplorer.ApiDescription
can optionally have a group name defined by the GroupName
property. Today in the framework there isn't a way provided to set the group name for an endpoint via its metadata and the EndpointMetadataApiDescriptionProvider
does not set ApiDescription.GroupName
when it populates ApiExplorer
with details of the registered endpoints.
ApiDescription.GroupName
is used by frameworks like Swashbuckle to associate APIs with different OpenAPI documents, i.e. if the document name and API group name match the API is included in the document (see default logic here).
We should allow for setting the group name for endpoints via their metadata and have that used to populate the ApiDescription.GroupName
property when the endpoints are added to ApiExplorer
.
Proposed types for addition:
namespace Microsoft.AspNetCore.Routing;
/// <summary>
/// Declares the group name for this endpoint method or delegate.<br />
/// </summary>
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Delegate, Inherited = false, AllowMultiple = false)]
public sealed class EndpointGroupNameAttribute: Attribute, IEndpointGroupNameMetadata
{
public EndpointGroupNameAttribute(string endpointGroupName)
{
if (endpointGroupName == null)
{
throw new ArgumentNullException(nameof(endpointGroupName));
}
EndpointGroupName = endpointGroupName;
}
/// <summary>
/// The endpoint group name.
/// </summary>
public string EndpointGroupName { get; }
}
/// <summary>
/// Specifies an endpoint group name in Microsoft.AspNetCore.Http.Endpoint.Metadata.
/// </summary>
public class EndpointGroupNameMetadata : IEndpointGroupNameMetadata
{
public EndpointGroupNameMetadata(string endpointGroupName)
{
if (endpointGroupName == null)
{
throw new ArgumentNullException(nameof(endpointGroupName));
}
EndpointGroupName = endpointGroupName;
}
/// <summary>
/// The endpoint group name.
/// </summary>
public string EndpointGroupName { get; }
}
/// <summary>
/// Defines a contract use to specify an endpoint group name in Microsoft.AspNetCore.Http.Endpoint.Metadata.
/// </summary>
public interface IEndpointGroupNameMetadata
{
/// <summary>
/// The endpoint group name.
/// </summary>
string EndpointGroupName { get; }
}
Proposed extension methods for addition:
namespace Microsoft.AspNetCore.Builder;
public static class RoutingEndpointConventionBuilderExtensions
{
+ /// <summary>
+ /// Adds an EndpointGroupNameMetadata item to the Metadata for all endpoints produced by the builder.
+ /// </summary>
+ /// <param name="builder"></param>
+ /// <param name="groupName"></param>
+ /// <returns>The Microsoft.AspNetCore.Builder.IEndpointConventionBuilder.</returns>
+ public static TBuilder WithGroupName<TBuilder>(this TBuilder builder, string groupName) where TBuilder : IEndpointConventionBuilder
+ {
+ builder.WithMetadata(new EndpointGroupNameMetadata(groupName));
+
+ return builder;
+ }
}
Example of these new types and methods being used with minimal APIs:
app.MapGet("/hello/{name}", (string name) => $"Hello {name}")
.WithName("SayHelloToName")
.WithGroupName("NameApi")
app.MapGet("/todos/get-all", async (TodoDb db) => await db.Todos.ToListAsync())
.WithName("GetAllTodos")
.WithGroupName("TodoApi");