web-dev-qa-db-fra.com

La migration vers .NET Core 2.1 rompt l'interface utilisateur de Swagger

Récemment, nous avons migré notre projet de .NET Core 2.0 à .NET Core 2.1. En conséquence, notre site de documentation Swagger a cessé de fonctionner. Nous sommes toujours en mesure d'y accéder. Nous pouvons voir le titre et la version personnalisés, mais il n'y a pas de documentation sur l'API, mais juste un message disant No operations defined in spec!.

J'ai essayé une solution plus ancienne pour .NET Core 2.0 , mais cela n’a pas aidé. Sur la base des deux articles suivants 12 / J'ai essayé de supprimer les attributs Swagger des méthodes de contrôleur et d'ajouter un attribut [ApiController] au-dessus de la classe de contrôleur, mais cela n'a pas aidé. Quelqu'un peut-il aider à résoudre ce problème?

.csproj

<Project Sdk="Microsoft.NET.Sdk.Web">

    <PropertyGroup>
        <TargetFramework>netcoreapp2.1</TargetFramework>
        <RootNamespace>Company.Administration.Api</RootNamespace>
        <AssemblyName>Company.Administration.Api</AssemblyName>
        <PackageId>Company.Administration.Api</PackageId>
        <Authors></Authors>
        <Company>Company, Inc</Company>
        <Product>Foo</Product>
        <ApplicationInsightsResourceId>/subscriptions/dfa7ef88-f5b4-45a8-9b6c-2fb145290eb4/resourcegroups/Foo/providers/Microsoft.insights/components/foo</ApplicationInsightsResourceId>
        <ApplicationInsightsAnnotationResourceId>/subscriptions/dfa7ef88-f5b4-45a8-9b6c-2fb145290eb4/resourceGroups/Foo/providers/Microsoft.insights/components/foo</ApplicationInsightsAnnotationResourceId>
        <UserSecretsId>bf821b77-3f23-47e8-834e-7f72e2ab00c5</UserSecretsId>
    </PropertyGroup>

    <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
        <DocumentationFile>bin\Debug\netcoreapp2.1\Administration.Api.xml</DocumentationFile>
    </PropertyGroup>

    <PropertyGroup>
        <!-- Try to set version using environment variables set by GitVersion. -->
        <Version Condition=" '$(Version)' == '' And '$(GitVersion_AssemblySemVer)' != '' ">$(GitVersion_AssemblySemVer)</Version>
        <InformationalVersion Condition=" '$(InformationalVersion)' == '' And '$(GitVersion_InformationalVersion)' != '' ">$(GitVersion_InformationalVersion)</InformationalVersion>

        <!-- If we don't have environment variables set by GitVersion, use default version. -->
        <Version Condition=" '$(Version)' == '' ">0.0.1</Version>
        <InformationalVersion Condition=" '$(InformationalVersion)' == '' ">0.0.1-local</InformationalVersion>
    </PropertyGroup>

    <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
        <DocumentationFile>bin\Release\netcoreapp2.1\Administration.Api.xml</DocumentationFile>
    </PropertyGroup>

    <PropertyGroup>
        <MvcRazorCompileOnPublish>false</MvcRazorCompileOnPublish>
        <PreserveCompilationContext>false</PreserveCompilationContext>
    </PropertyGroup>

    <ItemGroup>
        <Folder Include="wwwroot\" />
    </ItemGroup>

    <ItemGroup>
        <PackageReference Include="IdentityModel" Version="3.7.0-preview1" />
        <PackageReference Include="IdentityServer4.AccessTokenValidation" Version="2.6.0" />
        <PackageReference Include="Microsoft.ApplicationInsights.AspNetCore" Version="2.3.0" />
        <PackageReference Include="Microsoft.AspNet.WebApi.Client" Version="5.2.6" />
        <PackageReference Include="Microsoft.AspNetCore.All" Version="2.1.0" />
        <PackageReference Include="Microsoft.AspNetCore.StaticFiles" Version="2.1.0" />
        <PackageReference Include="Swashbuckle.AspNetCore" Version="2.4.0" />
        <PackageReference Include="Swashbuckle.AspNetCore.ReDoc" Version="2.4.0" />
    </ItemGroup>

    <ItemGroup>
        <WCFMetadata Include="Connected Services" />
    </ItemGroup>

</Project>

Startup.cs

