Unit Testing Public Signed .NET Core/Framework Libraries - c#

I have a NuGet package library project that is compiling for .NET Core and .NET Framework. It is also using the new public signing.
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup Label="Build">
<TargetFrameworks>netstandard2.0;net472</TargetFrameworks>
</PropertyGroup>
<PropertyGroup Label="Signing">
<SignAssembly>true</SignAssembly>
<AssemblyOriginatorKeyFile>../../Key.snk</AssemblyOriginatorKeyFile>
<PublicSign>true</PublicSign>
</PropertyGroup>
</Project>
I have an xUnit test project using which is also cross compiling to .NET Core and .NET Framework.
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup Label="Build">
<TargetFrameworks>netcoreapp3.1;net472</TargetFrameworks>
</PropertyGroup>
<ItemGroup Label="Package References">
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.4.0" />
<PackageReference Include="xunit" Version="2.4.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.1" />
</ItemGroup>
<ItemGroup Label="Project References">
<ProjectReference Include="..\..\Source\Foo\Foo.csproj" />
</ItemGroup>
</Project>
When I run the tests in this project, the .NET Core test run succeeds but the .NET Framework test run fails with:
System.IO.FileLoadException : Could not load file or assembly 'Foo, Version=0.0.1.0, Culture=neutral, PublicKeyToken=fc5550082a9c642c' or one of its dependencies. Strong name signature could not be verified. The assembly may have been tampered with, or it was delay signed but not fully signed with the correct private key. (Exception from HRESULT: 0x80131045)
How can I get them both to work?

Use
<PublicSign Condition=" '$(OS)' != 'Windows_NT' ">True</PublicSign>
Reference
#SNMP Library

Related

Multi-targeted UWP project can't refer .NET Standard 2.0 project

I have a multi-targeted project (MultiTargetedProj) that targets .NET Standard 2.0 and UWP. This project refers a .NET Standard 2.0 project (SayClassLibraryProj).
When building MultiTargetedProj, I get an error saying ClassLibraryProj's dll cannot be found:
7>CSC : error CS0006: Metadata file 'C:\Users\sanjay\Downloads\NewProjectStructurePOC-master(2)\NewProjectStructurePOC-master\ClassLibraryProj\bin\x64\Debug\uap10.0\ClassLibraryProj.dll' could not be found
7>Done building project "MultiTargetedProj.csproj" -- FAILED.
As per my understanding, ClassLibraryProj's bin should only have a sub folder for .NET Standard and not for UWP. Since my reference to ClassLibraryProj is non-conditional, multi targeted project should resolve correctly.
When I replace project references with direct DLL reference to the .NET Standard subfolder, the build succeeds.
Project configuration for MultiTargetedProj:
<Project Sdk="MSBuild.Sdk.Extras">
<PropertyGroup>
<TargetFrameworks>netstandard2.0;uap10.0</TargetFrameworks>
<AssemblyName>MultiTargetedProj</AssemblyName>
<RootNamespace>MultiTargetedProj</RootNamespace>
<Platforms>AnyCPU;x64;x86</Platforms>
<EnableDefaultCompileItems>false</EnableDefaultCompileItems>
<BaseOutputPath></BaseOutputPath>
<BaseIntermediateOutputPath></BaseIntermediateOutputPath>
</PropertyGroup>
<ItemGroup>
<!--<Reference Include="..\ClassLibraryProj\bin\x64\Debug\netstandard2.0\ClassLibraryProj.dll" />-->
<ProjectReference Include="..\ClassLibraryProj\ClassLibraryProj.csproj" />
</ItemGroup>
<PropertyGroup Condition=" $(TargetFramework.StartsWith('netcore')) ">
<DefineConstants>NET_CORE</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition=" $(TargetFramework.StartsWith('uap')) ">
<TargetPlatformVersion>10.0.19041.0</TargetPlatformVersion>
<TargetPlatformMinVersion>10.0 .18362.0</TargetPlatformMinVersion>
<DefineConstants>WINDOWS_UWP</DefineConstants>
<LanguageTargets>$(MSBuildExtensionsPath)\Microsoft\WindowsXaml\v$(VisualStudioVersion)\Microsoft.Windows.UI.Xaml.CSharp.targets</LanguageTargets>
</PropertyGroup>
<ItemGroup>
<EmbeddedResource Remove="obj\**" />
<None Remove="obj\**" />
</ItemGroup>
<ItemGroup>
...
</ItemGroup>
<ItemGroup Condition=" $(TargetFramework.StartsWith('uap')) ">
<Compile Include="UWP\**\*.cs" />
<PackageReference Include="Microsoft.NETCore.UniversalWindowsPlatform">
<Version>6.2.13</Version>
</PackageReference>
</ItemGroup>
<ItemGroup Condition=" $(TargetFramework.StartsWith('netcore')) ">
<Compile Include="NetCore\**\*.cs" />
</ItemGroup>
</Project>
This issue is only while using.NET SDK Version 6.0.302. On a different machine with .NET SDK Version 5.0.410, build succeeds.

