Skip to content

Commit

Permalink
Fix bug with "AmbiguousMatchException".
Browse files Browse the repository at this point in the history
  • Loading branch information
unchase committed Feb 29, 2020
1 parent f371e5d commit ce464bb
Show file tree
Hide file tree
Showing 6 changed files with 120 additions and 18 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@

These are the changes to each version that has been released on the [nuget](https://www.nuget.org/packages/Unchase.Swashbuckle.AspNetCore.Extensions/).

## v2.2.2 `(2020-02-29)`

- [x] Fix bug with `AmbiguousMatchException`

## v2.2.1 `(2020-02-29)`

- [x] Add feature: remove Paths and Definitions from OpenApi documentation for all controller actions without accepted roles
Expand Down
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,8 @@ public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
}
```

Validated actions must be annotated with the one of `HttpMethodAttribute` (`HttpGetAttribute`, `HttpPostAttribute`, `HttpDeleteAttribute`, `HttpPutAttribute`, `HttpPatchAttribute`) attributes.

3. **Append action count into the SwaggetTag's descriptions in OpenApi document**:
- In the _ConfigureServices_ method of _Startup.cs_, inside your `AddSwaggerGen` call, enable `AppendActionCountToTagSummaryDocumentFilter` document filter:

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ public static OpenApiDocument RemovePathsAndComponentsWithoutAcceptedRolesForCon
var paths = new Dictionary<MethodInfo, string>();
foreach (var methodInfo in typeof(TController).GetMethods().Where(m => !m.IsSpecialName))
{
var actionDescriptor = ApiDescriptionFactory.Create<TController>(c => methodInfo.Name, typeof(TController).GetCustomAttribute<RouteAttribute>().Template)?.ActionDescriptor;
var actionDescriptor = ApiDescriptionFactory.Create<TController>(methodInfo, typeof(TController).GetCustomAttribute<RouteAttribute>().Template)?.ActionDescriptor;
if (actionDescriptor != null)
{
paths.Add(((Microsoft.AspNetCore.Mvc.Controllers.ControllerActionDescriptor)actionDescriptor).MethodInfo, actionDescriptor.AttributeRouteInfo.Template);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ internal static class ApiDescriptionFactory
/// Create <see cref="ApiDescription"/>.
/// </summary>
/// <param name="controllerType">Type of Controller.</param>
/// <param name="actionName">Controller action name.</param>
/// <param name="methodInfo">Controller action <see cref="MethodInfo"/>.</param>
/// <param name="groupName">Group name.</param>
/// <param name="httpMethod">Http method.</param>
/// <param name="relativePath">Relative path.</param>
Expand All @@ -31,25 +31,14 @@ internal static class ApiDescriptionFactory
/// </returns>
internal static ApiDescription Create(
Type controllerType,
string actionName,
MethodInfo methodInfo,
string groupName = null,
string httpMethod = null,
string relativePath = null,
IEnumerable<ApiParameterDescription> parameterDescriptions = null,
IEnumerable<ApiRequestFormat> supportedRequestFormats = null,
IEnumerable<ApiResponseType> supportedResponseTypes = null)
{
MethodInfo methodInfo;

try
{
methodInfo = controllerType.GetMethod(actionName);
}
catch (AmbiguousMatchException)
{
return null;
}

if (methodInfo == null)
return null;

Expand All @@ -59,7 +48,7 @@ internal static ApiDescription Create(

if (string.IsNullOrWhiteSpace(actionDescriptor?.AttributeRouteInfo?.Template))
return null;
//throw new InvalidOperationException($"HttpMethod attribute of \"{methodInfo.Name}\" action in \"{controllerType.Name}\" controller must have a template specified.");
//throw new InvalidOperationException($"HttpMethod attribute of \"{methodInfo.Name}\" action in \"{controllerType.Name}\" controller must have a template specified.");

if (routAttr != null && !string.IsNullOrWhiteSpace(routAttr.Template))
{
Expand Down Expand Up @@ -127,6 +116,45 @@ internal static ApiDescription Create(
return apiDescription;
}

/// <summary>
/// Create <see cref="ApiDescription"/>.
/// </summary>
/// <param name="controllerType">Type of Controller.</param>
/// <param name="actionName">Controller action name.</param>
/// <param name="groupName">Group name.</param>
/// <param name="httpMethod">Http method.</param>
/// <param name="relativePath">Relative path.</param>
/// <param name="parameterDescriptions">Collection of <see cref="ApiParameterDescription"/>.</param>
/// <param name="supportedRequestFormats">Collection of <see cref="ApiRequestFormat"/>.</param>
/// <param name="supportedResponseTypes">Collection of <see cref="ApiResponseType"/>.</param>
/// <returns>
/// Returns <see cref="ApiDescription"/>.
/// </returns>
internal static ApiDescription Create(
Type controllerType,
string actionName,
string groupName = null,
string httpMethod = null,
string relativePath = null,
IEnumerable<ApiParameterDescription> parameterDescriptions = null,
IEnumerable<ApiRequestFormat> supportedRequestFormats = null,
IEnumerable<ApiResponseType> supportedResponseTypes = null)
{
MethodInfo methodInfo;

try
{
methodInfo = controllerType.GetMethod(actionName);
}
catch (AmbiguousMatchException)
{
return null;
}

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

/// <summary>
/// Create <see cref="ApiDescription"/>.
/// </summary>
Expand Down Expand Up @@ -163,6 +191,42 @@ internal static ApiDescription Create<TController>(
);
}

/// <summary>
/// Create <see cref="ApiDescription"/>.
/// </summary>
/// <typeparam name="TController">Type of Controller.</typeparam>
/// <param name="methodInfo">Action <see cref="MethodInfo"/>.</param>
/// <param name="groupName">Group name.</param>
/// <param name="httpMethod">Http method.</param>
/// <param name="relativePath">Relative path.</param>
/// <param name="parameterDescriptions">Collection of <see cref="ApiParameterDescription"/>.</param>
/// <param name="supportedRequestFormats">Collection of <see cref="ApiRequestFormat"/>.</param>
/// <param name="supportedResponseTypes">Collection of <see cref="ApiResponseType"/>.</param>
/// <returns>
/// Returns <see cref="ApiDescription"/>.
/// </returns>
internal static ApiDescription Create<TController>(
MethodInfo methodInfo,
string groupName = null,
string httpMethod = null,
string relativePath = null,
IEnumerable<ApiParameterDescription> parameterDescriptions = null,
IEnumerable<ApiRequestFormat> supportedRequestFormats = null,
IEnumerable<ApiResponseType> supportedResponseTypes = null)
where TController : new()
{
return Create(
typeof(TController),
methodInfo,
groupName,
httpMethod,
relativePath,
parameterDescriptions,
supportedRequestFormats,
supportedResponseTypes
);
}

private static ActionDescriptor CreateActionDescriptor(MethodInfo methodInfo)
{
var httpMethodAttribute = methodInfo.GetCustomAttribute<HttpMethodAttribute>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@
<NeutralLanguage></NeutralLanguage>
<LangVersion>7.3</LangVersion>
<PackageIconUrl>https://github.com/unchase/Unchase.Swashbuckle.AspNetCore.Extensions/blob/master/assets/icon.png?raw=true</PackageIconUrl>
<Version>2.2.1</Version>
<AssemblyVersion>2.2.1.0</AssemblyVersion>
<FileVersion>2.2.1.0</FileVersion>
<Version>2.2.2</Version>
<AssemblyVersion>2.2.2.0</AssemblyVersion>
<FileVersion>2.2.2.0</FileVersion>
<GeneratePackageOnBuild>false</GeneratePackageOnBuild>
<DocumentationFile>Unchase.Swashbuckle.AspNetCore.Extensions.xml</DocumentationFile>
</PropertyGroup>
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit ce464bb

Please sign in to comment.