web-dev-qa-db-ja.com

.NET Core 2.1のSwashbuckle / Swaggerは、アップグレード後に動作を停止しました

Swashbuckle/Swaggerを使用してAPIドキュメントを生成する.NET Core 2.0アプリケーションがあります。 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

プロジェクトには_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"));
_

他にも同様の質問がたくさんありましたが、そのうちの1つは、エンドポイントが重複している可能性があることを示唆しています。 .ResolveConflictingEndpoints()への呼び出しを追加しようとしましたが、違いはありませんでした。プロジェクトフォルダーを検索しましたが、_swagger.json_というファイルがないため、これが問題だと思います。

これが機能しない理由、または修正方法はありますか?

7
Shaul Behr

これは通常、Swashbuckleが何らかの理由でサポートしていないコントローラー/アクションを示しています。

プロジェクトにswagger.jsonファイルがないことが予想されます。 Swashbuckleは、ASP.NET CoreのApiExplorer APIを使用して動的に作成および提供します。おそらくここで起こっているのは、SwashbuckleがSwagger.jsonを生成できないため、UIが表示されないことです。

HelderSepuが言ったように、失敗の原因を正確に知ることは難しいため、デバッグする最善の方法は、おそらくコントローラーの半分を削除し(ファイルを一時的な場所に移動するだけ)、問題が解決しないかどうかを確認することです。その後、コントローラーのどの半分に問題のあるアクションが含まれているかがわかります。 SwashbuckleがSwagger.jsonを生成できない原因となっているアクションメソッドがわかるまで、コントローラー(およびアクション)を削除する「バイナリ検索」が可能です。これを知ったら、これがコードの問題なのか、それとも Swashbuckle repo に提出すべき問題なのかが明らかになるはずです。

たとえば、Swashbuckleはオープンジェネリックをサポートしていないように見えるため、[ResponseType(typeof(IEnumerable<>))]のような応答タイプ属性があると、このような動作が発生する可能性があります。また、あいまいなルートや、スワッシュバックルがトリップするような問題もあります。障害の原因をより具体的なものに絞り込んだら、必要に応じて修正または提出できます。

9
MJRousos

今日、私はブラウザのjson urlにアクセスして、たとえばエラー情報を取得できることがわかりました

myapiurl/api/vi/swagger.json

6
Kirsten Greed

Http動詞属性をasp.net core 2.xコントローラーメソッドに明示的に追加することで、このエラーを解決できました。メソッド名の前にhttp動詞を付けるという規則は、明らかにSwashbuckleには十分ではありません。

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

3
Werewolf

私の場合、「。」を省略することでエラーを再現できます。あなたがしたようにエンドポイントから。 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
Kirsten Greed

個人的に私は少し速く、Startup.csのConfigureServicesメソッドにこの行を追加するのを忘れていました。

services.AddSwaggerDocument();

1

私の場合、HttpPostAttributeアノテーションをメソッドに追加するのを忘れていました。

[HttpPost]
public ActionResult Post()
{
    return Ok();
}
0

他の回答は私にはうまくいきませんでした。

Swagger.jsonのURLの場所にアクセスしようとしたときに、問題を修正して理解することができました。

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

ページにエラーと、見つからない理由が表示されます。

私の場合、返されたエラーに基づいて、メソッドの1つのXML定義が誤って構成されていることがわかりました。

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

非常に一般的なケースはあいまいです。たとえば、2つのPUTまたはPOST操作に同じ署名を使用すると、エラーが発生します。

0

私の場合、これがありました:

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


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

HttpGet()の名前が同じであることに注意してください。同様に、未定義エラーが発生します。

0
duckwizzle

私の場合、「HttpAttribute」を見逃していました。

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

それから私はそれを入れて、それを好きに振ってください:

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