Could not load file or assembly 'Microsoft.Extensions.Configuration.Abstractions, Version=3.0.0.0

I am migrating my .NET standard 2.0 class library application to .NET core 3.0 where I want to start web API server from class library, Where class library application is getting launched with executable.
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup Label="Globals">
<SccProjectName>SAK</SccProjectName>
<SccProvider>SAK</SccProvider>
<SccAuxPath>SAK</SccAuxPath>
<SccLocalPath>SAK</SccLocalPath>
<AppendTargetFrameworkToOutputPath>true</AppendTargetFrameworkToOutputPath>
</PropertyGroup>
<PropertyGroup>
<TargetFramework>netcoreapp3.0</TargetFramework>
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
</PropertyGroup>
<ItemGroup>
<FrameworkReference Include="Microsoft.AspNetCore.App" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="3.0.0" />
<PackageReference Include="RestSharp" Version="106.6.10" />
</ItemGroup>
</Project>
When class library application is getting launched with executable It throws error like below.
Creating of instance of type
'MySampleDll' failed: Could not load
file or assembly 'Microsoft.Extensions.Configuration.Abstractions,
Version=3.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60'.
The system cannot find the file specified.
When I download Microsoft.Extensions.Configuration.Abstractions from nuget package and manually keep the library in output directory. It throws new error saying Microsoft.AspNetCore 3.0.0 could not be found.
Please help me what I am doing wrong.
Get rid of Microsoft.AspNetCore.App, it's not needed any more, as explained in Microsoft documentation.
Also, consider upgrading to .NET Core 3.1 instead, which is an LTS version. .NET Core 3.0 has already reached end of life and is no longer supported.

'HttpClientHandler' does not contain a definition for 'ClientCertificates' in net461 and net47?

