在 asp .net CORE / MVC 6 应用程序中设置 Swagger 时出现 500 错误

Posted

技术标签:

【中文标题】在 asp .net CORE / MVC 6 应用程序中设置 Swagger 时出现 500 错误【英文标题】:500 Error when setting up Swagger in asp .net CORE / MVC 6 app 【发布时间】:2016-03-04 05:51:54 【问题描述】:

我正在尝试在新的 asp .net CORE / MVC 6 项目中设置基本的 swagger API 文档,并从 swagger UI 收到 500 错误: 500 : http://localhost:4405/swagger/v1/swagger.json

我的启动类中有以下代码:

using Swashbuckle.SwaggerGen;
using Swashbuckle.SwaggerGen.XmlComments;
using Swashbuckle.Application;
....
public void ConfigureServices(IServiceCollection services)

  ...
  services.AddSwaggerGen();
  services.ConfigureSwaggerDocument(options =>
  
    options.SingleApiVersion(new Info
    
        Version = "v1",
        Title = "Blog Test Api",
        Description = "A test API for this blogpost"
    );
  );

然后在配置下:

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)

....
  app.UseSwaggerGen();
  app.UseSwaggerUi();
....

当我构建并运行项目时,当我转到 swagger/UI/index.html 时会出现 UI,但会显示上面的 500 错误。当我转到 swagger/v1/swagger.json 链接时,控制台给出以下 500 错误: Failed to load resource: the server responded with a status of 500 (Internal Server Error)

有什么方法可以找出 500 的根本原因,或者在 swagger 中启用任何额外的调试来找出它为什么会抛出这个错误?根据我看过的一些教程,基本实现只需要我在启动时拥有的东西。如果我可以提供任何其他信息,请告诉我。

编辑:这是针对 rc1 的,可能与当前发布的新 netcore 1.0 无关(2016 年 6 月 29 日)

【问题讨论】:

【参考方案1】:

最初我也收到 500 错误。在堆栈跟踪的深处,它说: System.NotSupportedException:路径“api/hotels”的无限 HTTP 动词。是否缺少 HttpMethodAttribute?

原来我的 api 方法之一缺少 HttpGet 属性:

[Microsoft.AspNetCore.Mvc.HttpGet]

【讨论】:

从哪里获得堆栈跟踪?我只是在我的网络客户端中收到 500 错误,没有更多信息。服务器不会抛出异常。 打开 API 的 Swagger 文档站点时出现错误消息和堆栈跟踪,即myapi.somedomain.com/help/index 谢谢,我的情况是 NoAction 方法 如果方法不应该添加到swagger中,你可以将它保护起来 Swagger 真的应该用自定义错误来处理这个问题。【参考方案2】:

如果有人想知道确切的错误在 Swagger 的堆栈跟踪中,请请求 URL:

<your-app-url>/swagger/v1/swagger.json

或者,从浏览器开发工具控制台点击swagger.json链接:

这将在您的 IDE 输出中显示错误:

【讨论】:

这是找出真正问题所在的完美方式。非常感谢! 希望我能多点赞。网上有很多关于此的帖子,通常是猜测问题所在,而不是关于如何调试的建议。这种调试方法其实就是我想知道的。 不适合我。单击链接或转到地址给了我错误 500。 @ohdev 检查中间件管道的顺序。如果 UseSwagger 出现在任何类型的异常处理/记录之前,则可能导致任何错误都不会被记录 @Sangman 谢谢。我在另一条评论中得到了解决方案,我只需将控制器中的方法访问限定符从公共更改为受保护。就这样。 Swagger 期望控制器中每个公共方法的请求类型属性(HttpPost、HttpGet 等)。【参考方案3】:

当我的一个函数被标记为 public 时,我收到了这个错误,但这并不是一个可以直接调用的 Web 服务。

将函数更改为private 使错误消失。

或者,在您的 public 函数之前,您可以放置​​ [NonAction] 命令,告诉 Swagger 忽略它。

