ASP.NET Core - Swashbuckle 未创建 swagger.json 文件

ASP.NET Core - Swashbuckle not creating swagger.json file

我无法让 Swashbuckle.AspNetCore (1.0.0) 包生成任何输出。我读到 swagger.json 文件应该写入 '~/swagger/docs/v1'。但是,我没有得到任何输出。

我从一个全新的 ASP.NET 核心 API 项目开始。我应该提到这是 ASP.NET Core 2。API 有效,我能够很好地从值控制器中检索值。

我的启动 class 的配置与本文 (Swashbuckle.AspNetCore on GitHub) 中描述的完全相同。

public class Startup
{
    public Startup(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public IConfiguration Configuration { get; }

    // This method gets called by the runtime. Use this method to add services to the container.
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddMvc();

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

    // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();

            // Enable middleware to serve generated Swagger as a JSON endpoint.
            app.UseSwagger();
            app.UseSwaggerUI(c =>
            {
                c.SwaggerEndpoint("/swagger/v1/swagger.json", "MyAPI V1");
            });
        }
        else
        {
            app.UseExceptionHandler();
        }

        app.UseStatusCodePages();
        app.UseMvc();

        //throw new Exception();
    }
}

您可以看到 NuGet 引用...

同样,这都是默认模板,但我包含了 ValuesController 以供参考...

[Route("api/[controller]")]
public class ValuesController : Controller
{
    // GET api/values
    [HttpGet]
    public IEnumerable<string> Get()
    {
        return new string[] { "value1", "value2" };
    }

    // GET api/values/5
    [HttpGet("{id}")]
    public string Get(int id)
    {
        return "value";
    }

    // POST api/values
    [HttpPost]
    public void Post([FromBody]string value)
    {
    }

    // PUT api/values/5
    [HttpPut("{id}")]
    public void Put(int id, [FromBody]string value)
    {
    }

    // DELETE api/values/5
    [HttpDelete("{id}")]
    public void Delete(int id)
    {
    }
}

我相信您在配置中错过了这两行:

if (env.IsDevelopment())
{
    app.UseDeveloperExceptionPage();

    // Enable middleware to serve generated Swagger as a JSON endpoint.
    app.UseSwagger();
    app.UseSwaggerUI(c =>
    {
        c.SwaggerEndpoint("v1/swagger.json", "MyAPI V1");
    });
}

要访问 Swagger UI,URL 应该是:http://localhost:XXXX/swagger/

可以在Swagger的顶部找到json UI:

我遇到了同样的问题,并注意到我的 API 没有托管在根文件夹和虚拟目录中。 我将 API 移动到 IIS 中的根文件夹并开始工作。

更多信息

就我个人而言,我遇到了同样的问题,当我今天再次尝试时,我发现在新版本 (2.5.0) 中出现 json I could see an explanation of the error that was in here.

还有另一件事帮助我解决了这个问题,就是删除了连接到网站的托管信息,该网站位于解决方案文件夹根目录下的“..vs\config\applicationhost.config”

我删除了配置网站的元素。

           <site name="**" id="9">
              <application path="/" applicationPool=""></application>
              <bindings></bindings>
           </site>
#if DEBUG
   // For Debug in Kestrel
   c.SwaggerEndpoint("/swagger/v1/swagger.json", "Web API V1");
#else
   // To deploy on IIS
   c.SwaggerEndpoint("/webapi/swagger/v1/swagger.json", "Web API V1");
#endif

部署到 IIS webapi(base URL) 时是应用程序别名。您需要为所有 IIS 部署保持 Application Alias(base URL) 相同,因为 swagger 在“/swagger/v1/swagger.json”位置查找 swagger.json 但不会为应用程序别名添加前缀(base URL) 这就是它不起作用的原因。

例如:

localhost/swagger/v1/swagger.json - Couldn't find swagger.json

如果您的应用程序托管在 IIS/IIS Express 上,请尝试以下操作:

c.SwaggerEndpoint("../swagger/v1/swagger.json", "MyAPI V1");

我 运行 遇到了一个与 swagger 类似但不完全相同的问题。希望这对其他人有帮助。

