Skip to content

Commit

Permalink
Support setting operation IDs from EndpointName metadata
Browse files Browse the repository at this point in the history
  • Loading branch information
captainsafia committed Jul 29, 2021
1 parent a66864f commit 05b3f45
Show file tree
Hide file tree
Showing 3 changed files with 70 additions and 3 deletions.
Expand Up @@ -3,6 +3,7 @@
using System.Linq;
using Microsoft.AspNetCore.Mvc.ApiExplorer;
using Microsoft.OpenApi.Models;
using Microsoft.AspNetCore.Routing;

namespace Swashbuckle.AspNetCore.SwaggerGen
{
Expand Down Expand Up @@ -61,7 +62,19 @@ private bool DefaultDocInclusionPredicate(string documentName, ApiDescription ap

private string DefaultOperationIdSelector(ApiDescription apiDescription)
{
return apiDescription.ActionDescriptor.AttributeRouteInfo?.Name;
var actionDescriptor = apiDescription.ActionDescriptor;

// Resolve the operation ID from the route name and fallback to the
// endpoint name if no route name is available. This allows us to
// generate operation IDs for endpoints that are defined using
// minimal APIs.
#if (!NETSTANDARD2_0)
return
actionDescriptor.AttributeRouteInfo?.Name
?? (actionDescriptor.EndpointMetadata.FirstOrDefault(m => m is EndpointNameMetadata) as EndpointNameMetadata)?.EndpointName;
#else
return actionDescriptor.AttributeRouteInfo?.Name;
#endif
}

private IList<string> DefaultTagsSelector(ApiDescription apiDescription)
Expand Down
@@ -1,9 +1,12 @@
using System.Linq;
using System.Collections.Generic;
using System.Reflection;
using System.Text.Json;
using Microsoft.AspNetCore.Mvc.ApiExplorer;
using Microsoft.AspNetCore.Mvc.Controllers;
using Microsoft.OpenApi.Models;
using Microsoft.AspNetCore.Mvc.ModelBinding;
using Microsoft.AspNetCore.Routing;
using Microsoft.OpenApi.Any;
using Xunit;
using Swashbuckle.AspNetCore.Swagger;
Expand Down Expand Up @@ -77,6 +80,34 @@ public void GetSwagger_SetsOperationIdToRouteName_IfActionHasRouteNameMetadata()
Assert.Equal("SomeRouteName", document.Paths["/resource"].Operations[OperationType.Post].OperationId);
}

[Fact]
public void GetSwagger_SetsOperationIdToEndpointName_IfActionHasEndpointNameMetadata()
{
var methodInfo = typeof(FakeController).GetMethod(nameof(FakeController.ActionWithParameter));
var actionDescriptor = new ControllerActionDescriptor
{
ControllerTypeInfo = methodInfo.DeclaringType.GetTypeInfo(),
ControllerName = methodInfo.DeclaringType.Name,
MethodInfo = methodInfo,
EndpointMetadata = new List<object>() { new EndpointNameMetadata("SomeEndpointName") },
RouteValues = new Dictionary<string, string>
{
["controller"] = methodInfo.DeclaringType.Name.Replace("Controller", string.Empty)
}
};
var subject = Subject(
apiDescriptions: new[]
{
ApiDescriptionFactory.Create(actionDescriptor, methodInfo, groupName: "v1", httpMethod: "POST", relativePath: "resource"),
}
);

var document = subject.GetSwagger("v1");

Assert.Equal("SomeEndpointName", document.Paths["/resource"].Operations[OperationType.Post].OperationId);
}


[Fact]
public void GetSwagger_SetsDeprecated_IfActionHasObsoleteAttribute()
{
Expand Down
Expand Up @@ -12,6 +12,7 @@ namespace Swashbuckle.AspNetCore.TestSupport
public static class ApiDescriptionFactory
{
public static ApiDescription Create(
ActionDescriptor actionDescriptor,
MethodInfo methodInfo,
string groupName = "v1",
string httpMethod = "POST",
Expand All @@ -20,8 +21,6 @@ public static class ApiDescriptionFactory
IEnumerable<ApiRequestFormat> supportedRequestFormats = null,
IEnumerable<ApiResponseType> supportedResponseTypes = null)
{
var actionDescriptor = CreateActionDescriptor(methodInfo);

var apiDescription = new ApiDescription
{
ActionDescriptor = actionDescriptor,
Expand Down Expand Up @@ -74,6 +73,30 @@ public static class ApiDescriptionFactory
return apiDescription;
}

public static ApiDescription Create(
MethodInfo methodInfo,
string groupName = "v1",
string httpMethod = "POST",
string relativePath = "resoure",
IEnumerable<ApiParameterDescription> parameterDescriptions = null,
IEnumerable<ApiRequestFormat> supportedRequestFormats = null,
IEnumerable<ApiResponseType> supportedResponseTypes = null)
{

var actionDescriptor = CreateActionDescriptor(methodInfo);

return Create(
actionDescriptor,
methodInfo,
groupName,
httpMethod,
relativePath,
parameterDescriptions,
supportedRequestFormats,
supportedResponseTypes
);
}

public static ApiDescription Create<TController>(
Func<TController, string> actionNameSelector,
string groupName = "v1",
Expand Down

0 comments on commit 05b3f45

Please sign in to comment.