domaindrivendev / Swashbuckle.WebApi

Seamlessly adds a swagger to WebApi projects!
BSD 3-Clause "New" or "Revised" License
3.07k stars 678 forks source link

Referencing Swashbuckle.AspNetCore 5.0.0 in library with multiple targets #1358

Open berndku opened 4 years ago

berndku commented 4 years ago

VERSION:

5.0.0

STEPS TO REPRODUCE:

Create project with multiple targets, e.g.

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <TargetFrameworks>netstandard2.0;netcoreapp3.1</TargetFrameworks>
    <PackageId>Test</PackageId>
    <Platforms>AnyCPU;x64</Platforms>
  </PropertyGroup>

  <ItemGroup Condition="'$(TargetFramework)' == 'netcoreapp3.1'">
    <FrameworkReference Include="Microsoft.AspNetCore.App" />
    <PackageReference Include="Swashbuckle.AspNetCore" Version="5.0.0" />
    <PackageReference Include="Swashbuckle.AspNetCore.SwaggerGen" Version="5.0.0" />
  </ItemGroup>
</Project>

EXPECTED RESULT:

Project should compile

ACTUAL RESULT:

Compilation error: The target "GenerateOpenApiDocuments" does not exist in the project.

bigwheels490 commented 4 years ago

I've run into this same issue. Interestingly enough, if I specify the target framework on the build command line like dotnet build <project> --framework netcoreapp3.1 for each target framework, the build succeeds. When it tries to build all target frameworks at once, it fails. However, that solution doesn't work when building as part of the dotnet pack command.

krispenner commented 4 years ago

I've also stumbled upon this issue and it only affects multi-targeting <TargetFrameworks>. Targeting a single framework works, however I need to target two.

Expanding on what @bigwheels490 suggested, you can use dotnet pack --no-build so that it just packages your pre-existing individually built assemblies, that seems to work for me, so now I have:

dotnet build --framework netcoreapp3.1
dotnet build --framework netstandard2.0
dotnet pack --no-build

Also, interestingly, the order in which you list the target frameworks will produce different errors:

netstandard2.0;netcoreapp3.1

<TargetFrameworks>netstandard2.0;netcoreapp3.1</TargetFrameworks>

MSB4057: The target "GenerateOpenApiDocuments" does not exist in the project.

netcoreapp3.1;netstandard2.0

<TargetFrameworks>netcoreapp3.1;netstandard2.0</TargetFrameworks>

Assembly 'D:\dev\proj\bin\Debug\netcoreapp3.1\proj.dll' does not contain an entry point. The command "dotnet "D:\dev\packages\cache\microsoft.extensions.apidescription.server\3.0.0\build\/../tools/dotnet-getdocument.dll" --assembly "D:\dev\proj\bin\Debug\netcoreapp3.1\proj.dll" --file-list "obj\proj.OpenApiFiles.cache" --framework ".NETCoreApp,Version=v3.1" --output "obj" --project "proj" --assets-file "D:\dev\proj\obj\project.assets.json" --platform "AnyCPU" " exited with code 3. 1>Done building project "proj.csproj" -- FAILED.

krispenner commented 4 years ago

I've also noticed that you can ignore the error as both targets are correctly built, but some post build process named GenerateOpenApiDocuments fails which I don't think is actually required.

krispenner commented 4 years ago

I've narrowed this down to the referenced package in Swashbuckle 5.x: https://github.com/dotnet/aspnetcore/tree/master/src/Tools/Extensions.ApiDescription.Server

Options listed here: https://github.com/dotnet/aspnetcore/blob/master/src/Tools/Extensions.ApiDescription.Server/src/build/Microsoft.Extensions.ApiDescription.Server.props

Just add this to your csproj file and it will disable trying to generate your swagger file:

    <PropertyGroup>
        <TargetFrameworks>netcoreapp3.1;netstandard2.0</TargetFrameworks>
        <OpenApiGenerateDocuments>false</OpenApiGenerateDocuments>
    </PropertyGroup>

Or you can disabled it on build events only:

    <PropertyGroup>
        <TargetFrameworks>netcoreapp3.1;netstandard2.0</TargetFrameworks>
        <OpenApiGenerateDocumentsOnBuild>false</OpenApiGenerateDocumentsOnBuild>
    </PropertyGroup>
DerTolleEmil commented 4 years ago

I have run into this issue as well. It can be fixed by manually adding the target to your project file; The definition can be found here:

https://github.com/dotnet/aspnetcore/blob/master/src/Tools/Extensions.ApiDescription.Server/src/build/Microsoft.Extensions.ApiDescription.Server.targets

<Target Name="GenerateOpenApiDocuments" Inputs="$(TargetPath)" Outputs="$(_OpenApiDocumentsCache)">
    <!-- E.g. project sets $(OpenApiGenerateDocumentsOnBuild) to 'true' but $(OpenApiGenerateDocuments) is 'false'. -->
    <Error Condition=" '$(OpenApiGenerateDocuments)' != 'true' " Text="OpenAPI document generation is disabled. Add '&lt;OpenApiGenerateDocuments&gt;true&lt;/OpenApiGenerateDocuments&gt;' to the project." />
    <!-- E.g. project sets $(OpenApiGenerateDocuments) to 'true' but TFM is not supported. -->
    <Error Condition=" '$(TargetFrameworkIdentifier)' == '.NETCoreApp' AND '$(TargetFrameworkVersion.TrimStart(&quot;vV&quot;))' &lt; '2.1' " Text="OpenAPI document generation is not supported when targeting netcoreapp2.0 or earlier. Disable the feature or move to a later target framework." />

    <PropertyGroup>
        <_Command>dotnet "$(MSBuildThisFileDirectory)/../tools/dotnet-getdocument.dll" --assembly "$(TargetPath)"</_Command>
        <_Command>$(_Command) --file-list "$(_OpenApiDocumentsCache)" --framework "$(TargetFrameworkMoniker)"</_Command>
        <_Command>$(_Command) --output "$(OpenApiDocumentsDirectory.TrimEnd('\'))" --project "$(MSBuildProjectName)"</_Command>
        <_Command Condition=" '$(ProjectAssetsFile)' != '' ">$(_Command) --assets-file "$(ProjectAssetsFile)"</_Command>
        <_Command Condition=" '$(PlatformTarget)' != '' ">$(_Command) --platform "$(PlatformTarget)"</_Command>
        <_Command Condition=" '$(PlatformTarget)' == '' AND '$(Platform)' != '' ">$(_Command) --platform "$(Platform)"</_Command>
        <_Command Condition=" '$(RuntimeIdentifier)' != '' ">$(_Command) --runtime "$(RuntimeIdentifier)"</_Command>
        <_Command>$(_Command) $(OpenApiGenerateDocumentsOptions)</_Command>
    </PropertyGroup>

    <Message Importance="high" Text="%0AGenerateOpenApiDocuments:" />
    <Message Importance="high" Text="  $(_Command)" />
    <Exec Command="$(_Command)" LogStandardErrorAsError="true" />
</Target>
torfikarl commented 4 years ago

This issue just caused me a huge headache all day/evening, such an obscure error message from VS as well.

Thankfully @bigwheels490's solution worked, targeting each framework version from the command line individually and then packing with the --no-build flag. Cheers!

lachezar-gizdov commented 11 months ago

why is this still not fixed for .net 8.0?