Skip to content

Commit cf7c50b

Browse files
Merge pull request #2173 from captainsafia/safia/op-id-from-group-name
Support setting operation IDs from EndpointName metadata
2 parents a66864f + ea7246b commit cf7c50b

File tree

3 files changed

+67
-3
lines changed

3 files changed

+67
-3
lines changed

src/Swashbuckle.AspNetCore.SwaggerGen/SwaggerGenerator/SwaggerGeneratorOptions.cs

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
using System.Linq;
44
using Microsoft.AspNetCore.Mvc.ApiExplorer;
55
using Microsoft.OpenApi.Models;
6+
using Microsoft.AspNetCore.Routing;
67

78
namespace Swashbuckle.AspNetCore.SwaggerGen
89
{
@@ -61,7 +62,19 @@ private bool DefaultDocInclusionPredicate(string documentName, ApiDescription ap
6162

6263
private string DefaultOperationIdSelector(ApiDescription apiDescription)
6364
{
64-
return apiDescription.ActionDescriptor.AttributeRouteInfo?.Name;
65+
var actionDescriptor = apiDescription.ActionDescriptor;
66+
67+
// Resolve the operation ID from the route name and fallback to the
68+
// endpoint name if no route name is available. This allows us to
69+
// generate operation IDs for endpoints that are defined using
70+
// minimal APIs.
71+
#if (!NETSTANDARD2_0)
72+
return
73+
actionDescriptor.AttributeRouteInfo?.Name
74+
?? (actionDescriptor.EndpointMetadata.FirstOrDefault(m => m is IEndpointNameMetadata) as IEndpointNameMetadata)?.EndpointName;
75+
#else
76+
return actionDescriptor.AttributeRouteInfo?.Name;
77+
#endif
6578
}
6679

6780
private IList<string> DefaultTagsSelector(ApiDescription apiDescription)

test/Swashbuckle.AspNetCore.SwaggerGen.Test/SwaggerGenerator/SwaggerGeneratorTests.cs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
11
using System.Linq;
22
using System.Collections.Generic;
3+
using System.Reflection;
34
using System.Text.Json;
45
using Microsoft.AspNetCore.Mvc.ApiExplorer;
6+
using Microsoft.AspNetCore.Mvc.Abstractions;
57
using Microsoft.OpenApi.Models;
68
using Microsoft.AspNetCore.Mvc.ModelBinding;
9+
using Microsoft.AspNetCore.Routing;
710
using Microsoft.OpenApi.Any;
811
using Xunit;
912
using Swashbuckle.AspNetCore.Swagger;
@@ -77,6 +80,31 @@ public void GetSwagger_SetsOperationIdToRouteName_IfActionHasRouteNameMetadata()
7780
Assert.Equal("SomeRouteName", document.Paths["/resource"].Operations[OperationType.Post].OperationId);
7881
}
7982

83+
[Fact]
84+
public void GetSwagger_SetsOperationIdToEndpointName_IfActionHasEndpointNameMetadata()
85+
{
86+
var methodInfo = typeof(FakeController).GetMethod(nameof(FakeController.ActionWithParameter));
87+
var actionDescriptor = new ActionDescriptor
88+
{
89+
EndpointMetadata = new List<object>() { new EndpointNameMetadata("SomeEndpointName") },
90+
RouteValues = new Dictionary<string, string>
91+
{
92+
["controller"] = methodInfo.DeclaringType.Name.Replace("Controller", string.Empty)
93+
}
94+
};
95+
var subject = Subject(
96+
apiDescriptions: new[]
97+
{
98+
ApiDescriptionFactory.Create(actionDescriptor, methodInfo, groupName: "v1", httpMethod: "POST", relativePath: "resource"),
99+
}
100+
);
101+
102+
var document = subject.GetSwagger("v1");
103+
104+
Assert.Equal("SomeEndpointName", document.Paths["/resource"].Operations[OperationType.Post].OperationId);
105+
}
106+
107+
80108
[Fact]
81109
public void GetSwagger_SetsDeprecated_IfActionHasObsoleteAttribute()
82110
{

test/Swashbuckle.AspNetCore.TestSupport/ApiExplorer/ApiDescriptionFactory.cs

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ namespace Swashbuckle.AspNetCore.TestSupport
1212
public static class ApiDescriptionFactory
1313
{
1414
public static ApiDescription Create(
15+
ActionDescriptor actionDescriptor,
1516
MethodInfo methodInfo,
1617
string groupName = "v1",
1718
string httpMethod = "POST",
@@ -20,8 +21,6 @@ public static ApiDescription Create(
2021
IEnumerable<ApiRequestFormat> supportedRequestFormats = null,
2122
IEnumerable<ApiResponseType> supportedResponseTypes = null)
2223
{
23-
var actionDescriptor = CreateActionDescriptor(methodInfo);
24-
2524
var apiDescription = new ApiDescription
2625
{
2726
ActionDescriptor = actionDescriptor,
@@ -74,6 +73,30 @@ public static ApiDescription Create(
7473
return apiDescription;
7574
}
7675

76+
public static ApiDescription Create(
77+
MethodInfo methodInfo,
78+
string groupName = "v1",
79+
string httpMethod = "POST",
80+
string relativePath = "resoure",
81+
IEnumerable<ApiParameterDescription> parameterDescriptions = null,
82+
IEnumerable<ApiRequestFormat> supportedRequestFormats = null,
83+
IEnumerable<ApiResponseType> supportedResponseTypes = null)
84+
{
85+
86+
var actionDescriptor = CreateActionDescriptor(methodInfo);
87+
88+
return Create(
89+
actionDescriptor,
90+
methodInfo,
91+
groupName,
92+
httpMethod,
93+
relativePath,
94+
parameterDescriptions,
95+
supportedRequestFormats,
96+
supportedResponseTypes
97+
);
98+
}
99+
77100
public static ApiDescription Create<TController>(
78101
Func<TController, string> actionNameSelector,
79102
string groupName = "v1",

0 commit comments

Comments
 (0)