我使用的是自定义文档标题,并且没有更改 SwaggerEndPoint 中的文件夹路径以匹配文档标题。如果你让端点指向 swagger/v1/swagger.json 它不会在 swagger UI.

中找到 json 文件

示例:

services.AddSwaggerGen(swagger =>
{
    swagger.SwaggerDoc("AppAdministration", new Info { Title = "App Administration API", Version = "v1.0" });
            
});


app.UseSwaggerUI(c =>
{
    c.SwaggerEndpoint("/swagger/AppAdministration/swagger.json", "App Administration");
});

您必须遵守 2 条规则:

  1. [HttpGet("xxx")][HttpPost("xxx")]、......而不是[Route("xxx")]
  2. 等明确的Http动词修饰所有动作
  3. [NonAction] 属性修饰控制器中的 public 方法。

请注意 http://localhost:XXXX/swagger/ page requests for http://localhost:XXXX/swagger/v1/swagger.json 文件,但如果您不遵守上述规则,Swagger 会发生异常。

我遇到了同样的问题。检查 http://localhost:XXXX/swagger/v1/swagger.json。如果您遇到任何错误,请修复它们。

例如,我在基本控制器 class 中有一条不明确的路线,我得到了错误:"Ambiguous HTTP method for action. Actions require an explicit HttpMethod binding for Swagger 2.0."。 如果您使用基本控制器,请确保您的 public 方法使用 HttpGet/HttpPost/HttpPut/HttpDelete OR Route 属性以避免不明确的路由。

然后,我也在同一个方法中定义了 HttpGet("route") 和 Route("route") 属性,这是 swagger 的最后一个问题。

看完答案和推荐后,我最终不知道哪里出了问题。

我真的什么都试过了。因此,如果您最终遇到同样的情况,请理解问题可能出在其他方面,与 swagger 完全无关。

我的情况是 OData 异常。

程序如下:

1) 导航至 localhost:xxxx/swagger
2) 打开开发者工具
3) 单击控制台中显示的错误,您将看到导致问题的内部异常。

确保您拥有所有必需的依赖项,转到 url xxx/swagger/v1/swagger。json 您可能会发现缺少一个或多个依赖项。

我们在使用 Swagger 时常犯的一个错误是给 (NET ASP) 两个或多个路由赋予相同的名称。这导致 swagger 无法生成 JSON 文件。例如,这是错误的方式

[HttpPost, Route("Start")]
public async Task<TransactionResult> WipStart(BodyWipStartDTO data)
{
    return await _wipServices.WipStart(data);
}

具有相同路由名称但不同操作名称的其他操作

[HttpPost, Route("Start")]
public async Task<TransactionResult> WipAbort(BodyWipStartDTO data)
{
    return await _wipServices.WipAbort(data);
}

这是正确的方法

[HttpPost, Route("Start")]
public async Task<TransactionResult> WipStart(BodyWipStartDTO data)
{
    return await _wipServices.WipStart(data);
}

[HttpPost, Route("Abort")]
public async Task<TransactionResult> WipAbort(BodyWipStartDTO data)
{
    return await _wipServices.WipAbort(data);
}

当我使用版本 headers 而不是 url 版本控制创建 api 的版本 2 时,我遇到了这个 Swagger 错误。解决方法是向版本 1 方法添加 [Obsolete] 属性,然后使用 SwaggerGeneratorOptions 忽略 Startup -> ConfigureServices 方法中过时的 api 方法。

services.AddSwaggerGen(c =>
{
    c.SwaggerGeneratorOptions.IgnoreObsoleteActions = true;
    c.SwaggerDoc("v2", new Info { Title = "My API", Version = "v2" });
});

查看 Chrome 开发者工具,有时,swagger.json 请求抛出 http 500, 意味着您的控制器存在一些不一致。 例如:在我的例子中,有一个 "Ambiguous HTTP method for action":

我还遇到了一个问题,因为我在 IIS 级别对应用程序进行版本控制,如下所示:

如果这样做,Configure 方法中的配置应附加版本号,如下所示:

app.UseSwaggerUI(options =>
{
    options.SwaggerEndpoint("/1.0/swagger/V1/swagger.json", "Static Data Service");
});

