Swashbuckle/Swagger + ASP.Net核心:"无法加载API定义"

Ash*_*Ash 28 c# swagger swashbuckle asp.net-core

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

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

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

无法加载API定义.

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

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

为什么Swagger表现得这样?

我可以使用任何配置吗?

小智 24

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

  • 这在我的例子中有效:有几个使用 GET 的公共 Action 方法,但没有明确地这样做 (2认同)

dan*_*nsc 11

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

[Route("images")]
[HttpGet("{id}")]
Run Code Online (Sandbox Code Playgroud)

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

[HttpGet("images/{id}")]
Run Code Online (Sandbox Code Playgroud)

HttpPost 也是如此。


Hel*_*eda 10

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

这是实际的错误:

System.NotSupportedException: Ambiguous HTTP method for action
Run Code Online (Sandbox Code Playgroud)

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

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

  • 对于 ASP.net core 3,我必须将 ResolveConflictingActions 添加到启动 > c.ResolveConflictingActions(apiDescriptions => apiDescriptions.First()); 中的 AddSwaggerGen 部分; (3认同)

rjs*_*jso 10

与其盲目猜测可能是什么问题,不如导航到

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

在此处输入图片说明

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

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

  • 这对我帮助很大!导航到 http://localhost:PORT/swagger/v1/swagger.json 并收到更详细的错误消息。 (2认同)

小智 7

我不知道这是否已经解决,但是您可以通过以下方法装饰方法之一:

[ApiExplorerSettings(IgnoreApi = true)]
Run Code Online (Sandbox Code Playgroud)

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


Hos*_*Rad 7

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

在此处输入图片说明


Pad*_*mac 6

除了 Helder Sepulvedas 的回答和来自 'Monte-Christos' 在这个 github 问题中的回答 -动作需要 Swagger 的独特方法/路径组合

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

services.AddSwaggerGen(c => 
  { 
    other configs...;
    c.ResolveConflictingActions(apiDescriptions => apiDescriptions.First());
  });
Run Code Online (Sandbox Code Playgroud)

这对我来说成功了!


小智 6

默认 api 控制器路由配置是导致此问题的原因。当我们在 ASP.NET Core API 应用程序中添加 API 控制器时,默认情况下它具有特定于控制器的路由,这意味着它只能支持每个 HTTP 动词 Post、PUT、Delete、GET 和 Patch 的单个方法。

当我们需要在单个控制器中创建多个具有 Http 动词 Post、PUT、Delete、GET 和 Patch 的方法时,可能会有这样的需求,如果您使用默认路由配置创建方法,那么您将得到加载 Swagger UI 时出现以下错误。

在此输入图像描述

解决方案是,当您使用 HTTP 动词“post”、“put”和“get”创建多个方法时,必须在控制器级别更改默认路由配置。删除或放入单个 API 控制器类。

考虑以下示例:我创建了 ASP.NET Core API 应用程序,该应用程序默认有一个 Get 方法 GetWeatherForecast,它返回 WeatherForecast。然后我在默认 API Controller 类中又添加了一个名为 WeatherForecastByCity 的 Get 方法,而不修改默认路由。

 [ApiController]
[Route("[controller]")]
public class WeatherForecastController : ControllerBase
{
    private static readonly string[] Summaries = new[]
    {
    "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
};

    private readonly ILogger<WeatherForecastController> _logger;

    public WeatherForecastController(ILogger<WeatherForecastController> logger)
    {
        _logger = logger;
    }

    [HttpGet(Name = "GetWeatherForecast")]
    public IEnumerable<WeatherForecast> Get()
    {
        return Enumerable.Range(1, 5).Select(index => new WeatherForecast
        {
            Date = DateTime.Now.AddDays(index),
            TemperatureC = Random.Shared.Next(-20, 55),
            Summary = Summaries[Random.Shared.Next(Summaries.Length)]
        })
        .ToArray();
    }