I'm making a NuGet package and my csproj looks like this:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup Label="Globals">
<SccProjectName>SAK</SccProjectName>
<SccProvider>SAK</SccProvider>
<SccAuxPath>SAK</SccAuxPath>
<SccLocalPath>SAK</SccLocalPath>
</PropertyGroup>
<PropertyGroup>
<TargetFrameworks>netstandard2.0;netstandard1.6;net461;net47</TargetFrameworks>
...
<PackageId>Package2</PackageId>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Package1\Package1.csproj" />
</ItemGroup>
<ItemGroup Condition="'$(TargetFramework)'=='net461' OR '$(TargetFramework)'=='net47'">
<Reference Include="System.Net.Http" />
</ItemGroup>
</Project>
The project it's referencing looks like this:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup Label="Globals">
<SccProjectName>SAK</SccProjectName>
<SccProvider>SAK</SccProvider>
<SccAuxPath>SAK</SccAuxPath>
<SccLocalPath>SAK</SccLocalPath>
</PropertyGroup>
<PropertyGroup>
<TargetFrameworks>netstandard2.0;netstandard1.6;net461;net47</TargetFrameworks>
<PackageId>Package1</PackageId>
...
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)'=='Debug'">
<NoWarn>1701;1702; CS1591</NoWarn>
</PropertyGroup>
<ItemGroup Condition="'$(TargetFramework)'=='netstandard1.6' OR '$(TargetFramework)'=='net461'">
<PackageReference Include="System.ValueTuple" Version="4.5.0" />
</ItemGroup>
<ItemGroup Condition="'$(TargetFramework)'=='net461' OR '$(TargetFramework)'=='net47'">
<Reference Include="System.Net.Http" />
</ItemGroup>
</Project>
And inside the Package2 project it has the following line:
webRequestHandler.ClientCertificates.Add(certificate);
But it isn't building in net461 or net47, saying:
'HttpClientHandler' does not contain a definition for
'ClientCertificates' and no accessible extension method
'ClientCertificates' accepting a first argument of type
'HttpClientHandler' could be found (are you missing a using
directive or an assembly reference?)
Package2(net461),
Package2(net47)
But the only thing I've changed is removed this from the csproj for package2:
<ItemGroup Condition="'$(TargetFramework)'=='netstandard2.0'">
<PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="2.0.0" />
</ItemGroup>
<ItemGroup Condition="'$(TargetFramework)'=='netstandard1.6' OR '$(TargetFramework)'=='net461' OR '$(TargetFramework)'=='net47'">
<PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="1.1.2" />
</ItemGroup>
Can anyone help me understand how to fix it? I don't really want to bring in that whole NuGet package just to fix this one dependency I think I'm just missing an assembly but as far as I know it should be in System.Net.Http which I should already be referencing (and so should the other project it's already dependent on).
Looks like this property is available from version 4.7.1:
https://learn.microsoft.com/en-us/dotnet/api/system.net.http.httpclienthandler.clientcertificates?view=netframework-4.7.1
Note that if you select an older .NET version, you'll see a message like this:
The requested page is not available for .NET Framework 4.7.
For me the solution was to download the newest version of "System.Net.Http".
You can find it through the NuGet package manager.
At the time of writing v4.3.4 is the newest version and it contains the ClientCertificates methode.
I've swapped out the assembly reference for the NuGet package:
<ItemGroup Condition="'$(TargetFramework)'=='net47' OR '$(TargetFramework)'=='net461'">
<PackageReference Include="System.Net.Http" Version="4.3.4" />
</ItemGroup>
pretty sure this is the wrong thing to do™ as the assembly reference in .NET Framework should be sufficient and I'm probably going to suffer many conflicting reference issues anywhere I install my package, but this is the best I can come up with right now.

NUnit TestRunner working directory is different depending on target framework of project

I am developing a library which has a test project in the solution. The library uses several framework from the .NET universe (like net462 or netcoreapp2.0) and works fine. The test project currently uses netcoreapp2.1 and the latest NUnit framework and test runner.
I have tests that rely on files that are included in the test project and are copied to the output folder during the build process. When the test project uses .NET Core as target framework, the files are found and the tests pass. When the test project uses anything else than .NET Core (I didn't test all .NET Framework versions, but some), the files are not found and the tests fail.
When not using .NET Core the working directory of the test runner seems to be located at C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\Common7\IDE\ which is not the project's output directory.
This is the not working project file
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net461</TargetFramework>
<IsPackable>false</IsPackable>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
<OutputPath>bin\Release\</OutputPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<OutputPath>bin\Debug\</OutputPath>
</PropertyGroup>
<PropertyGroup>
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.8.0" />
<PackageReference Include="NUnit" Version="3.10.1" />
<PackageReference Include="NUnit3TestAdapter" Version="3.10.0" />
</ItemGroup>
</Project>
And this is the working project file
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp2.1</TargetFramework>
<IsPackable>false</IsPackable>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
<OutputPath>bin\Release\</OutputPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<OutputPath>bin\Debug\</OutputPath>
</PropertyGroup>
<PropertyGroup>
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.8.0" />
<PackageReference Include="NUnit" Version="3.10.1" />
<PackageReference Include="NUnit3TestAdapter" Version="3.10.0" />
</ItemGroup>
</Project>
Does anyone know more about this behaviour? How do I fix this?
As explained in the cited issue, NUnit does not change the current working directory at all. This is by design, based on the notion that library programs should never change the cd but should leave it as set by the calling program.
There may be reasons why either the runner or Visual Studio itself changes the directory in the case of a .NET Core project. I don't know what they are but I do know that NUnit doesn't do it.
The obvious workaround is to use TestContext.TestDirectory in your tests. It is provided by NUnit for this purpose. Note that it only works in test code. If you need something similar outside of the test code, you can copy the logic from TestContext.TestDirectory, which is quite well tested.

.NET Core 2.0 Project Builds But Not When Referenced By Another .NET Core 2.0 Project

I'm on Ubuntu and I have two .NET Core 2.0 projects (Project Oranges.csproj and Apples.csproj). Oranges only contains references to NuGet packages, while Apples contains a reference to Oranges.
Running dotnet build -f netcoreapp2.0 Oranges.csproj succeeds! Oranges.dll now exists at /Oranges/bin/Debug/netcoreapp2.0/Oranges.dll.
Running dotnet build -f netcoreapp2.0 Apples.csproj fails with: error CS0009: Metadata file '/Oranges/bin/Debug/netcoreapp2.0/Oranges.dll' could not be opened -- PE image doesn't contain managed metadata
How can I go about referencing Oranges, which builds without issue, in Apples without issue?
Oranges.csproj
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
<TargetFrameworks>netcoreapp2.0;net451;</TargetFrameworks>
<RootNamespace>Oranges</RootNamespace>
<SignAssembly>true</SignAssembly>
<AssemblyOriginatorKeyFile>..\..\GeneratedKey.snk</AssemblyOriginatorKeyFile>
<DelaySign>false</DelaySign>
</PropertyGroup>
<PropertyGroup Condition="'$(TargetFramework)' == 'netcore2.0'">
<DefineConstants>NETCORE2_0</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$(TargetFramework)' == 'net451'">
<DefineConstants>NET4_5_1</DefineConstants>
</PropertyGroup>
<ItemGroup>
<None Remove="packages.config" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Newtonsoft.Json" Version="10.0.3" />
<PackageReference Include="System.Collections.Immutable" Version="1.4.0" />
</ItemGroup>
</Project>
Apples.csproj
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
<TargetFrameworks>netcoreapp2.0;net451;</TargetFrameworks>
<RootNamespace>Apples</RootNamespace>
<SignAssembly>true</SignAssembly>
<DelaySign>false</DelaySign>
<AssemblyOriginatorKeyFile>..\..\GeneratedKey.snk</AssemblyOriginatorKeyFile>
</PropertyGroup>
<ItemGroup>
<None Remove="packages.config" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="CommandLineParser" Version="2.1.1-beta" />
<PackageReference Include="Newtonsoft.Json" Version="10.0.3" />
<PackageReference Include="System.Collections.Immutable" Version="1.4.0" />
<PackageReference Include="System.Composition" Version="1.1.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Oranges\Oranges.csproj" />
</ItemGroup>
</Project>
After deleting the bin and obj folders from the project directory and rebuilding, a different error was being displayed.
CSC : error CS7027: Error signing output with public key from file 'GeneratedKey.snk' -- Assembly signing not supported. [.../Oranges/Oranges.csproj]
After some research I stumbled across a solution.
Assembly Signing Not Supported
Adding the line below to the .csproj file for each assembly that required signing resolved the issue.
<PublicSign Condition=" '$(OS)' != 'Windows_NT' ">true</PublicSign>
For now it seems like if you need to sign netcore assemblies, it should be done on Windows.

Categories

Resources