繁体   English   中英

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

[英]ASP.NET Core - Swashbuckle not creating swagger.json file

我无法让 Swashbuckle.AspNetCore (1.0.0) package 生成任何 output。我读到 swagger.json 文件应该写入“~/swagger/docs/v1”。 但是,我没有收到任何 output。

我从一个全新的 ASP.NET Core API 项目开始。 我应该提到这是 ASP.NET Core 2。API 有效,我能够从值 controller 中检索值就好了。

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

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)
    {
    }
}

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

例如,我在基本控制器类中有一条不明确的路由,并收到错误消息:“用于操作的不明确的 HTTP 方法。操作需要 Swagger 2.0 的显式 HttpMethod 绑定。”。 如果您使用基本控制器,请确保您的公共方法使用 HttpGet/HttpPost/HttpPut/HttpDelete 或 Route 属性以避免模糊路由。

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

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

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/

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

在此处输入图像描述

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

c.SwaggerEndpoint("../swagger/v1/swagger.json", "MyAPI V1");
#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 部署保持应用程序别名(基本 URL)相同,因为 swagger 在“/swagger/v1/swagger.json”位置查找 swagger.json,但不会为应用程序别名(基本 URL)添加前缀,这就是它不起作用的原因.

例如:

localhost/swagger/v1/swagger.json - 找不到 swagger.json

我在招摇时遇到了类似但不完全相同的问题。 希望这对其他人有帮助。

我使用的是自定义文档标题,并且没有更改 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. 用明确的 Http 动词装饰所有动作,例如[HttpGet("xxx")][HttpPost("xxx")] ,...而不是[Route("xxx")]
  2. 使用[NonAction]属性装饰控制器中的公共方法。

请注意, http://localhost:XXXX/swagger/页面请求http://localhost:XXXX/swagger/v1/swagger.json文件,但如果您不遵守上述规则,Swagger 会出现异常。

在查看答案并检查建议后,我最终不知道出了什么问题。

我真的尝试了一切。 因此,如果您最终处于相同的情况,请了解问题可能是其他问题,与招摇完全无关。

在我的情况下是一个OData异常。

这是程序:

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

我将我的评论移至答案,因为它似乎很有帮助。


为避免 IIS 别名出现问题,请从 URL 路径中删除 /swagger/。 它应该如下所示:

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

如果您的控制器中有任何问题无法映射到唯一的 URL,您会收到此错误。

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

一些原因是

  1. 在没有 HTTP 方法属性的控制器中有公共方法

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

  3. 如果您正在使用版本控制,请确保您在所有控制器版本中都有该方法(如果使用继承,即使您从基础使用)

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

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

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

带有大写 V 的版本名称

实际上,您只需要通过删除起始反斜杠来修复 swagger url,就像这样:

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

代替 :

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

我们在使用 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);
}

添加相对路径对我有用:

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

就我个人而言,我遇到了同样的问题,当我今天再次尝试时,我发现在新版本(2.5.0)中进入json我可以看到对此处错误的解释。

帮助我解决它的另一件事是删除连接到解决方案文件夹根目录“..vs\config\applicationhost.config”中的网站的托管信息

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

           <site name="**" id="9">
              <application path="/" applicationPool=""></application>
              <bindings></bindings>
           </site>

尝试遵循这些步骤,简单而干净。

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

每个端点都应该有方法(get/post/put/delete)

. 解决方案

重新访问您的每个控制器,并确保您添加了预期的方法。

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

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

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

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

福在哪里

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

    public class Bar
    {
    }
}

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

为了找到根本问题,我导航到了实际的 swagger.json 文件,这给了我真正的错误

/swagger/v1/swagger.json

此网址显示的实际错误是

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()
 {

问题解决了

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

在此处输入图像描述

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

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

我有同样的问题。 我正在使用像下面提到的模式那样的招摇,即“../swagger/v1/swagger.json”,因为我使用的是 IIS Express。后来我将其更改为“/swagger/v1/swagger.json”并清理,重建解决方案为我工作。

Swagger 启用 UI

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

app.UseSwagger();

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

我有一个类似的问题,在我将异步版本的 API 添加到现有的 API 之后,我的 Swagger 文档中断了。 我通过安装/重新安装来玩 Swagger DLL,最后评论新添加的 API,它工作正常。 然后我在属性中添加了不同的签名,然后宾果游戏!,它起作用了。

在您的情况下,您有两个具有匹配签名的 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";
}

这应该可以解决问题。

请注意,在 Visual Studio 2022 和 .NetCore 6 中,如果您创建新的ASP.NET Core Web 应用程序,Program.cs 会检查开发环境。

代替

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

你会找到

if (!app.Environment.IsDevelopment())
{
     app.UseExceptionHandler("/Home/Error");
}
// You shoukd add swagger calls here 
app.UseSwagger();
app.UseSwaggerUI();

如果您通过选择模板ASP.NET Core Web API 创建一个新项目并选中“启用 OpenAPI 支持” ,您将拥有不同的 Program.cs,其中预装了 swagger 包和相关代码。

这花了我一些时间来寻找,希望对某人有所帮助。

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

此答案中的更多信息

看看 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");
});

当我尝试转到 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

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

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" />

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

在 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

我有一个愚蠢的问题,我在 AddSwaggerGen 方法中有一个大写的 v,在 c.SwaggerEndpoint 中有一个小写的 v。

它似乎区分大小写。

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

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

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

使用以下内容创建某处类 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访问修饰符!

// 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");
});

请对简单的 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";                
        });

请注意以下 2 行依次构成这两种方法。

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

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

所以无论你放什么而不是v1都应该匹配。

在我的例子中,我的 controller 中的多个端点具有相同的HttpPost属性名称。 您可以更改其中之一或将其完全删除。

[HttpPost("Post")]
[Route("someroute")]
public async Task<IActionResult> Method1([FromBody] Request request)
{
 // Some body
 return Ok(JsonConvert.SerializeObject(citations));
}

// Rename this "Post" or remove it
[HttpPost("Post")]
[Route("otherroute")]
public async Task<IActionResult> Method2([FromBody] Request request)
{
 // Some body
 return Ok(JsonConvert.SerializeObject(citations));
}

为了我:

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM