.NET Core 2.1上的Swashbuckle / Swagger自升级以来已停止工作

问题描述 投票:5回答:8

我有一个.NET Core 2.0应用程序,使用Swashbuckle / Swagger生成API文档。当我们在2.1.0预览时,Swagger工作正常。然后我们进行了2.1.0版和SDK 2.1.300的大升级。我们没有注意到事情何时破裂,但现在我们的Swagger文档将无法加载。以下是我们所看到的:Failed to load API definition Errors Fetch error undefined /swagger/v1/swagger.json

Project参考了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的文件,所以我猜这是问题所在。

任何想法为什么这不起作用,或如何解决?

asp.net-core swagger swashbuckle
8个回答
9
投票

这通常表示Swashbuckle因某种原因不支持的控制器/操作。

预计您的项目中没有swagger.json文件。 Swashbuckle使用ASP.NET Core的ApiExplorer API动态创建和提供。这里可能发生的事情是Swashbuckle无法生成Swagger.json,因此UI无法显示。

正如HelderSepu所说,很难确切知道导致失败的原因,因此调试的最佳方法可能只是删除一半控制器(只需将文件移动到临时位置)并检查问题是否仍然存在。然后你会知道哪一半的控制器包含麻烦的动作。您可以“二进制搜索”删除控制器(然后执行操作),直到找出导致Swashbuckle无法生成Swagger.json的操作方法。一旦你知道这一点,你的代码中是否存在某些问题或者应该在Swashbuckle repo中提交的问题应该是显而易见的。

例如,Swashbuckle似乎不支持开放泛型,因此拥有像[ResponseType(typeof(IEnumerable<>))]这样的响应类型属性可能会导致这种行为。这也可能是一个模糊的路线问题或者像Swashbuckle绊倒的事情。一旦你将失败的原因缩小到更具体的东西,就可以酌情修复或归档。


5
投票

今天我发现我可以在浏览器中找到json url并获取一些错误信息

myapiurl /火/ VI / swagger.json


2
投票

在我的情况下,我可以通过省略“。”来重现您的错误。从你做到的最终点开始。 enter image description here

如果我包含“。”,我不会收到错误。在路径的开头。如果它是相关的,这里有更多我的代码。

在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 = "[email protected]"
            }
        });
    });

在配置中

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)

2
投票

我能够通过显式添加http动词属性到我的asp.net core 2.x控制器方法来解决这个错误。对于Swashbuckle来说,使用http动词为方法名称加前缀的约定是不够的。

[HttpPost] public async Task<IActionResult> AddNewData([FromBody] MyType myType) { … }


1
投票

就个人而言,我有点快,忘了将此行添加到Startup.cs中的方法ConfigureServices。

services.AddSwaggerDocument();


0
投票

就我而言,我错过了'HttpAttribute':

public async Task<IEnumerable<ClientesListDto>> GetAll()
{
     return await _service.GetAllAsync();
}

然后我把它放在心里喜欢它:

[HttpGet]
public async Task<IEnumerable<ClientesListDto>> GetAll()
{
     return await _service.GetAllAsync();
}

0
投票

就我而言,我有这个:

    [HttpGet("CleanUpSnoozedLeads")]
    public async Task<ActionResult<bool>> CleanUpSnoozedLeads()


    [HttpGet("CleanUpSnoozedLeads")]
    public async Task<ActionResult<bool>> DoSomethingElse()

请注意,HttpGet()具有相同的名称。这也导致了未定义的错误。


0
投票

一个非常常见的情况是模棱两可。例如,对两个PUT或POST操作使用相同的签名,您将收到错误。

© www.soinside.com 2019 - 2024. All rights reserved.