尝试按照这些步骤操作,既简单又干净。

  1. 检查您的控制台是否收到类似“Ambiguous HTTP method for action. Actions require an explicit HttpMethod binding for Swagger 2.0.”的任何错误“
  2. 如果此错误的原因:Swagger 期望

each endpoint should have the method (get/post/put/delete)

解决方案

Revisit your each and every controller and make sure you have added expected method.

(或者您可以在控制台错误中看到哪个控制器导致歧义)

  1. 如果如果您发现任何问题,请告诉我们您的问题和解决方案。

我在 Post 参数中使用内部 class 时遇到了这个问题

[HttpPost]
public async Task Post([FromBody] Foo value)
{
}

Foo 在哪里

public class Foo
{
    public IEnumerable<Bar> Bars {get;set;}

    public class Bar
    {
    }
}

如果您的控制器在映射到唯一 URL 时遇到任何问题,您会收到此错误。

查找问题原因的最佳方法是从项目中排除所有控制器。然后通过一次启用一个控制器或控制器中的一种或多种方法来尝试 运行 应用程序,以查找有问题的控制器/控制器方法 (S)。或者你可以变得聪明,做一个二进制搜索逻辑来找到禁用启用多个 controller/methods 来找到有问题的。

部分原因是

  1. 在没有 HTTP 方法属性的控制器中有 public 个方法

  2. 具有多个具有相同 Http 属性的方法,如果您不使用基于“[action]”的映射

    ,这些方法可以映射到相同的 api 调用
  3. 如果您正在使用版本控制,请确保您在所有控制器版本中都有该方法(如果使用继承,即使您使用的是基础)

当我尝试前往 swagger.json URL 位置时,我能够解决并理解我的问题:

https://localhost:XXXXX/swagger/v1/swagger.json

该页面将显示错误和未找到的原因。

在我的例子中,我看到我的一个方法根据它返回的错误配置 XML 定义错误:

NotSupportedException: HTTP method "GET" & path "api/Values/{id}" overloaded by actions - ...
...
...

在我的例子中,问题出在方法类型上,应该是 HttpPOST 但有 HttpGET 一旦我改变了它,一切都会开始工作。

https://c2n.me/44p7lRd.png

我遇到了同样的问题。我正在使用像下面提到的模式一样的招摇,即“../swagger/v1/swagger.json”因为我使用的是 IIS Express.Later 而不是我将其更改为 “/swagger/v1/swagger.json”并清理、重建对我有用的解决方案。

您应该将以下包安装到您的项目中。

5.0.0-rc4 Swashbuckle 版本是最低的。不然不行。

截至目前,直接从 Nuget 安装它会安装不适用于 Core 3 的旧版本。

我将以下行插入到 .csproj 项目文件中:

<PackageReference Include="Microsoft.OpenApi" Version="1.1.4" />
<PackageReference Include="Swashbuckle.AspNetCore.Swagger" Version="5.0.0-rc4" />
<PackageReference Include="Swashbuckle.AspNetCore.SwaggerGen" Version="5.0.0-rc4" />
<PackageReference Include="Swashbuckle.AspNetCore.SwaggerUi" Version="5.0.0-rc4" />

之后,重建会安装较新的版本。 如果没有,你也可以使用还原。

在 Startup.cs 中,您应该像这样配置 Swashbuckle:

 // This method gets called by the runtime. Use this method to add services to the container.
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddControllers();

            // Register the Swagger generator, defining 1 or more Swagger documents
            services.AddSwaggerGen(c =>
            {
                c.SwaggerDoc("v1", new OpenApiInfo { Title = "My API", Version = "v1" });
            });

        services.AddMvc();
    }

// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }

        app.UseHttpsRedirection();

        // Enable middleware to serve generated Swagger as a JSON endpoint.
        app.UseSwagger();

        // Enable middleware to serve swagger-ui (HTML, JS, CSS, etc.),
        // specifying the Swagger JSON endpoint.
        app.UseSwaggerUI(c =>
        {
            c.SwaggerEndpoint("/swagger/v1/swagger.json", "My API V1");
            //c.RoutePrefix = String.Empty;
        });

        app.UseRouting();

        app.UseAuthorization();

        app.UseEndpoints(endpoints =>
        {
            endpoints.MapControllers();
        });
    }