[NonAction]
public async Task<IActionResult> SomeEvent(string id)
 
   ...

(我希望 Swagger 实际上会报告导致此问题的函数的 name,而不仅仅是抱怨它无法再找到“../swagger/v1/ swagger.json" 文件...这不是特别有用。)

【讨论】:

就我而言,我的 BaseController 中的公共方法应该从公共更改为受保护。但你的方法给了我灵感。 我花了很长时间才找到这个解决方案 在我的例子中,我继承了一个 BaseController,它有一些没有这个属性的方法。添加这个属性解决了我的问题。【参考方案4】:

首先,您可以通过在 Configure() 上添加 app.UseDeveloperExceptionPage(); 来启用开发人员异常页面,以便更好地查看根本原因。看看here

就我而言,问题是我还必须安装 Microsoft.AspNetCore.StaticFiles nuget 才能使 Swagger 正常工作。

也尝试卸载/重新安装Swashbuckle.AspNetCorenuget。

【讨论】:

这为我修好了 卸载/重新安装 Swashbuckle.AspNetCore 对我不起作用 我遵循了talkingdotnet.com/add-swagger-to-asp-net-core-2-0-web-api 的指示,但是对于我从 Core 1.1 升级的 API。添加 Microsoft.AspNetCore.StaticFiles 对我有用。【参考方案5】:

如果您无法加载,请查看此处并查看控制台中的 swagger.json。

Swagger 很难协商命名空间之间的差异。在构建预期用于 api 调用的对象时,它将通过每个定义的类进行索引。如果有两个类共享一个类名,它将无法处理 swagger.json 文件。

.Net 将正确处理但 Swagger 不会正确处理的两个类的示例。

namespace MyCompany.PaymentProcessor.DTO


    public class Payment
    
      //dto content
    

namespace MyCompany.CbData


    public class Payment
    
       //couch base data
    

.Net 会正确对待,但 swagger 无法解决。

【讨论】:

这是一个很棒的发现! 感谢这个,我花了 40 分钟才找到错误。因为输出中没有异常。【参考方案6】:

我今天遇到了这个问题,原因是我的控制器 API 上的某些方法丢失了 [HttpGet]:

异常(在堆栈跟踪中)向我展示了问题 您还可以像这样在 Visual Studio 的“输出”窗口中检查异常(在我的例子中它显示给我):

【讨论】:

【参考方案7】:

另外,如果我可以补充一下,当您在控制器的根级别路由时,swagger 设置不喜欢它。例如:

不要这样做:

[Produces("application/json")]
[Route("/v1/myController")]
[Authorize]
public class myController

    [SwaggerResponse((int)System.Net.HttpStatusCode.OK, Type = typeof(RestOkResponse<Response>))]
    [SwaggerResponse((int)System.Net.HttpStatusCode.InternalServerError, Type = typeof(RestErrorResponse))]
    [SwaggerResponse((int)System.Net.HttpStatusCode.BadRequest, Type = typeof(RestErrorResponse))]
    [SwaggerResponse((int)System.Net.HttpStatusCode.Forbidden, Type = typeof(RestErrorResponse))]
    [SwaggerResponse((int)System.Net.HttpStatusCode.NotFound)]
    [HttpPost]
    [Authorize()]
    public async Task<IActionResult> Create([FromBody] MyObject myObject)
    
        return Ok();
    

这样做:

[Produces("application/json")]
[Authorize]
public class myController

    [SwaggerResponse((int)System.Net.HttpStatusCode.OK, Type = typeof(RestOkResponse<Response>))]
    [SwaggerResponse((int)System.Net.HttpStatusCode.InternalServerError, Type = typeof(RestErrorResponse))]
    [SwaggerResponse((int)System.Net.HttpStatusCode.BadRequest, Type = typeof(RestErrorResponse))]
    [SwaggerResponse((int)System.Net.HttpStatusCode.Forbidden, Type = typeof(RestErrorResponse))]
    [SwaggerResponse((int)System.Net.HttpStatusCode.NotFound)]
    [HttpPost("/v1/myController")]
    [Authorize()]
    public async Task<IActionResult> Create([FromBody] MyObject myObject)
    
        return Ok();
    

我花了一段时间才弄清楚我收到内部服务器错误的原因是因为这个路由问题。希望这对某人有帮助!

【讨论】:

【参考方案8】:

可能很明显,但除了缺少HttpGetHttpPost 属性外,别忘了区分post 方法。

您可能有 2 个不同的方法(具有不同的名称)标记为 HttpPost,这也会导致此类问题。记得在属性中指定方法名:[HttpPost("update")]

【讨论】:

【参考方案9】:

遇到了同样的问题,错误消息帮助我确定了根本原因:


  "error": "Conflicting method/path combination \"POST api/calls\" for actions - SMSApi_v2.Controllers.CallController.CreateCall (SMSApi_v2),SMSApi_v2.Controllers.CallController.CreateCalls (SMSApi_v2). Actions require a unique method/path combination for Swagger/OpenAPI 3.0. Use ConflictingActionsResolver as a workaround"

根源是这些代码行:

    **[HttpPost("calls")]**
    public IActionResult CreateCall([FromBody]Call call)
    
        repository.Create(call);
        return Ok(call);
    

    **[HttpPost("calls")]**
    public IActionResult CreateCalls([FromBody] string xmlFile)
    
        var calls = xmlProcessor.DeserializeTo<List<Call>>(xmlFile);
        if (!calls.Any())
            return BadRequest("Deserializing was not done correctly.");

        repository.Create(calls);
        return Ok(calls);
    

即使方法的签名不同,两个 API 动词也有相同的路由,这会产生错误。

【讨论】:

【参考方案10】:

我在 ASP.NET Boilerplate 中遇到同样的错误。我搜索了很多,发现我的代码有问题。我使用同名的两个 DTO 对象,但位于不同的命名空间。

例如第一个 DTO 对象如下:

namespaces Test
    public class TestDto
    
        public int Idget;set;
    

第二个 DTO 对象如下:

namespaces Test_2
    public class TestDto
    
        public int Idget;set;
    

我更改了 Test_2.TestDto 的名称,之后问题确实为我解决了。

【讨论】:

【参考方案11】:

在我的例子中,一个模型与另一个模型具有相同的名称,我修复了更改名称

【讨论】:

【参考方案12】:

在我的情况下,我在你的 API 控制器中缺少路由属性中的一个操作。

类似这样的:

[Route("api/[controller]/[action]")]

在我有之前:

[Route("api/[controller]")]

在编写 [Route("api/[controller]")] 时发生错误,因为 swagger 不知道如何在您的 route 属性内不进行操作的情况下分离 API 方法。

【讨论】:

谢谢,这需要 30 分钟的谷歌搜索才能找到正确的答案 :)【参考方案13】:

当我添加参数 Version 时,它可以工作

services.AddSwaggerGen(options =>
        
            options.SwaggerDoc("v1", new Info  Title = "My API", Version = "v1" );
        );

【讨论】:

【参考方案14】:

查看异常来源

打开 chrome 浏览器 打开开发者工具 在控制台选项卡中查看例外情况 修复它。

【讨论】:

您最好给个适当的解释,而不是要求我们去控制台! 你是对的。我试图解释说没有具体的解决方案。问题的根源可能在控制台消息中。【参考方案15】:

也有这个问题。就我而言,这是由同一控制器中的两个端点具有相同的路由和方法名称(但参数类型不同)引起的。当然,后来很明显这可能是不好的做法,所以我更改了端点名称,一切都很好。

【讨论】:

【参考方案16】:

在某些情况下,控制器的路由器是重复的。查看上次修改的控制器

【讨论】:

您需要检查并检查路由器的控制器...在此之后,再次构建并运行。这只是一个建议。就我而言,这解决了我的问题...【参考方案17】:

我收到此错误是因为在 STARTUP.CS 中我没有将版本名称放在 SwaggerDoc 参数中:

错误 => c.SwaggerDoc("", blablabla

工作 => c.SwaggerDoc("v1",blablabla

那么,现在可以了!

services.AddSwaggerGen(c => 
    
c.SwaggerDoc("v1", new Swashbuckle.AspNetCore.Swagger.Info Title = "PME SERVICES", Version = "v1");
            );

【讨论】:

【参考方案18】:

我今天在 .Net Core 2.2 Web Api 项目中配置 Swagger 时遇到了这个问题。我通过在我的项目中包含Microsoft.AspNetCore.StaticFiles 依赖项开始了@Popa Andrei 上面提到的路径,因为我认为这很可能是罪魁祸首。这变成了链接依赖的兔子洞,尽管它最终对我有用。

然后我意识到,在我的 Startup 中的 ConfigureServices 方法中,我有 services.AddMvcCore(...),它只是为您提供了基本信息,您可以根据需要添加依赖项。当我将其更改为 services.AddMvc(...) 时,它开始工作,而无需手动添加 Microsoft.AspNetCore.StaticFiles 所需的所有依赖项。

这并不意味着您不能选择继续使用services.AddMvcCore(...) 然后添加所有必要的依赖项。你可以,它会起作用的。

采用services.AddMvc(...) 方法并完成工作要容易得多。

希望对某人有所帮助。

【讨论】:

【参考方案19】:

确保我的招摇版本彼此对齐解决了我的问题。因为我开始一个新项目,所以我将我的 api 版本设置为 v0.1

services.AddSwaggerGen(c =>

    c.SwaggerDoc("v0.1", new Info  Title = "Tinroll API", Version = "v0.1" );
);

但我的招摇网址是 v1。

app.UseSwaggerUI(c =>

    c.SwaggerEndpoint("/swagger/v1/swagger.json", "Tinroll API v0.1");
    c.RoutePrefix = string.Empty;
);

我将我的版本更新为 /swagger/v0.1/swagger.json 而不是 v1 并且 Swagger 按预期工作。

【讨论】:

【参考方案20】:

由于我没有看到此处发布的对我有用的解决方案,因此我将为正在进行的线程贡献一个。在我的例子中,Route 属性是在函数级别(不是控制器级别)与 HttpPost/HttpGet 单独设置的。

不正确:

[HttpPost]

[Route("RequestItem/itemId")]

正确:

[HttpPost("RequestItem/itemId")]

此外,Swagger 似乎期望成功请求返回 Ok(object) 结果而不是 StatusCode(object) 结果。

【讨论】:

【参考方案21】:

对我来说,这是因为有两个同名但具有不同命名空间的类类型,它们被用作不同控制器中两个不同操作的返回类型!

当我更改其中一个的名字后,问题就解决了!

【讨论】:

【参考方案22】:

对我来说,问题是由于 OData。如果我只是注释掉了我的 services.AddOData();我没有收到任何错误。just comment out the services.AddOData();

【讨论】:

【参考方案23】:

如果您使用在 .Net Core 5 中默认启用的 Swagger,它需要了解您的方法。通常,您不需要添加 [HttpGet] 属性,因为它是您方法的默认 HttpMethod,但 swagger 需要该信息来生成代码文档。

所以在我的方法上方添加[HttpGet] 解决了我的问题。

【讨论】:

【参考方案24】:

看看这个项目。 https://github.com/domaindrivendev/Ahoy/tree/master/test/WebSites/Basic

这个 repo 来自 Swashbuckle 的所有者,是一个基本的 ASP.NET 5 示例应用程序,它可以帮助您正确配置您的中间件(并注意它们的顺序,这很重要,例如,使用“ app.UseSwaggerGen();app.UseSwaggerUi(); 在 app.UseMvc();) 之后

要在您的应用程序中启用日志记录,请查看: https://docs.asp.net/en/latest/fundamentals/logging.html?highlight=logging (日志将在“wwwroot”文件夹中生成

【讨论】:

我试图让它与我真正想添加 swashbuckle 的项目一起工作,但它就是行不通。我认为控制器路由中可能有一些东西导致它挂断。按照上面的操作,我可以将它添加到一个新的.net 项目中,没有任何问题。我遇到的问题绝对是项目特定的。将标记为已接受的答案,如果我能找出导致问题的具体路线,我将更新原始问题。谢谢!【参考方案25】:

Swagger 的设置因版本而异。这个答案适用于 Swashbuckle 6.0.0-beta9 和 Asp.Net Core 1.0。在 Startup.cs 的 ConfigureServices 方法中,需要添加 -

 services.AddSwaggerGen(c =>
    
      c.SingleApiVersion(new Info
      
        Version = "v1",
        Title = "My Awesome Api",
        Description = "A sample API for prototyping.",
        TermsOfService = "Some terms ..."
      );
    );

然后在Configure方法中你必须添加-

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)

    loggerFactory.AddConsole(Configuration.GetSection("Logging"));
    loggerFactory.AddDebug();

    app.UseMvc();
    app.UseSwaggerGen();
    app.UseSwaggerUi();

确保您在 Startup.cs 中引用 -

使用 Swashbuckle.SwaggerGen.Generator;

我的 project.json 文件看起来像 -

"dependencies": 
    "Microsoft.AspNetCore.Mvc": "1.0.0-rc2-final",
    "Microsoft.AspNetCore.Server.IISIntegration": "1.0.0-rc2-final",
    "Microsoft.AspNetCore.Server.Kestrel": "1.0.0-rc2-final",
    "Microsoft.EntityFrameworkCore.SqlServer": "1.0.0-rc2-final",
    "Microsoft.EntityFrameworkCore.SqlServer.Design": "1.0.0-rc2-final",
    "Microsoft.EntityFrameworkCore.Tools": "1.0.0-*",
    "Microsoft.Extensions.Configuration.EnvironmentVariables": "1.0.0-rc2-final",
    "Microsoft.Extensions.Configuration.FileExtensions": "1.0.0-rc2-final",
    "Microsoft.Extensions.Configuration.Json": "1.0.0-rc2-final",
    "Microsoft.Extensions.Logging": "1.0.0-rc2-final",
    "Microsoft.Extensions.Logging.Console": "1.0.0-rc2-final",
    "Microsoft.Extensions.Logging.Debug": "1.0.0-rc2-final",
    "Swashbuckle": "6.0.0-beta9"
  ,

  "tools": 
    "Microsoft.AspNetCore.Server.IISIntegration.Tools": 
      "version": "1.0.0-preview1-final",
      "imports": "portable-net45+win8+dnxcore50"
    ,
    "Microsoft.EntityFrameworkCore.Tools": 
      "version": "1.0.0-preview1-final",
      "imports": [
        "portable-net45+win8+dnxcore50",
        "portable-net45+win8"
      ]
    
  ,

  "frameworks": 
    "net452":  
  ,
  "buildOptions": 
    "emitEntryPoint": true,
    "preserveCompilationContext": true,
    "xmlDoc": false
  ,

  "publishOptions": 
    "include": [
      "wwwroot",
      "Views",
      "appsettings.json",
      "web.config"
    ]
  ,

  "scripts": 
    "postpublish": [ "dotnet publish-iis --publish-folder %publish:OutputPath% --framework %publish:FullTargetFramework%" ]
  

【讨论】:

以上是关于在 asp .net CORE / MVC 6 应用程序中设置 Swagger 时出现 500 错误的主要内容,如果未能解决你的问题,请参考以下文章

ASP.NET MVC Core/6:多个提交按钮

ASP.NET Core MVC 之依赖注入 Controller

在 asp .net CORE / MVC 6 应用程序中设置 Swagger 时出现 500 错误

ASP.NET Core 6框架揭秘实例演示[02]:基于路由MVC和gRPC的应用开发

ASP.NET MVC Core/6:EF 6 脚手架错误

在 asp.net core 5 MVC 视图中从 C# 代码调用 JavaScript 函数