    [HttpGet(Name = "WeatherForecastByCity")]
    public IEnumerable<WeatherForecast> Get(string city)
    {
        return Enumerable.Range(1, 5).Select(index => new WeatherForecast
        {
            Date = DateTime.Now.AddDays(index),
            TemperatureC = Random.Shared.Next(-20, 55),
            Summary = Summaries[Random.Shared.Next(Summaries.Length)]
        })
        .ToArray();
    }
}
Run Code Online (Sandbox Code Playgroud)

当我们运行应用程序时,我们将收到 Swagger 加载错误,

在此输入图像描述

现在更改控制器级别的默认路由,该路由可以在单个控制器中支持多个具有 Http 动词 Post、PUT、Delete、GET 和 Patch 的方法。

[Route("api/[controller]/[action]")]
Run Code Online (Sandbox Code Playgroud)

另外,从 HTTP 动词中删除方法的名称,该名称是使用 Name 属性定义的;只需定义 HTTP 动词和正确的方法名称即可。

更改自

 [HttpGet(Name = "GetWeatherForecast")]
    public IEnumerable<WeatherForecast> Get()
    {
        return Enumerable.Range(1, 5).Select(index => new WeatherForecast
        {
            Date = DateTime.Now.AddDays(index),
            TemperatureC = Random.Shared.Next(-20, 55),
            Summary = Summaries[Random.Shared.Next(Summaries.Length)]
        })
        .ToArray();
    }
Run Code Online (Sandbox Code Playgroud)

 [HttpGet]
    public IEnumerable<WeatherForecast> GetWeatherForecast()
    {
        return Enumerable.Range(1, 5).Select(index => new WeatherForecast
        {
            Date = DateTime.Now.AddDays(index),
            TemperatureC = Random.Shared.Next(-20, 55),
            Summary = Summaries[Random.Shared.Next(Summaries.Length)]
        })
        .ToArray();
    }
Run Code Online (Sandbox Code Playgroud)

完整代码

 [ApiController]
[Route("api/[controller]/[action]")]
public class WeatherForecastController : ControllerBase
{
    private static readonly string[] Summaries = new[]
    {
    "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
};

    private readonly ILogger<WeatherForecastController> _logger;

    public WeatherForecastController(ILogger<WeatherForecastController> logger)
    {
        _logger = logger;
    }

    [HttpGet]
    public IEnumerable<WeatherForecast> GetWeatherForecast()
    {
        return Enumerable.Range(1, 5).Select(index => new WeatherForecast
        {
            Date = DateTime.Now.AddDays(index),
            TemperatureC = Random.Shared.Next(-20, 55),
            Summary = Summaries[Random.Shared.Next(Summaries.Length)]
        })
        .ToArray();
    }

     [HttpGet]
    public IEnumerable<WeatherForecast> WeatherForecastByCity(string city)
    {
        return Enumerable.Range(1, 5).Select(index => new WeatherForecast
        {
            Date = DateTime.Now.AddDays(index),
            TemperatureC = Random.Shared.Next(-20, 55),
            Summary = Summaries[Random.Shared.Next(Summaries.Length)]
        })
        .ToArray();
    }
}
Run Code Online (Sandbox Code Playgroud)

现在,更改默认路由后再次运行应用程序,您将看到 swagger 加载,没有任何问题。

在此输入图像描述


小智 5

如果控制器中存在不是操作的公共方法,Swagger 也会抛出相同的异常。解决方法是使所有这些protectedprivate或如上所述添加属性[ApiExplorerSettings(IgnoreApi = true)]

  • 我有一个带有公共辅助函数的控制器的基类,您的建议通过使其“受保护”解决了该问题。 (2认同)

Eri*_*ick 5

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

我有:

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

我不得不使用:

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

});
Run Code Online (Sandbox Code Playgroud)

  • 另一个解决方案是使用 `c.SwaggerEndpoint("v1/swagger.json", "V1 Docs");`。这应该适用于相对和绝对 URL。 (2认同)

hos*_*ora 5

就我而言,我使用此代码就像 .net 代码一样

[ActionName("Login")]
[HttpPost]
Run Code Online (Sandbox Code Playgroud)

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

[HttpPost("Login")]
Run Code Online (Sandbox Code Playgroud)

而且效果很好