From ce464bb7c2ae8f3b8a39fc0aed5c01dec12397f5 Mon Sep 17 00:00:00 2001 From: Chebotov Nikolay Date: Sat, 29 Feb 2020 09:46:00 +0300 Subject: [PATCH] Fix bug with "AmbiguousMatchException". --- CHANGELOG.md | 4 + README.md | 2 + .../Extensions/OpenApiDocumentExtensions.cs | 2 +- .../Factories/ApiDescriptionFactory.cs | 92 ++++++++++++++++--- ...e.Swashbuckle.AspNetCore.Extensions.csproj | 6 +- ...hase.Swashbuckle.AspNetCore.Extensions.xml | 32 +++++++ 6 files changed, 120 insertions(+), 18 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e46e8d4..ccccdb8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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 diff --git a/README.md b/README.md index 439bbd4..55b1917 100644 --- a/README.md +++ b/README.md @@ -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: diff --git a/src/Unchase.Swashbuckle.AspNetCore.Extensions/Extensions/OpenApiDocumentExtensions.cs b/src/Unchase.Swashbuckle.AspNetCore.Extensions/Extensions/OpenApiDocumentExtensions.cs index be64f9a..e0473f9 100644 --- a/src/Unchase.Swashbuckle.AspNetCore.Extensions/Extensions/OpenApiDocumentExtensions.cs +++ b/src/Unchase.Swashbuckle.AspNetCore.Extensions/Extensions/OpenApiDocumentExtensions.cs @@ -54,7 +54,7 @@ public static OpenApiDocument RemovePathsAndComponentsWithoutAcceptedRolesForCon var paths = new Dictionary(); foreach (var methodInfo in typeof(TController).GetMethods().Where(m => !m.IsSpecialName)) { - var actionDescriptor = ApiDescriptionFactory.Create(c => methodInfo.Name, typeof(TController).GetCustomAttribute().Template)?.ActionDescriptor; + var actionDescriptor = ApiDescriptionFactory.Create(methodInfo, typeof(TController).GetCustomAttribute().Template)?.ActionDescriptor; if (actionDescriptor != null) { paths.Add(((Microsoft.AspNetCore.Mvc.Controllers.ControllerActionDescriptor)actionDescriptor).MethodInfo, actionDescriptor.AttributeRouteInfo.Template); diff --git a/src/Unchase.Swashbuckle.AspNetCore.Extensions/Factories/ApiDescriptionFactory.cs b/src/Unchase.Swashbuckle.AspNetCore.Extensions/Factories/ApiDescriptionFactory.cs index b9cd6bc..be373f2 100644 --- a/src/Unchase.Swashbuckle.AspNetCore.Extensions/Factories/ApiDescriptionFactory.cs +++ b/src/Unchase.Swashbuckle.AspNetCore.Extensions/Factories/ApiDescriptionFactory.cs @@ -19,7 +19,7 @@ internal static class ApiDescriptionFactory /// Create . /// /// Type of Controller. - /// Controller action name. + /// Controller action . /// Group name. /// Http method. /// Relative path. @@ -31,7 +31,7 @@ internal static class ApiDescriptionFactory /// internal static ApiDescription Create( Type controllerType, - string actionName, + MethodInfo methodInfo, string groupName = null, string httpMethod = null, string relativePath = null, @@ -39,17 +39,6 @@ internal static ApiDescription Create( IEnumerable supportedRequestFormats = null, IEnumerable supportedResponseTypes = null) { - MethodInfo methodInfo; - - try - { - methodInfo = controllerType.GetMethod(actionName); - } - catch (AmbiguousMatchException) - { - return null; - } - if (methodInfo == null) return null; @@ -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)) { @@ -127,6 +116,45 @@ internal static ApiDescription Create( return apiDescription; } + /// + /// Create . + /// + /// Type of Controller. + /// Controller action name. + /// Group name. + /// Http method. + /// Relative path. + /// Collection of . + /// Collection of . + /// Collection of . + /// + /// Returns . + /// + internal static ApiDescription Create( + Type controllerType, + string actionName, + string groupName = null, + string httpMethod = null, + string relativePath = null, + IEnumerable parameterDescriptions = null, + IEnumerable supportedRequestFormats = null, + IEnumerable supportedResponseTypes = null) + { + MethodInfo methodInfo; + + try + { + methodInfo = controllerType.GetMethod(actionName); + } + catch (AmbiguousMatchException) + { + return null; + } + + return Create(controllerType, methodInfo, groupName, httpMethod, relativePath, parameterDescriptions, + supportedRequestFormats, supportedResponseTypes); + } + /// /// Create . /// @@ -163,6 +191,42 @@ internal static ApiDescription Create( ); } + /// + /// Create . + /// + /// Type of Controller. + /// Action . + /// Group name. + /// Http method. + /// Relative path. + /// Collection of . + /// Collection of . + /// Collection of . + /// + /// Returns . + /// + internal static ApiDescription Create( + MethodInfo methodInfo, + string groupName = null, + string httpMethod = null, + string relativePath = null, + IEnumerable parameterDescriptions = null, + IEnumerable supportedRequestFormats = null, + IEnumerable 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(); diff --git a/src/Unchase.Swashbuckle.AspNetCore.Extensions/Unchase.Swashbuckle.AspNetCore.Extensions.csproj b/src/Unchase.Swashbuckle.AspNetCore.Extensions/Unchase.Swashbuckle.AspNetCore.Extensions.csproj index 6789f7c..d6b5b22 100644 --- a/src/Unchase.Swashbuckle.AspNetCore.Extensions/Unchase.Swashbuckle.AspNetCore.Extensions.csproj +++ b/src/Unchase.Swashbuckle.AspNetCore.Extensions/Unchase.Swashbuckle.AspNetCore.Extensions.csproj @@ -14,9 +14,9 @@ 7.3 https://github.com/unchase/Unchase.Swashbuckle.AspNetCore.Extensions/blob/master/assets/icon.png?raw=true - 2.2.1 - 2.2.1.0 - 2.2.1.0 + 2.2.2 + 2.2.2.0 + 2.2.2.0 false Unchase.Swashbuckle.AspNetCore.Extensions.xml diff --git a/src/Unchase.Swashbuckle.AspNetCore.Extensions/Unchase.Swashbuckle.AspNetCore.Extensions.xml b/src/Unchase.Swashbuckle.AspNetCore.Extensions/Unchase.Swashbuckle.AspNetCore.Extensions.xml index 8c7b3c3..dfc6d91 100644 --- a/src/Unchase.Swashbuckle.AspNetCore.Extensions/Unchase.Swashbuckle.AspNetCore.Extensions.xml +++ b/src/Unchase.Swashbuckle.AspNetCore.Extensions/Unchase.Swashbuckle.AspNetCore.Extensions.xml @@ -78,6 +78,22 @@ factory. + + + Create . + + Type of Controller. + Controller action . + Group name. + Http method. + Relative path. + Collection of . + Collection of . + Collection of . + + Returns . + + Create . @@ -110,6 +126,22 @@ Returns . + + + Create . + + Type of Controller. + Action . + Group name. + Http method. + Relative path. + Collection of . + Collection of . + Collection of . + + Returns . + + Options for response example.