我正在尝试在新的 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 日)
最初我也收到了 500 错误。它在堆栈跟踪的深处说:System.NotSupportedException:路径'api/hotels'的无限HTTP动词。您是否缺少 HttpMethodAttribute?
事实证明,我的一种 api 方法缺少 HttpGet 属性:
[Microsoft.AspNetCore.Mvc.HttpGet]
如果有人想知道确切的错误在 Swagger 的堆栈跟踪中,请请求 URL:
<your-app-url>/swagger/v1/swagger.json
或者,单击浏览器开发工具控制台中的 swagger.json
链接:
https://i.stack.imgur.com/dP0uI.png
这将在您的 IDE 输出中显示错误:
https://i.stack.imgur.com/B4rhl.png
当我的一个函数被标记为 public
时,我收到了这个错误,但这并不是一个可以直接调用的 Web 服务。
将函数更改为 private
使错误消失。
或者,在您的 public
函数之前,您可以放置 [NonAction]
命令,告诉 Swagger 忽略它。
[NonAction]
public async Task<IActionResult> SomeEvent(string id)
{
...
}
(我希望 Swagger 实际上会报告导致此问题的函数的名称,而不仅仅是抱怨它无法再找到“../swagger/v1/swagger.json”文件......这不是特别有用。 )
首先,您可以通过在 Configure() 中添加 app.UseDeveloperExceptionPage();
来启用开发人员异常页面,以便更好地查看根本原因。看看here
就我而言,问题是我还必须安装 Microsoft.AspNetCore.StaticFiles
nuget 才能使 Swagger 正常工作。
也尝试卸载/重新安装 Swashbuckle.AspNetCore
nuget。
我今天遇到了这个问题,原因是我的控制器 API 上的某些方法丢失了 [HttpGet]:
https://i.stack.imgur.com/dNkrl.png
异常(在堆栈跟踪中)向我显示了问题您还可以像这样在 Visual Studio 的输出窗口中检查异常(在我的情况下它向我显示):
https://i.stack.imgur.com/YCQUI.png
如果您无法加载并查看控制台中的 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正确对待,但无法通过招摇来解决。
就我而言,我错过了 API 控制器中存在的路由属性中的一个操作。
像这样的东西:
[Route("api/[controller]/[action]")]
在我有之前:
[Route("api/[controller]")]
编写 [Route("api/[controller]")] 时发生错误,因为 swagger 不知道如何在您的 route 属性内不采取任何操作的情况下分离 API 方法。
有同样的问题,错误消息帮助我确定了根本原因:
{
"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 动词也有相同的路由,这会产生错误。
另外,如果我可以添加,当您在控制器的根级别路由时,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();
}
}
我花了一段时间才弄清楚我收到内部服务器错误的原因是因为这个路由问题。希望这对某人有帮助!
可能很明显,但除了缺少 HttpGet
或 HttpPost
属性外,不要忘记区分 post 方法。
您可能有 2 个不同的方法(具有不同的名称)标有 HttpPost
,这也会导致此类问题。请记住在属性中指定方法名称:[HttpPost("update")]
。
我在 ASP.NET Boilerplate 中遇到同样的错误。我搜索了很多,发现我的代码有问题。我使用同名的两个 DTO 对象,但位于不同的命名空间。
例如第一个 DTO 对象如下所示:
namespaces Test{
public class TestDto
{
public int Id{get;set;}
}
}
第二个 DTO 对象如下所示:
namespaces Test_2{
public class TestDto
{
public int Id{get;set;}
}
}
我更改了 Test_2.TestDto 的名称,之后问题确实为我解决了。
在我的情况下,一个模型与另一个模型具有相同的名称,我修复了更改名称
当我添加参数 Version 时,它可以工作
services.AddSwaggerGen(options =>
{
options.SwaggerDoc("v1", new Info { Title = "My API", Version = "v1" });
});
也有这个问题。就我而言,这是由同一控制器中的两个端点具有相同的路由和方法名称(但参数类型不同)引起的。当然,很明显这可能是不好的做法,所以我更改了端点名称,一切都很好。
在某些情况下,控制器的路由器是重复的。查看上次修改的控制器。
我收到此错误是因为在 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"});
});
我今天在 .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(...)
方法并完成工作要容易得多。
希望对某人有所帮助。
确保我的招摇版本彼此对齐解决了我的问题。由于我开始一个新项目,我将我的 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 按预期工作。
由于我没有看到此处发布的对我有用的解决方案,因此我将为正在进行的线程贡献一个。在我的例子中,Route 属性是在函数级别(不是控制器级别)与 HttpPost/HttpGet 单独设置的。
不正确:
[HttpPost]
[Route("RequestItem/{itemId}")]
正确的:
[HttpPost("RequestItem/{itemId}")]
此外,Swagger 似乎期望成功请求返回 Ok(object) 结果而不是 StatusCode(object) 结果。
对我来说,这是因为有两个具有相同名称但具有不同命名空间的类类型,它们被用作不同控制器中两个不同操作的返回类型!
当我更改其中一个的名称时,问题就解决了!
对我来说,问题是由于 OData。如果我只是注释掉了我的 services.AddOData();我没有收到任何错误。just comment out the services.AddOData();
如果您使用在 .Net Core 5 中默认启用的 Swagger,它需要了解您的方法。通常,您不需要添加 [HttpGet]
属性,因为它是您的方法的默认 HttpMethod
,但 swagger 需要该信息来生成代码文档。
所以在我的方法上方添加 [HttpGet]
解决了我的问题。
在 api 操作之上添加 [HttpGet] 或 [HttpPost]。在 api 操作之上添加 [Reout("YourApiActionName")] ,或在 Controller 类之上添加 [Route("[controller]/[action]")] 。
https://i.stack.imgur.com/VOjI1.png
看看这个项目。 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”文件夹中生成
查看异常的来源
打开 chrome 浏览器
打开开发者工具
在控制台选项卡中查看异常
修理它。
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%" ]
}
}