How to reference assemblies using Visual Studio Code? - c#

I would like to reference the System.Drawing.dll in a console app I am writing using Visual Studio Code on OSX. i.e. I want to use these using statements
using System.Drawing;
using System.Drawing.Imaging;
to avoid this build error
Program.cs(56,20): error CS0246: The type or namespace name `Bitmap' could not be found. Are you missing an assembly reference?
I can't find a tutorial on this, I don't even know if the dll is available in .net core or mono or whatever visual-studio-code uses.

In your .csproj file, add your dependency as a PackageReference in an ItemGroup, then run dotnet restore or nuget restore. Example:
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Xml" />
<Reference Include="System.Core" />
<Reference Include="Xamarin.iOS" />
<PackageReference Include="Realm" Version="2.1.0" />
<PackageReference Include="xunit">
<Version>2.3.1</Version>
</PackageReference>
</ItemGroup>
Take a look at this article for a full explanation.

The new .NET Core SDK restore command is dotnet restore
To add any asssembly reference in Visual Studio Code, please refer to my post.

Mono offers a WinForms pipeline implementation that you can leverage, that includes support for System.Drawing.

Related

Project reference not resolved when running dotnet build

I have a Visual Studio 2022 solution, with multiple projects, but four in particular are interesting here.
Provider1 which is based on .NET Framework 4.
Provider2 which is based on .NET 6.
Provider1Test which is based on .NET Framework 4.
Provider2Test which is based on .NET 6.
The Provider1 project has a number of classes, all in the Provider.Data namespace, one of them being Class1. This is my source code. The Provider1.csproj file:
<ItemGroup>
<Compile Include="Class1.cs">
<SubType>Code</SubType>
</Compile>
...
</ItemGroup>
The Class1.cs file:
namespace Provider.Data
{
public class Class1
{
...
}
}
The Provider2 project has links to these source files, i.e. "Add"->"Existing item"->"As link". It compiles with different conditional compilation symbols, so the output is not the same as for the Provider1 project.
The Provider2.csproj file:
<ItemGroup>
<Compile Include="..\Provider1\Class1.cs" Link="Class1.cs" />
</ItemGroup>
The Provider1Test project is an NUnit test project, that tests Provider1. It has multiple test classes, one of them is TestClass1.
The Provider2Test project is also a NUnit test project, with a ProjectReference to Provider2. It links to the test classes in Provider1Test in the same way as the source code does. The Provider2Test.csproj file:
<ItemGroup>
<ProjectReference Include="..\Provider2\Provider2.csproj" />
</ItemGroup>
<ItemGroup>
<Compile Include="..\Provider1Test\TestClass1.cs" Link="TestClass1.cs" />
</ItemGroup>
The TestClass1.cs file:
using Provider.Data;
namespace ProviderTests
{
public class TestClass1
{
...
}
}
Now, this builds and runs just fine inside Visual Studio, but if I navigate to the Provider2Test folder and try to build with the dotnet build command, it doesn't find the source code.
C:\dev\DataProvider\Provider2Test>dotnet build
MSBuild version 17.3.1+2badb37d1 for .NET
Determining projects to restore...
All projects are up-to-date for restore.
Provider2 -> C:\dev\DataProvider\Provider2\bin\x64\Debug\net6.0\Provider.Data.dll
1 file(s) copied.
C:\dev\DataProvider\Provider1Test\TestClass1.cs(14,7): error CS0246: The type or namespace name 'Provider' could not be found (are you missing a using directive or an assembly reference?) [C:\dev\DataProvider\Provider2Test\Provider2Test.csproj]
Build FAILED.
What is the issue here, why doesn't dotnet build follow the reference path here, and how do I solve it?
I tried to create a TestClass2.cs file directly in Provider2Test, that is not a link but a standard compile include, and also using the Provider.Data namespace. It produces the same error.
I found a workaround, so I'm posting it here and I'm going with it for now, but I don't think it's a good solution, and it doesn't explain the original issue, so I'm not going to mark this as the accepted answer.
In Provider2.csproj, I added that if it is built with dotnet build, it has a post-build event that copies its source code dll to Provider2Test. This is not run if the project is build within Visual Studio ("$(MSBuildRuntimeType)" == "Full").
if "$(MSBuildRuntimeType)" == "Core" XCOPY "$(OutDir)Provider.Data.dll" "$(ProjectDir)..\Provider2Test\$(OutDir)" /Y /F
In Provider2Test.csproj I added a conditional assembly reference.
<ItemGroup>
<Reference Include="Provider.Data" Condition="$(MSBuildRuntimeType) == 'Core'">
<HintPath>$(OutDir)Provider.Data.dll</HintPath>
</Reference>
</ItemGroup>
I kept the ProjectReference in all cases (both "Full" and "Core"), in order to trigger a Provider2 build whenever Provider2Test is built.

Newtonsoft.Json dependency not publishing with the right version on "dotnet publish -o <other folder>"

Problem
So basically, i'm in DLL hell.
I have a dotnet 5.0 + react project where a C# dependency (I assume Microsoft.AspNetCore.Mvc.NewtonsoftJson) needs another one Newtonsoft.Json.
When building and publishing in release or debug in the bin folder, the project runs perfectly fine and all the dependencies and .dll are loaded correctly. But as soon as I use the option -o for dotnet publish, the Newtonsoft.Json.dll created in the published folder is of version 9.0.0.0, which throws an error when trying to run the server in production, since it expects it to be of version 12.x.x.x.
What I've tried
Currently I have a fix, which is to build independently the correct version (12.x.x.x or higher) of the dll file of Newtsoft.Json and put it in the published folder when going in production, but obviously I would like to know of other possible fixes or more direct ones without needing to do extra steps when deploying in production and help people who face the same problem with this dependency or another in the future.
I have tried including the dependency explicitely with the correct version in the .csproj but the dependency still was outputing at version 9.0.0.0.
Another fix would be to downgrade the Microsoft.AspNetCore.Mvc.NewtonsoftJson to a version that accepts 9.0.0.0 but that opens up a whole other can of worms
I have tried clearing my nuget packages, that did not work either.
I have tried this very recent stack overflow solution where the OP faced a similar issue, but their fix of adding False to their test project didn't work for me, since my test project does not use Newtonsoft.Json.
Files
dependencies listed in the .csproj
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.JsonPatch" Version="5.0.11" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="5.0.10" />
<PackageReference Include="Microsoft.AspNetCore.SpaServices.Extensions" Version="5.0.6" />
<PackageReference Include="Microsoft.AspNetCore.ApiAuthorization.IdentityServer" Version="5.0.6" />
<PackageReference Include="Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore" Version="5.0.6" />
<PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="5.0.6" />
<PackageReference Include="Microsoft.AspNetCore.Identity.UI" Version="5.0.6" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="5.0.6" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="5.0.6" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="5.0.6" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
<PackageReference Include="Newtonsoft.Json.Bson" Version="1.0.2" />
<PackageReference Include="System.Data.SqlClient" Version="4.8.3" />
</ItemGroup>
Outputed Newtonsoft.Json.dll
// C:\Users\***\published\Newtonsoft.Json.dll
// Newtonsoft.Json, Version=9.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed
// Global type: <Module>
// Architecture: AnyCPU (64-bit preferred)
// Runtime: v4.0.30319
// This assembly is signed with a strong name key.
// Hash algorithm: SHA1
// Public key: 0024000004800000940000000602000000240000525341310004000001000100f561df277c6c0b497d629032b410cdcf286e537c054724f7ffa0164345f62b3e642029d7a80cc351918955328c4adc8a048823ef90b0cf38ea7db0d729caf2b633c3babe08b0310198c1081995c19029bc675193744eab9d7345b8a67258ec17d112cebdbbb2a281487dceeafb9d83aa930f32103fbe1d2911425bc5744002c7
using System;
using System.Diagnostics;
using System.Reflection;
using System.Resources;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(/*Could not decode attribute arguments.*/)]
[assembly: AssemblyInformationalVersion("9.0.1")]
[assembly: NeutralResourcesLanguage("en-US")]
[assembly: TargetFramework(".NETStandard,Version=v1.0")]
[assembly: AssemblyTitle("Json.NET .NET Standard 1.0")]
[assembly: InternalsVisibleTo("Newtonsoft.Json.Schema, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f561df277c6c0b497d629032b410cdcf286e537c054724f7ffa0164345f62b3e642029d7a80cc351918955328c4adc8a048823ef90b0cf38ea7db0d729caf2b633c3babe08b0310198c1081995c19029bc675193744eab9d7345b8a67258ec17d112cebdbbb2a281487dceeafb9d83aa930f32103fbe1d2911425bc5744002c7")]
[assembly: InternalsVisibleTo("Newtonsoft.Json.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f561df277c6c0b497d629032b410cdcf286e537c054724f7ffa0164345f62b3e642029d7a80cc351918955328c4adc8a048823ef90b0cf38ea7db0d729caf2b633c3babe08b0310198c1081995c19029bc675193744eab9d7345b8a67258ec17d112cebdbbb2a281487dceeafb9d83aa930f32103fbe1d2911425bc5744002c7")]
[assembly: InternalsVisibleTo("Newtonsoft.Json.Dynamic, PublicKey=0024000004800000940000000602000000240000525341310004000001000100cbd8d53b9d7de30f1f1278f636ec462cf9c254991291e66ebb157a885638a517887633b898ccbcf0d5c5ff7be85a6abe9e765d0ac7cd33c68dac67e7e64530e8222101109f154ab14a941c490ac155cd1d4fcba0fabb49016b4ef28593b015cab5937da31172f03f67d09edda404b88a60023f062ae71d0b2e4438b74cc11dc9")]
[assembly: AssemblyDescription("Json.NET is a popular high-performance JSON framework for .NET")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Newtonsoft")]
[assembly: AssemblyProduct("Json.NET")]
[assembly: AssemblyCopyright("Copyright © James Newton-King 2008")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyFileVersion("9.0.1.19813")]
[assembly: CLSCompliant(true)]
[assembly: AssemblyVersion("9.0.0.0")]
Wish I could give an explanation WHY it happens but I actually don't get it. One clue is to check your project.assets.json in the /obj folder for which dependency actually requires Newtonsoft in the version 9 (do a full-text search on the exact version number).
Then if you have identified the package(s) - in our case it was Microsoft.Extensions.DependencyModel - you can upgrade the package so that it uses a newer Newtonsoft version. In our case we explicitely added this package in the upgraded version. Alternatively, setting "PrivateAssets=true" onto the dependency seems to work too.
If there are some packages with version 9 and some with other packages we actually noticed that the behavior not deterministic, so the published DLL will sometimes be version 9 and sometimes version 13.

Visual Studio cannot publish

I tried this with a new project just to confirm that I have not made any errors, but Visual Studio 2019 won't publish any dot net core project. Below is the error I am getting... Any help would be much appreciated...
Severity Code Description Project File Line Suppression State
Error The "TransformAppSettings" task failed unexpectedly.
System.IO.FileNotFoundException: Could not load file or assembly 'Newtonsoft.Json, Version=10.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed' or one of its dependencies. The system cannot find the file specified.
File name: 'Newtonsoft.Json, Version=10.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed'
at Microsoft.NET.Sdk.Publish.Tasks.AppSettingsTransform.UpdateDestinationConnectionStringEntries(String destinationAppSettingsFilePath, ITaskItem[] destinationConnectionStrings)
at Microsoft.NET.Sdk.Publish.Tasks.TransformAppSettings.TransformAppSettingsInternal()
at Microsoft.NET.Sdk.Publish.Tasks.TransformAppSettings.Execute()
at Microsoft.Build.BackEnd.TaskExecutionHost.Microsoft.Build.BackEnd.ITaskExecutionHost.Execute()
at Microsoft.Build.BackEnd.TaskBuilder.d__26.MoveNext()
WRN: Assembly binding logging is turned OFF.
To enable assembly bind failure logging, set the registry value [HKLM\Software\Microsoft\Fusion!EnableLog] (DWORD) to 1.
Note: There is some performance penalty associated with assembly bind failure logging.
To turn this feature off, remove the registry value [HKLM\Software\Microsoft\Fusion!EnableLog]. ProjectNameX 0
Here is my project file
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>netcoreapp3.0</TargetFramework>
<UserSecretsId>aspnet-ProjectNameX-A0D4A38F-C3FA-4FD3-8EBC-0F2201FBCD57</UserSecretsId>
<DockerDefaultTargetOS>Linux</DockerDefaultTargetOS>
<DockerfileContext>..\..\..</DockerfileContext>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore" Version="3.0.0-preview6.19307.2" />
<PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="3.0.0-preview6.19307.2" />
<PackageReference Include="Microsoft.AspNetCore.Identity.UI" Version="3.0.0-preview6.19307.2" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="3.0.0-preview6.19304.10" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="3.0.0-preview6.19304.10" />
<PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.7.12" />
</ItemGroup>
While digging into visual studio folders, I found this...
Please check if Newtonsoft.Jsonis referenced in your solution. It seems solution is not able to find it.
Below link shows how to add it.
https://learn.microsoft.com/en-us/nuget/quickstart/install-and-use-a-package-in-visual-studio
Can you try publishing using a different Visual Studio 2019 instance? Not with the preview version of course.
The error has nothing to do with your project. The error message "clearly" says that Microsoft.NET.Sdk.Publish.Tasks.TransformAppSettings.TransformAppSettingsInternal() tried to access Newtonsoft.Json. This is obviously not your code.
I find this very strange, as Microsoft.NET.Sdk.Publish.Tasks.dll exists in the same directory as Newtonsoft.Json.dll (check c:\program files\dotnet\sdk), and it should have been compiled against the same version that ships. You can confirm using something like ILSpy to see what the assembly version of Newtonsoft.Json is and what assembly reference the publish tasks dll has. You can also better understand the paths and dlls that .NET used to try to load the dll, and why any dll with a matching filename was not used, using Fusion Logs. But I'm not going to write a tutorial on using Fusion Logs here.
In any case, understanding why it's happening won't help you solve it. All you can really do is make sure you're using the latest SDK, install the newest version if not, and if the problem still exists using the Visual Studio "report a problem" tool to let the .NET Core team know about this.
I faced similar issue.
In package manager console execute: Update-Package –reinstall Newtonsoft.Json
Though you haven't added package reference in .csproj. Open the project.assets.json file in your obj folder and search for Newtonsoft.Json you would find the real version you refer to.
So just check if binding redirect can help. If not, check if this issue persists if you create a new .net core empty web-app. Then publish it to locate the issue according to the result whether it succeeds or not.

servicestack 4.5.14 & .Net Core 2.0

I was excited to read that the latest release version of ServiceStack (4.5.14) supports .Net Core 2.0 (see release notes). I tried adding ServiceStack 4.5.14 to my application targeting .Net Core 2.0.
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>netcoreapp2.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<Folder Include="wwwroot\" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.All" Version="2.0.3" />
<PackageReference Include="ServiceStack" Version="4.5.14" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Local.Service\Local.Service.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Update="Microsoft.NETCore.App" Version="2.0.3" />
</ItemGroup>
</Project>
When I build the project, I get the following error:
Severity Code Description Project File Line Suppression State
Error CS1061 'IApplicationBuilder' does not contain a definition for 'UseServiceStack' and no extension method 'UseServiceStack' accepting a first argument of type 'IApplicationBuilder' could be found (are you missing a using directive or an assembly reference?) Startup ...\Startup\Startup.cs 24 Active
And warnings for each of the ServiceStack packages like this one:
Severity Code Description Project File Line Suppression State
Warning NU1701 Package 'ServiceStack 4.5.14' was restored using '.NETFramework,Version=v4.6.1' instead of the project target framework '.NETCoreApp,Version=v2.0'. This package may not be fully compatible with your project. Local.Service ...\Local.Service\Local.Service.csproj 1
The release notes to which I referred above reference example applications provided by the ServiceStack team. However, all of the examples that support .Net Core 2.0 are also using ServiceStack 5.0 and not 4.5.14.
I added ServiceStack 5.0 to my project, and it does work nicely with .Net Core 2.0. I would prefer to use a release version of the package, though, if possible.
Does v4.5.14 really support .Net Core 2.0? If so, how?
You need to use the ServiceStack.*.Core packages rather than the 4.5.14 packages.
If you read further through the release notes, you'll see that .NET Core packages still aren't merged into the regular release packages. That's planned for v5:
Merging the .NET Core packages into main packages where they’ll share
the same version and release cadence
The .NET Core 2.0 starter app is also deceptive as it references ServiceStack's MyGet feed and includes version 5 rather than 4.5.14.

How do you multi-target a .NET Core class library with csproj?

When .NET Core still used the project.json format, you could build a class library targeting multiple frameworks (e.g. net451, netcoreapp1.0).
Now that the official project format is csproj using MSBuild, how do you specify multiple frameworks to target? I am trying to look for this from the project settings in VS2017, but I am able to only target a single framework from the .NET Core frameworks (it doesn't even list the other full .NET Framework versions which I do have installed):
You need to manually edit the project file and add s to the default TargetFramework and basically change it to TargetFrameworks. Then you mention the Moniker with a ; separator.
Also you can put the Nuget package references in a conditional ItemGroup manually or using VS Nuget Package Manager.
Here is what your .csproj should look like:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>netstandard1.6;net452</TargetFrameworks>
</PropertyGroup>
<ItemGroup Condition="'$(TargetFramework)' == 'net452'">
<PackageReference Include="Microsoft.Azure.DocumentDB">
<Version>1.12.0</Version>
</PackageReference>
</ItemGroup>
<ItemGroup Condition="'$(TargetFramework)' == 'netstandard1.6'">
<PackageReference Include="Microsoft.Azure.DocumentDB.Core">
<Version>1.1.0</Version>
</PackageReference>
</ItemGroup>
</Project>
Another workaround I do these days because of missing documentation is that I create a project in VS2015 and form the project.json using the available documentation and intellisense, then open the solution in VS2017 and use the built-in upgrade. I will then look at the csproj file to figure out how to make that configuration happen.
Multi-targeting more esoteric targets without a Moniker:
Microsoft:
PCLs are not recommended+
Although PCLs are supported, package authors should support
netstandard instead. The .NET Platform Standard is an evolution of
PCLs and represents binary portability across platforms using a single
moniker that isn't tied to a static like like portable-a+b+c monikers.
If you want to target a Portable Profile it doesn't have a predefined moniker so Portable Profiles also can't infer TargetFrameworkIdentifier, TargetFrameworkVersion, and TargetFrameworkProfile. Also a compiler constant isn't defined automatically. Finally you have to add all assembly references none are provided by default.
This Example below is taken from a project that used the dynamic keyword so it additionally needed the Microsoft.CSharp assembly, thus you can see how it's references for different targets.
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>netstandard1.5;net40;portable40-net45+sl5+win8+wp8</TargetFrameworks>
</PropertyGroup>
<PropertyGroup Condition="'$(TargetFramework)'=='portable40-net45+sl5+win8+wp8'">
<TargetFrameworkIdentifier>.NETPortable</TargetFrameworkIdentifier>
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
<TargetFrameworkProfile>Profile158</TargetFrameworkProfile>
<DefineConstants>$(DefineConstants);PORTABLE158</DefineConstants>
</PropertyGroup>
<ItemGroup Condition="'$(TargetFramework)'=='netstandard1.5'">
<PackageReference Include="Microsoft.CSharp" Version="4.3.0" />
<PackageReference Include="System.ComponentModel" Version="4.3.0" />
</ItemGroup>
<ItemGroup Condition="'$(TargetFramework)'=='net40'">
<Reference Include="Microsoft.CSharp" />
</ItemGroup>
<ItemGroup Condition="'$(TargetFramework)'=='portable40-net45+sl5+win8+wp8'">
<Reference Include="Microsoft.CSharp" />
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Windows" />
</ItemGroup>
</Project>
You can manually edit .csproj file for this and set TargetFrameworks (not TargetFramework) property.
<TargetFrameworks>net451;netstandard1.4</TargetFrameworks>
For example see EFCore.csproj:
https://github.com/aspnet/EntityFrameworkCore/blob/951e4826a38ad5499b9b3ec6645e47c825fa842a/src/EFCore/EFCore.csproj
I actually selected Class Library (.NET Core).
That is not the project template you want if your library needs to work on multiple platform targets. With this project template, your library can only ever be used in a project that targets .NETCore. The PCL library approach was retired, you now have to pick a .NETStandard.
You do so by starting the project with the "Class Library (.NET Standard)" project template. You now have the option of picking the .NETStandard version. The current compatibility grid is here.
Hopefully they'll keep that linked article updated. This is in flux, .NETStandard 2.0 was nailed down but does not ship yet. Targeted for Q2 of 2017, end of spring probably, it currently shows as 97% done. I overheard the designers saying that using 1.5 or 1.6 is not recommended, not compatible enough with 2.0
I did a simple guide to multi-targeting net framework and netcore which starts with the minimum 15 second fix but then walks you through each of the complications.
The very simplest approach is:
First, get a netcore or netstandard target working.
Then
Edit the .csproj project file and work through these steps for the other targets.
Change the <TargetFramework> tag to <TargetFrameworks> and add your next target to the list, delimited by ;
Learn about conditional sections in your csproj file. Create one for each target. Use them to declare dependencies for each target.
Add <Reference />s for System.* dlls for any netframework targets just by reading what the build error messages say is missing.
Deal with NuGet <PackageReference />s dependencies in the cases where they are not the same for each target. (The easiest trick here is to temporarily revert to single targetting so that the GUI will just handle the Nuget references correctly for you).
If you must: learn a creative variety of techniques, workarounds and timesavers to deal with code that doesn’t compile on all targets.
Know when to cut your losses when the cost of adding more targets is too high.

Categories

Resources