Swashbuckle/Swagger .NET Core 2.1 自升级后已停止工作
Swashbuckle/Swagger on .NET Core 2.1 has stopped working since upgrade
我有一个 .NET Core 2.0 应用程序,使用 Swashbuckle/Swagger 生成 API 文档。当我们使用 2.1.0 预览版时,Swagger 运行良好。然后我们对 2.1.0 版本和 SDK 2.1.300 进行了重大升级。我们没有注意到事情发生的确切时间,但现在我们的 Swagger 文档不会加载。这是我们看到的:
项目引用了 Swashbuckle.AspNetCore
版本 2.5.0。 Startup.cs
中的相关代码如下。在 ConfigureServices()
:
services.AddSwaggerGen(swaggerOptions =>
{
// Register a swagger doc
swaggerOptions.SwaggerDoc("v1", new Info
{
// Optional descriptive info that will be included in the Swagger output
Contact = new Contact
{
Name = "LightSail",
Url = "https://myurl.com/"
},
Description = "A description of the API can go here",
Title = "My API",
Version = "v1"
});
// Xml file to get comment information from
swaggerOptions.IncludeXmlComments("App_Data/Api.xml");
});
在Configure()
中:
app.UseSwagger();
app.UseSwaggerUI(swaggerUiOptions => swaggerUiOptions.SwaggerEndpoint("/swagger/v1/swagger.json", "My API v1"));
我发现了很多其他类似的问题,其中一个提示可能存在重复的端点;我尝试添加对 .ResolveConflictingEndpoints()
的调用,但这没有任何区别。我搜索了我的项目文件夹,没有名为 swagger.json
的文件,所以我猜这就是问题所在。
为什么这不起作用,或者如何解决?
就我而言,我可以通过省略“.”来重现您的错误。从你所做的终点开始。
如果我包含“.”,我不会收到错误消息。在路径的开始。
这是我的更多代码,以防相关。
在 ConfigureServices 我有
services.AddSwaggerGen(c =>
{
c.OperationFilter<AuthorizationHeaderParameterOperationFilter>();
c.SwaggerDoc("v1", new Info
{
Version = "v1",
Title = "My API",
Description = "ASP.NET Core Web API",
TermsOfService = "None",
Contact = new Contact
{
Name = "my name",
Email = "me@myemail.com"
}
});
});
在配置中
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
app.UseAuthentication();
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseDatabaseErrorPage();
}
else
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseCookiePolicy();
app.UseRewriter(new RewriteOptions()
.AddRedirectToHttpsPermanent());
app.UseSwagger(c =>
{
c.RouteTemplate =
"api-docs/{documentName}/swagger.json";
});
app.UseSwaggerUI(c =>
{
//Include virtual directory if site is configured so
c.RoutePrefix = "api-docs";
c.SwaggerEndpoint("./v1/swagger.json", "Api v1");
});
app.UseMvc(routes =>
{
routes.MapRoute(
"default",
"{controller=Home}/{action=Index}/{id?}");
});
还有
public class AuthorizationHeaderParameterOperationFilter : IOperationFilter
{
public void Apply(Operation operation, OperationFilterContext context)
{
var filterPipeline = context.ApiDescription.ActionDescriptor.FilterDescriptors;
var isAuthorized = filterPipeline.Select(filterInfo => filterInfo.Filter).Any(filter => filter is AuthorizeFilter);
var allowAnonymous = filterPipeline.Select(filterInfo => filterInfo.Filter).Any(filter => filter is IAllowAnonymousFilter);
if (isAuthorized && !allowAnonymous)
{
if (operation.Parameters == null)
operation.Parameters = new List<IParameter>();
operation.Parameters.Add(new NonBodyParameter
{
Name = "Authorization",
In = "header",
Description = "access token",
Required = true,
Type = "string"
});
}
}
我的依赖项是
Microsoft.AspNetCore.App (2.1.0)
Swashbuckle.AspNetCore (2.5.0)
Microsoft.NETCore.App (2.1.0)
这通常表示 controllers/actions Swashbuckle 出于某种原因不支持。
预计您的项目中没有 swagger.json 文件。 Swashbuckle 使用 ASP.NET Core 的 ApiExplorer API 动态创建和提供服务。这里可能发生的事情是 Swashbuckle 无法生成 Swagger.json,因此 UI 无法显示。
正如 HelderSepu 所说,很难确切地知道是什么导致了失败,所以最好的调试方法可能只是删除一半的控制器(只需将文件移动到一个临时位置)并检查问题是否仍然存在。然后你就会知道你的控制器的哪一半包含麻烦的动作。您可以 'binary search' 删除控制器(然后是操作),直到您找出导致 Swashbuckle 无法生成的操作方法 Swagger.json。一旦您知道这一点,就很明显这是您代码中的某个问题还是应该在 Swashbuckle repo.
中提交的问题
例如,Swashbuckle 似乎不支持开放泛型,因此具有 [ResponseType(typeof(IEnumerable<>))]
之类的响应类型属性可能会导致此类行为。这也可能是路线不明确或类似绊倒 Swashbuckle 的问题。一旦您将故障原因缩小到更具体的原因,就可以根据需要修复或归档。
我能够通过将 http 动词属性显式添加到我的 asp.net 核心 2.x 控制器方法来解决此错误。在方法名称前加上 http 动词的惯例显然对 Swashbuckle 来说不够。
[HttpPost]
public async Task<IActionResult> AddNewData([FromBody] MyType myType) { … }
就我个人而言,我有点快,忘记将此行添加到 Startup.cs 中的方法 ConfigureServices 中。
services.AddSwaggerDocument();
就我而言,我错过了 'HttpAttribute':
public async Task<IEnumerable<ClientesListDto>> GetAll()
{
return await _service.GetAllAsync();
}
那我放上去招摇点赞:
[HttpGet]
public async Task<IEnumerable<ClientesListDto>> GetAll()
{
return await _service.GetAllAsync();
}
今天我发现我可以在浏览器中转到 json url 并获取一些错误信息
例如
myapiurl/api/vi/swagger.json
就我而言,我有这个:
[HttpGet("CleanUpSnoozedLeads")]
public async Task<ActionResult<bool>> CleanUpSnoozedLeads()
[HttpGet("CleanUpSnoozedLeads")]
public async Task<ActionResult<bool>> DoSomethingElse()
注意 HttpGet() 具有相同的名称。这也会导致未定义的错误。
一个非常常见的情况是歧义。例如,只需对两个 PUT 或 POST 操作使用相同的签名,您就会收到错误。
其他答案对我不起作用。
当我尝试前往 swagger.json URL 位置时,我能够解决并理解我的问题:
https://localhost:XXXXX/swagger/v1/swagger.json
该页面将显示错误和未找到的原因。
在我的例子中,我看到我的一个方法根据它返回的错误配置 XML 定义错误:
NotSupportedException: HTTP method "GET" & path "api/Values/{id}" overloaded by actions - ...
...
...
就我而言,我只是忘记将 HttpPostAttribute 注释添加到方法中。
[HttpPost]
public ActionResult Post()
{
return Ok();
}
就我而言,schemaId 中存在冲突。显然,swagger JSON 中的每个 class 都必须具有唯一的 schemaId。如果在不同的命名空间中有两个同名的 classes,这将不起作用。我们必须在启动 class 中配置 "UseFullTypeNameInSchemaIds"。
在 "services.AddSwaggerGen" 中添加 "options.CustomSchemaIds(x => x.FullName);"
我通过在 VS 中启用输出 window 找到跟踪,从 Show output from 下拉列表中选择主项目,然后访问 http://{yourapiendpoint}/swagger/v1/swagger.json
如果您的 api 有相同的两个或更多 [HttpGet]
它不会招摇。
您应该指定 [HttpGet] , [HttpGet ("{id}")]
简单的解决方案
我有一个 .NET Core 2.0 应用程序,使用 Swashbuckle/Swagger 生成 API 文档。当我们使用 2.1.0 预览版时,Swagger 运行良好。然后我们对 2.1.0 版本和 SDK 2.1.300 进行了重大升级。我们没有注意到事情发生的确切时间,但现在我们的 Swagger 文档不会加载。这是我们看到的:
项目引用了 Swashbuckle.AspNetCore
版本 2.5.0。 Startup.cs
中的相关代码如下。在 ConfigureServices()
:
services.AddSwaggerGen(swaggerOptions =>
{
// Register a swagger doc
swaggerOptions.SwaggerDoc("v1", new Info
{
// Optional descriptive info that will be included in the Swagger output
Contact = new Contact
{
Name = "LightSail",
Url = "https://myurl.com/"
},
Description = "A description of the API can go here",
Title = "My API",
Version = "v1"
});
// Xml file to get comment information from
swaggerOptions.IncludeXmlComments("App_Data/Api.xml");
});
在Configure()
中:
app.UseSwagger();
app.UseSwaggerUI(swaggerUiOptions => swaggerUiOptions.SwaggerEndpoint("/swagger/v1/swagger.json", "My API v1"));
我发现了很多其他类似的问题,其中一个提示可能存在重复的端点;我尝试添加对 .ResolveConflictingEndpoints()
的调用,但这没有任何区别。我搜索了我的项目文件夹,没有名为 swagger.json
的文件,所以我猜这就是问题所在。
为什么这不起作用,或者如何解决?
就我而言,我可以通过省略“.”来重现您的错误。从你所做的终点开始。
如果我包含“.”,我不会收到错误消息。在路径的开始。 这是我的更多代码,以防相关。
在 ConfigureServices 我有
services.AddSwaggerGen(c =>
{
c.OperationFilter<AuthorizationHeaderParameterOperationFilter>();
c.SwaggerDoc("v1", new Info
{
Version = "v1",
Title = "My API",
Description = "ASP.NET Core Web API",
TermsOfService = "None",
Contact = new Contact
{
Name = "my name",
Email = "me@myemail.com"
}
});
});
在配置中
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
app.UseAuthentication();
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseDatabaseErrorPage();
}
else
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseCookiePolicy();
app.UseRewriter(new RewriteOptions()
.AddRedirectToHttpsPermanent());
app.UseSwagger(c =>
{
c.RouteTemplate =
"api-docs/{documentName}/swagger.json";
});
app.UseSwaggerUI(c =>
{
//Include virtual directory if site is configured so
c.RoutePrefix = "api-docs";
c.SwaggerEndpoint("./v1/swagger.json", "Api v1");
});
app.UseMvc(routes =>
{
routes.MapRoute(
"default",
"{controller=Home}/{action=Index}/{id?}");
});
还有
public class AuthorizationHeaderParameterOperationFilter : IOperationFilter
{
public void Apply(Operation operation, OperationFilterContext context)
{
var filterPipeline = context.ApiDescription.ActionDescriptor.FilterDescriptors;
var isAuthorized = filterPipeline.Select(filterInfo => filterInfo.Filter).Any(filter => filter is AuthorizeFilter);
var allowAnonymous = filterPipeline.Select(filterInfo => filterInfo.Filter).Any(filter => filter is IAllowAnonymousFilter);
if (isAuthorized && !allowAnonymous)
{
if (operation.Parameters == null)
operation.Parameters = new List<IParameter>();
operation.Parameters.Add(new NonBodyParameter
{
Name = "Authorization",
In = "header",
Description = "access token",
Required = true,
Type = "string"
});
}
}
我的依赖项是
Microsoft.AspNetCore.App (2.1.0)
Swashbuckle.AspNetCore (2.5.0)
Microsoft.NETCore.App (2.1.0)
这通常表示 controllers/actions Swashbuckle 出于某种原因不支持。
预计您的项目中没有 swagger.json 文件。 Swashbuckle 使用 ASP.NET Core 的 ApiExplorer API 动态创建和提供服务。这里可能发生的事情是 Swashbuckle 无法生成 Swagger.json,因此 UI 无法显示。
正如 HelderSepu 所说,很难确切地知道是什么导致了失败,所以最好的调试方法可能只是删除一半的控制器(只需将文件移动到一个临时位置)并检查问题是否仍然存在。然后你就会知道你的控制器的哪一半包含麻烦的动作。您可以 'binary search' 删除控制器(然后是操作),直到您找出导致 Swashbuckle 无法生成的操作方法 Swagger.json。一旦您知道这一点,就很明显这是您代码中的某个问题还是应该在 Swashbuckle repo.
中提交的问题例如,Swashbuckle 似乎不支持开放泛型,因此具有 [ResponseType(typeof(IEnumerable<>))]
之类的响应类型属性可能会导致此类行为。这也可能是路线不明确或类似绊倒 Swashbuckle 的问题。一旦您将故障原因缩小到更具体的原因,就可以根据需要修复或归档。
我能够通过将 http 动词属性显式添加到我的 asp.net 核心 2.x 控制器方法来解决此错误。在方法名称前加上 http 动词的惯例显然对 Swashbuckle 来说不够。
[HttpPost]
public async Task<IActionResult> AddNewData([FromBody] MyType myType) { … }
就我个人而言,我有点快,忘记将此行添加到 Startup.cs 中的方法 ConfigureServices 中。
services.AddSwaggerDocument();
就我而言,我错过了 'HttpAttribute':
public async Task<IEnumerable<ClientesListDto>> GetAll()
{
return await _service.GetAllAsync();
}
那我放上去招摇点赞:
[HttpGet]
public async Task<IEnumerable<ClientesListDto>> GetAll()
{
return await _service.GetAllAsync();
}
今天我发现我可以在浏览器中转到 json url 并获取一些错误信息 例如
myapiurl/api/vi/swagger.json
就我而言,我有这个:
[HttpGet("CleanUpSnoozedLeads")]
public async Task<ActionResult<bool>> CleanUpSnoozedLeads()
[HttpGet("CleanUpSnoozedLeads")]
public async Task<ActionResult<bool>> DoSomethingElse()
注意 HttpGet() 具有相同的名称。这也会导致未定义的错误。
一个非常常见的情况是歧义。例如,只需对两个 PUT 或 POST 操作使用相同的签名,您就会收到错误。
其他答案对我不起作用。
当我尝试前往 swagger.json URL 位置时,我能够解决并理解我的问题:
https://localhost:XXXXX/swagger/v1/swagger.json
该页面将显示错误和未找到的原因。
在我的例子中,我看到我的一个方法根据它返回的错误配置 XML 定义错误:
NotSupportedException: HTTP method "GET" & path "api/Values/{id}" overloaded by actions - ...
...
...
就我而言,我只是忘记将 HttpPostAttribute 注释添加到方法中。
[HttpPost]
public ActionResult Post()
{
return Ok();
}
就我而言,schemaId 中存在冲突。显然,swagger JSON 中的每个 class 都必须具有唯一的 schemaId。如果在不同的命名空间中有两个同名的 classes,这将不起作用。我们必须在启动 class 中配置 "UseFullTypeNameInSchemaIds"。 在 "services.AddSwaggerGen" 中添加 "options.CustomSchemaIds(x => x.FullName);" 我通过在 VS 中启用输出 window 找到跟踪,从 Show output from 下拉列表中选择主项目,然后访问 http://{yourapiendpoint}/swagger/v1/swagger.json
如果您的 api 有相同的两个或更多 [HttpGet]
它不会招摇。
您应该指定 [HttpGet] , [HttpGet ("{id}")]
简单的解决方案