只需转到“https://localhost:5001/swagger/index.html”,您就会看到 Swagger UI。 (5001是我的本地端口,你应该换成你的)

我花了一点时间才弄明白。

希望对其他人有所帮助:)

答案:

If using directories or application  with IIS or a reverse proxy,<br/> set the Swagger endpoint to a relative path using the ./ prefix. For example,<br/> ./swagger/v1/swagger.json. Using /swagger/v1/swagger.json instructs the app to<br/>look for the JSON file at the true root of the URL (plus the route prefix, if used). For example, use http://localhost:<br/><br/><port>/<route_prefix>/swagger/v1/swagger.json instead of http://localhost:<br/><port>/<virtual_directory>/<route_prefix>/swagger/v1/swagger.json.<br/>
if (env.IsDevelopment())
{
    app.UseDeveloperExceptionPage();

    // Enable middleware to serve generated Swagger as a JSON endpoint.
    app.UseSwagger();
    app.UseSwaggerUI(c =>
    {
//c.SwaggerEndpoint("/swagger/v1/swagger.json", "MyAPI V1");
//Add dot in front of swagger path so that it takes relative path in server
c.SwaggerEndpoint("./swagger/v1/swagger.json", "MyAPI V1");
    });
}

[Detail description of the swagger integration to web api core 3.0][1]


  [1]: https://docs.microsoft.com/en-us/aspnet/core/tutorials/getting-started-with-swashbuckle?view=aspnetcore-3.1&tabs=visual-studio

同样的问题 - 我很容易解决。

为了找到潜在的问题,我导航到实际的 swagger.json 文件,它给了我真正的错误

/swagger/v1/swagger.json

此 Url 显示的实际错误是

NotSupportedException: Ambiguous HTTP method for action  ... Actions require an explicit HttpMethod binding for Swagger/OpenAPI 3.0

重点是

Actions require an explicit HttpMethod

然后我用 [HttpGet]