using Company.Administration.Api.Controllers;
using Company.Administration.Api.Security;
using Company.Administration.Api.Services;
using Company.Administration.Api.Swagger;
using Company.Administration.Api.Swagger.Examples;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.PlatformAbstractions;
using Newtonsoft.Json.Converters;
using Swashbuckle.AspNetCore.Swagger;
using System;
using System.Collections.Generic;
using System.IdentityModel.Tokens.Jwt;
using System.IO;
using System.Net.Http;

namespace Company.Administration.Api
{
    public class Startup
    {
        public Startup(IConfiguration configuration, ILogger<Startup> logger, IHostingEnvironment hostingEnvironment)
        {
            Configuration = configuration;
            Logger = logger;
            HostingEnvironment = hostingEnvironment;

            JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();
        }

        public IHostingEnvironment HostingEnvironment { get; }
        public IConfiguration Configuration { get; }
        public ILogger Logger { get; }

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddTransient<HttpClient>();
            services.AddTransient<AuthService>();
            services.AddTransient<FooAdministrationService>();

            services.AddMvc()
                .AddJsonOptions(options =>
                {
                    options.SerializerSettings.Converters.Add(new StringEnumConverter());
                });

            services.AddFooAuthentication(Configuration);

            services.AddFooAuthorization();

            services.AddCors();

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

                    var basePath = PlatformServices.Default.Application.ApplicationBasePath;
                    var xmlPath = Path.Combine(basePath, "Administration.Api.xml");
                    if (File.Exists(xmlPath))
                    {
                        c.IncludeXmlComments(xmlPath);
                    }
                    else
                    {
                        Logger.LogWarning($@"File does not exist: ""{xmlPath}""");
                    }

                    string authorityOption = Configuration["IdentityServerAuthentication:Url"] ?? throw new Exception("Failed to load authentication URL from configuration.");
                    string authority = $"{authorityOption}{(authorityOption.EndsWith("/") ? "" : "/")}";

                    var scopes = new Dictionary<string, string>
                    {
                        { "api", "Allow calls to the Foo administration API." }
                    };

                    c.AddSecurityDefinition("OpenId Connect", new OAuth2Scheme
                    {
                        Type = "oauth2",
                        Flow = "implicit",
                        AuthorizationUrl = $"{authority}connect/authorize",
                        TokenUrl = $"{authority}connect/token",
                        Scopes = scopes
                    });

                    c.DescribeAllEnumsAsStrings();

                    c.OperationFilter<ExamplesOperationFilter>(services.BuildServiceProvider());
                })
                .ConfigureSwaggerGen(options =>
                {
                    options.CustomSchemaIds(t => t.FullName);

                    options.OperationFilter<SecurityRequirementsOperationFilter>();
                });
        }

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

            app.UseCors(builder => builder
                .AllowAnyOrigin()
                .AllowAnyMethod()
                .AllowAnyHeader()
                .AllowCredentials()
                .WithExposedHeaders(AdministrationControllerBase.ExposedHeaders));

            app.UseAuthentication();

            app.UseMvc()
                .UseSwagger(x => x.RouteTemplate = "api-docs/{documentName}/swagger.json")
                .UseSwaggerUI(c =>
                {
                    c.OAuthClientId("foo-administration.swagger");
                    c.RoutePrefix = "api-docs";
                    c.SwaggerEndpoint("v1/swagger.json", "Foo Administration API");
                });

            app.UseReDoc(options =>
            {
                options.RoutePrefix = "api-docs-redoc";
                options.SpecUrl = "../api-docs/v1/swagger.json";
            });

        }
    }
}
5
lss

J'ai essayé de recréer la même solution ligne par ligne. Swagger a travaillé jusqu'à ce que j'ai ajouté <PreserveCompilationContext>false</PreserveCompilationContext> dans le fichier .csproj. La suppression de cet attribut a provoqué la réapparition de l'interface utilisateur Swagger. 

3
lss

Pour moi, cette erreur est apparue pourquoi j'ai essayé d'utiliser l'attribut [ApiVersionNeutral] sur le contrôleur v1 et [ApiVersion ("2.0")] sur le contrôleur v2. Quoi qu'il en soit, vous pouvez obtenir un message d'erreur complet dans les outils de sortie ou de diagnostic (onglet Evénements). Et alors j'ai eu ce message:

System.NotSupportedException: Méthode HTTP "GET" & chemin "api/Employees" surchargé par des actions - Api.V2.Controllers.EmployeesController.Get , Api.V1.Controllers.EmployeesController.Get. 

Les actions nécessitent une combinaison unique méthode/chemin pour Swagger 2.0. Utilisation ConflictingActionsResolver en guise d'une solution de contournement

0
Gilberto Alexandre