Swashbuckle.WebApi icon indicating copy to clipboard operation
Swashbuckle.WebApi copied to clipboard

Referencing Swashbuckle.AspNetCore 5.0.0 in library with multiple targets

Open berndku opened this issue 5 years ago • 7 comments

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.

berndku avatar Feb 21 '20 17:02 berndku

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.

bigwheels490 avatar Mar 26 '20 20:03 bigwheels490

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 avatar Mar 29 '20 23:03 krispenner

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 avatar Mar 30 '20 07:03 krispenner

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>

krispenner avatar Apr 02 '20 20:04 krispenner

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>

DerTolleEmil avatar Jul 31 '20 08:07 DerTolleEmil

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!

torfikarl avatar Oct 06 '20 20:10 torfikarl

why is this still not fixed for .net 8.0?

lachezar-gizdov avatar Nov 23 '23 08:11 lachezar-gizdov