Swashbuckle/Swagger + ASP.Net Core: "Failed to load API definition" Swashbuckle/Swagger与ASP.NET Core:API定义加载失败

129

我开发了一个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 会出现这种行为?

是否有任何配置可供使用?


1
我需要这个方法对所有可能的HTTP操作进行触发。为什么你需要支持所有方法,而不仅仅是GET? - Set
你能分享一下你的Swashbuckle配置吗? - Helder Sepulveda
在这种情况下,@Set将Error端点用作异常处理程序。根据请求的HTTP操作,调用Error端点上的相应操作。 - Ash
1
@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"; // 在根目录下提供UI c.SwaggerEndpoint("/swagger/v1/swagger.json", "V1 Docs"); }); - Ash
在我的情况下,这是因为我在两个API中使用了相同的路由,所以我纠正了它,为每个API使用了唯一的路由,然后它就正常工作了。 - undefined
显示剩余2条评论
36个回答

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

2
这在我的情况下起作用了:有几个公共的 Action 方法使用了 GET,但没有明确指定。 - Robert Dundon
因为这个答案对于那些因错误而来到此页面的人们是有帮助的,即使原因与 OP 不完全相同。 - Eric Brown - Cal
使用 [ApiExplorerSettings(IgnoreApi = true)],当我只需要针对 "/Error" 路由时,它完美地发挥了作用。谢谢! - Rohwedder

85

你可以直接查看输出窗口的日志,那里可以看到实际的错误。在我的情况下,我忘记在某些方法之上添加HTTP操作。

在此输入图片描述


是的,当Swagger加载时,请按F12,然后我们会得到更多详细信息 :) - mbielecki1
这帮助我找到了答案。问题出在控制器中的一个public辅助方法上。将其更改为protected - Swagger文件再次生成。 - JsAndDotNet

46

不要盲目猜测问题出在何处,导航至

http://localhost:PORT/swagger/v1/swagger.json

enter image description here

在我的情况下,可以通过使用c.CustomSchemaIds(x => x.FullName)来解决这个问题,虽然这是一个可怕的解决方法,但对于需要快速修复的人来说可能是一个快速解决方案。我的解决方案是重命名并澄清这些端点的路径。

8
这对我帮助很大!我访问了http://localhost:PORT/swagger/v1/swagger.json并得到了更详细的错误信息。 - JohanThorild
和 @JohanThorild 一样 - JSON 错误消息指向了我的控制器中 Swagger 认为是 API 调用的公共方法。将其更改为私有 - 解决了! - Thane Plummer
谢谢,那帮了我。 - Juver Paredes
正确的做法是导航到JSON位置以获取错误信息。 - toha

41

5
针对 ASP.net core 3,我需要在启动时的 AddSwaggerGen 部分中添加 ResolveConflictingActions。具体操作为:c.ResolveConflictingActions(apiDescriptions => apiDescriptions.First())。 - Paddymac
1
是的,在我的情况下,我为两个不同的API保留了相同的URL。 - Soni Vimalkumar
1
在我的情况下,我在我的ApiController中定义了两个[HttpGet],这让Swagger感到困惑,但如果我定义[HttpGet(“myMethod1”)]和[HttpGet(“myMethod2”)],那么Swagger就能理解了。我认为ResolveConflictingActions只是一个补丁。希望这有所帮助。 - Aquiles

21

我不知道这个问题是否已经解决了,但您可以通过在该方法上添加装饰器来处理:

[ApiExplorerSettings(IgnoreApi = true)]

这将确保 Swagger 忽略所讨论的方法。


16

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

我有:

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

我必须使用:

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

});

4
另一个解决方案是使用 c.SwaggerEndpoint("v1/swagger.json", "V1 Docs");。这应该适用于相对和绝对 URL。 - pawellipowczan
1
这就是导致我的问题的原因。 - Carlo Luther
这个 c.SwaggerEndpoint("v1/swagger.json", "V1 Docs"); 对我很有效。 - Md Farid Uddin Kiron
我也是这样做的,加了前导斜杠就可以了。不过我不确定为什么,我的其他微服务没有这个问题。opts.SwaggerEndpoint("/v1/download/swagger.json", "Download");编辑:看起来是我的一个控制器末尾有一个斜杠。[Route("api/v1/my-endpoint/")] - Donkoid

13
在 ASP.NET Core 中,如果存在以下控制器端点: ```html

In ASP.NET Core, if there is a controller endpoint like:

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

这也可能由于“fetch failed”失败而导致。解决方法是需要像下面这样的内容:

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

HttpPost也是一样的。


10

除了Helder Sepulvedas的答案外,还有'Monte-Christos'在github问题中的答案 - Swagger需要唯一的方法 / 路径组合

我发现在ASP.NET Core应用程序中配置ResolveConflictingActions的位置。 在您的Setup类中,将其添加到ConfigureServices()方法中:

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

这对我来说解决了问题!


6

如果控制器中存在公共方法不是action,Swagger也会抛出相同的异常。解决方法是将它们全部修改为 protected 或者 private,或者像上面提到的那样添加属性 [ApiExplorerSettings(IgnoreApi = true)]


3
我有一个基类用于控制器,并带有一个公共的辅助函数,你的建议通过将其改为“protected”解决了这个问题。 - ΩmegaMan

5

在我的情况下,我使用这段代码就像使用.NET代码一样。

[ActionName("Login")]
[HttpPost]

现在我将其更改以在.NET Core Web API上使用

[HttpPost("Login")]

它能正常工作


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接