修饰了我的控制器方法
[Route("GetFlatRows")]
 [HttpGet]
 public IActionResult GetFlatRows()
 {

问题已解决

我遇到了一个愚蠢的问题,我在 AddSwaggerGen 方法中有一个大写字母 v 而在 c.SwaggerEndpoint 中有一个小写字母 v。

似乎区分大小写。

我正在将我的评论移到答案中,因为它看起来很有帮助。


为避免 IIS 别名出现问题,请从 URL 路径中删除 /swagger/。它应该是这样的:

app.UseSwaggerUI(c => { c.SwaggerEndpoint("v1/swagger.json", "API name"); });

据微软称: 要在应用程序的根目录 (http://localhost:/) 提供 Swagger UI,请将 RoutePrefix 属性 设置为空字符串:

app.UseSwaggerUI(c =>
{
c.SwaggerEndpoint("/swagger/v1/swagger.json", "My API V1");
c.RoutePrefix = string.Empty;
});

添加相对路径对我有用:

app.UseSwaggerUI(c =>
{
    c.SwaggerEndpoint("../swagger/v1/swagger.json", "My App");
});

我有同样的错误,但由于不同的问题,我使用的是导致此问题的第 3 方库,我不需要在我的曝光中使用这个库,所以我使用了以下解决方案发布 here .

在某处创建 class ApiExplorerIgnores 具有以下内容

public class ApiExplorerIgnores : IActionModelConvention
{
    public void Apply(ActionModel action)
    {
        if (action.Controller.ControllerName.Equals("ImportExport"))
            action.ApiExplorer.IsVisible = false;
    }
}

将以下代码添加到 Startup.cs

中的方法 ConfigureServices
services.AddMvc(c => c.Conventions.Add(new ApiExplorerIgnores()))

这将读取该控制器中的所有方法,您也可以使用特定级别,例如方法名称等,您也可以只删除一个方法等等,

就我而言,我忘记为方法设置 public 访问修饰符!

我不知道这对某人是否有用,但就我而言,问题是名称的大小写不同。

V1在服务配置中-V大写字母
v1 在设置中 -- v 小写

我唯一做的就是使用相同的外壳并且它起作用了。

你实际上只需要像这样删除起始反斜杠来修复招摇 url :

c.SwaggerEndpoint("swagger/v1/swagger.json", "MyAPI V1");

而不是:

c.SwaggerEndpoint("/swagger/v1/swagger.json", "MyAPI V1");
// Enable middleware to serve generated Swagger as a JSON endpoint.

app.UseSwagger(c =>
{
    c.SerializeAsV2 = true;
});

// Enable middleware to serve swagger-ui (HTML, JS, CSS, etc.),
// specifying the Swagger JSON endpoint.
app.UseSwaggerUI(c =>
{
    c.SwaggerEndpoint("/swagger/v1/swagger.json", "API Name");
});

您可能忘记包含.. StartUp.cs/Configure()

app.UseSwagger();

检查是否忘记包含,必须删除错误。

我遇到了类似的问题,在我将 APIs 的异步版本添加到现有文档后,我的 Swagger 文档损坏了。 我通过安装/重新安装来玩弄 Swagger DLL,最后评论新添加的 APIs,它起作用了。 然后我在属性中添加了不同的签名,宾果!,成功了。

在您的情况下,您有两个 API 具有匹配的签名

[HttpGet]
public IEnumerable<string> Get()
{
  return new string[] { "value1", "value2" };
}

// GET api/values/5
[HttpGet("{id}")]
public string Get(int id)
{`enter code here`
  return "value";
}

Try providing different names in attributes like
[HttpGet("List")]
public IEnumerable<string> Get()
{
 return new string[] { "value1", "value2" };
}

// GET api/values/5
[HttpGet("ListById/{id}")]
public string Get(int id)
{
  return "value";
}

这应该可以解决问题。

对于简单的 API 文档,请使用以下约定。

ConfigureServices方法中

        services.AddSwaggerGen(c =>
        {
            c.SwaggerDoc("v1", new OpenApiInfo { Title = "My Test API", Version = "1.0.0.0" });
            c.OperationFilter<SwaggerAuthorizationOperationFilter>();
            c.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme()
            {
                Description = "Enter the request header in the following box to add Jwt To grant authorization Token: Bearer Token",
                Name = "Authorization",
                In = ParameterLocation.Header,
                Type = SecuritySchemeType.ApiKey,
                BearerFormat = "JWT",
                Scheme = "Bearer"
            });
            //c.SchemaFilter<SwaggerExcludeSchemaFilter>();
            c.AddSecurityRequirement(new OpenApiSecurityRequirement
                {
                {
                    new OpenApiSecurityScheme
                    {
                        Reference = new OpenApiReference {
                            Type = ReferenceType.SecurityScheme,
                            Id = "Bearer"
                        }
                    },
                    new string[] { }
                }
                });
        });

Configure方法中

        app.UseSwagger();
        app.UseSwaggerUI(c =>
            {
                c.DefaultModelExpandDepth(2);
                c.DefaultModelsExpandDepth(-1);
                c.DisplayOperationId();
                c.DisplayRequestDuration();
                c.EnableDeepLinking();
                c.EnableFilter();
                c.ShowExtensions();
                c.EnableValidator();
            });

        // Enable middleware to serve swagger-ui (HTML, JS, CSS, etc.),
        // specifying the Swagger JSON endpoint.
        app.UseSwaggerUI(c =>
        {
            c.SwaggerEndpoint("/swagger/v1/swagger.json", "My Test API");
            c.RoutePrefix = "";
            c.DocumentTitle = "My Test API Docs";                
        });

请注意以下两行顺序构成了这两种方法。

c.SwaggerDoc("v1", new OpenApiInfo { Title = "My Test API", Version = "1.0.0.0" });

c.SwaggerEndpoint("/swagger/v1/swagger.json", "My Test API");

因此,无论您输入什么而不是 v1,都应该匹配。

请注意,在 .NetCore 6 中,Program.cs 对开发环境进行了相反的检查。

而不是

if (app.Environment.IsDevelopment())
{
   app.UseSwagger();
   app.UseSwaggerUI();
}

你会发现

if (!app.Environment.IsDevelopment())
{
     app.UseExceptionHandler("/Home/Error");
}
// Add swagger usings here
app.UseSwagger();
app.UseSwaggerUI();

找了很久,希望对大家有所帮助。