【问题标题】:Swashbuckle/Swagger + ASP.Net Core: "Failed to load API definition"Swashbuckle/Swagger + ASP.Net Core:“加载 API 定义失败”
【发布时间】:2018-10-16 23:02:10
【问题描述】:

我开发了一个 ASP.NET Core 2 应用程序并包含 Swagger。一切正常,直到我引入了一个没有明确定义 HTTP 操作的方法:

public class ErrorController : Controller
{
    [Route("/error")]
    public IActionResult Index()
    {
        return StatusCode(500, new Error("Internal error."));
    }
}

当我使用这种方法启动应用程序时,出现以下消息:

未能加载 API 定义。

错误
获取错误内部服务器错误/swagger/v1/swagger.json

只要我明确设置例如[HttpGet] 错误消失。问题是,我需要这个方法来触发所有可能的 HTTP 操作。 当然,我可以明确指定所有操作,但我觉得 Swagger 应该能够正确处理。

为什么 Swagger 会这样?

有什么可以使用的配置吗?

【问题讨论】:

  • '我需要这个方法来触发所有可能的 HTTP 操作'为什么你需要支持所有方法,而不仅仅是 GET?
  • 你能分享一下你的 Swashbuckle 配置吗?
  • @Set 在这种情况下,Error 端点用作异常处理程序。根据请求的 HTTP 操作,调用Error 端点上的相应操作。
  • @HelderSepu 配置非常简单:services.AddSwaggerGen(c => { c.SwaggerDoc("v1", new Info { Title = "My Service", Version = "v1" }); }); app.UseSwagger(c => { c.PreSerializeFilters.Add((swagger, httpReq) => swagger.Host = httpReq.Host.Value); }); app.UseSwaggerUI(c => { c.RoutePrefix = "swagger"; // serve the UI at root c.SwaggerEndpoint("/swagger/v1/swagger.json", "V1 Docs"); });
  • 我设法重现了您的问题,看起来像 Swashbuckle.AspNetCore 中的错误,ResolveConflictingActions 应该可以工作

标签: c# asp.net-core swagger swashbuckle


【解决方案1】:

ResolveConflictingActions 选项应该适用于这种情况...

这是实际的错误:

System.NotSupportedException: Ambiguous HTTP method for action

这来自: https://github.com/domaindrivendev/Swashbuckle.AspNetCore/blob/86cc761bc4f5dda796f80ad8dfd8bc205542a6f6/src/Swashbuckle.AspNetCore.SwaggerGen/Generator/SwaggerGenerator.cs#L90

我认为这是一个错误,如果你真的感兴趣,你应该向项目报告它

【讨论】:

  • 对于 ASP.net core 3,我必须在启动时将 ResolveConflictingActions 添加到我的 AddSwaggerGen 部分 > c.ResolveConflictingActions(apiDescriptions => apiDescriptions.First());
  • 是的,就我而言,我为两个不同的 API 保留了相同的 URL。
  • 就我而言,我在 ApiController 中定义了两个 [HttpGet],Swagger 会感到困惑,但如果我定义了 [HttpGet("myMethod1")] 和 [HttpGet("myMethod2")],那么,大摇大摆明白。我仅将 ResolveConflictingActions 视为一个补丁。希望对您有所帮助。
【解决方案2】:

我不知道这是否已解决,但您可以解决此问题的一种方法是使用以下方法装饰方法:

[ApiExplorerSettings(IgnoreApi = true)]

这将确保 Swagger 忽略相关方法。

【讨论】:

    【解决方案3】:

    为每个 Action 方法添加 Httpxxx([HttpGet], [HttpPost], ...) 属性,或者[ApiExplorerSettings(IgnoreApi = true)]

    【讨论】:

    • 这在我的情况下有效:有几个使用 GET 的公共 Action 方法,但没有明确如此
    • 因为这个答案有助于人们来到这个页面寻找错误,即使原因与 OP 不同
    【解决方案4】:

    我正在删除一个未使用的类上的TypeLoadException。我的解决方法是删除 bin/obj/Debug 文件夹的内容。清洁解决方案 + 重建解决方案没有为我解决。

    【讨论】:

      【解决方案5】:

      如果控制器中有非操作的公共方法,Swagger 也会抛出相同的异常。解决方法是使它们全部变为protectedprivate 或如上所述添加属性[ApiExplorerSettings(IgnoreApi = true)]

      【讨论】:

      • 我有一个带有公共辅助函数的控制器基类,您的建议通过将其设置为protected 解决了这个问题。
      【解决方案6】:

      我也收到了这个错误,因为我创建了一个控制器,它有 [Route("api/[controller]")]。放上之后,错误就消失了。

      app.UseSwagger()
         .UseSwaggerUI(c =>
         {
             c.SwaggerEndpoint("/swagger/v1/swagger.json", "DOA.API V1");
         });
      

      【讨论】:

        【解决方案7】:

        在 ASP.NET Core 中,如果有一个控制器端点,例如:

        [Route("images")]
        [HttpGet("{id}")]
        

        这也可能因 fetch failed 而失败。解决方案是有类似的东西

        [HttpGet("images/{id}")]
        

        HttpPost 也是如此。

        【讨论】:

          【解决方案8】:

          另一个可能的问题是端点需要从域根目录完成。

          我有:

          app.UseSwaggerUI(c =>
          {
               c.SwaggerEndpoint("/swagger/v1/swagger.json", "V1 Docs");
          });
          

          我不得不使用:

           app.UseSwaggerUI(c=>
          {
               c.SwaggerEndpoint("/myApi/swagger/v1/swagger.json", "V1 Docs");
          
          });
          

          【讨论】:

          • 另一种解决方案是使用c.SwaggerEndpoint("v1/swagger.json", "V1 Docs");。这应该适用于相对和绝对网址。
          • 这是我造成问题的原因
          • 这个c.SwaggerEndpoint("v1/swagger.json", "V1 Docs"); 为我工作。
          【解决方案9】:

          我的错误原因是相同的网址名称,

           [HttpGet("get/LeaveCommand/{id}")]
          

          我使用相同的 url 并且招摇不能得到它们

           [HttpGet("get/LeaveCommand/{id}")]
          

          【讨论】:

            【解决方案10】:

            您只需在输出窗口中查看日志。在我的例子中可以看到实际的错误,我错过了在方法之上添加 HTTP 操作

            【讨论】:

            • 是的,当 swagger load 按下 f12 然后我们得到了更多细节:)
            • 这帮助我找到了答案。问题是控制器中的public 辅助方法。将其更改为 protected - 再次生成 swagger 文件。
            【解决方案11】:

            除了 Helder Sepulvedas 的回答和来自 'Monte-Christos' 在这个 github 问题上的回答 - Actions require unique method/path combination for Swagger

            我找到了在 ASP.NET 中配置 ResolveConflictingActions 的地方 核心应用。在您的 Setup 类中,将此添加到 ConfigureServices() 方法:

            services.AddSwaggerGen(c => 
              { 
                other configs...;
                c.ResolveConflictingActions(apiDescriptions => apiDescriptions.First());
              });
            

            这对我来说成功了!

            【讨论】:

              【解决方案12】:

              仔细检查,如果您在同一个控制器中使用了相同的 url 名称。我的代码发生了这种情况

              【讨论】:

                【解决方案13】:

                对我有用的是将 [NonAction] 属性添加到 public 方法中,这些方法不是我的控制器包装器中的 API 调用。

                【讨论】:

                • 就我而言,我的 BaseController 中的公共方法应该从公共更改为受保护。但你的方法给了我灵感。
                【解决方案14】:

                就我而言,这是因为 Newtonsoft.Json 而发生的。但问题是我没有使用它。其中一个软件包可能取决于它,但我没有时间检查。

                所以只需检查输出面板即可解决相关问题。

                【讨论】:

                  【解决方案15】:

                  在我的例子中,我使用这个代码就像 .net 代码一样

                  [ActionName("Login")]
                  [HttpPost]
                  

                  现在我将其更改为在 net core web api 上使用

                  [HttpPost("Login")]
                  

                  而且效果很好

                  【讨论】:

                    【解决方案16】:

                    我有同样的问题。就我而言,我所有的控制器都继承自 BaseController。在这个基类中,我得到了一个根据声明返回 UserId 的公共操作。我在此操作的顶部设置了 [NonAction] 属性。

                    [ApiController]
                    [ApiResultFilter]
                    [Route("api/[controller]")]
                    [Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]
                    
                    public class BaseController : ControllerBase
                    {
                    
                        [NonAction]
                        public int GetCurrentUserId()
                        {
                            return int.Parse(this.User.Claims.First(p => p.Type == ClaimTypes.NameIdentifier).Value);
                        }
                    }
                    

                    【讨论】:

                      【解决方案17】:

                      不要盲目猜测可能是什么问题,而是导航到

                      http:///swagger/v1/swagger.json

                      在我的情况下,这可以通过使用 c.CustomSchemaIds(x => x.FullName);

                      这是一个可怕的解决方法,但对于有需要的人来说可能是一个快速的解决方案。我的解决方案是重命名并阐明这些端点的路径

                      【讨论】:

                      • 这对我帮助很大!导航到localhost:PORT/swagger/v1/swagger.json 并收到更详细的错误消息。
                      • 与@JohanThorild 相同 - JSON 错误消息指向我的控制器中的一个公共方法,Swagger 认为它是一个 API 调用。将其更改为私有 - 已修复!
                      【解决方案18】:

                      我也有这个问题。我检查并应用了所有用于 swagger 配置的解决方案,但问题仍然存在。 最后查看了输出面板,问题出在[DefaultValue("SYSDATETIMEOFFSET()")]

                      答案就在这里:检查输出面板,你会找到答案

                      【讨论】:

                        【解决方案19】:

                        如果您的模型(请求或响应)中具有继承/实现类型如 System.ComponentModel(或其他类型)的类型属性,则会引发错误

                        "The JSON property 'item' is defined multiple times on type"...
                        

                        尝试使用Newtonsoft.Json[JsonIgnore] 属性忽略此属性

                        在我的例子中,我有一个 DataTable 类型的吸气剂

                        【讨论】:

                          【解决方案20】:

                          您需要确保在启动文件中添加

                          services.AddSwaggerDocument();
                          

                          添加之前

                          app.UseOpenApi();
                          app.UseSwaggerUi3();
                          

                          否则会导致此错误

                          获取错误未定义/swagger/{documentName}/swagger.json

                          【讨论】:

                            【解决方案21】:

                            对于核心 3,我遇到了同样的问题,并且真的很困惑问题出在斜线中。

                            配置是:

                            services.AddSwaggerGen(c =>
                                        {
                                            c.SwaggerDoc("v1", new OpenApiInfo { Title = "my-API", Version = "v1" });
                                        });
                            

                            这个swagger端点抛出了TS的消息:

                            app.UseSwaggerUI(c =>
                                        {
                                            c.SwaggerEndpoint("/v1/swagger.json", "my-API v1");
                                        });
                            

                            最后我成功地删除了 URL 中的第一个斜杠:

                            app.UseSwaggerUI(c =>
                                        {
                                            c.SwaggerEndpoint("v1/swagger.json", "my-API v1");
                                        });
                            

                            【讨论】:

                              猜你喜欢
                              • 2021-06-03
                              • 1970-01-01
                              • 1970-01-01
                              • 2018-09-18
                              • 1970-01-01
                              • 2019-06-12
                              • 1970-01-01
                              • 1970-01-01
                              • 1970-01-01
                              相关资源
                              最近更新 更多