I've added a new Class Library (Package) project to my solution. It's my first experience with a .NET Core (or whatever I'm using, still confused)
My class library contains two references: .NET Framework 4.5.1 and .NET Platform 5.4
I'm trying to import some code from a sample project that uses IPrincipal. For some reason it's saying that it doesn't exist on namespace "System.Security" altohugh I can get it trough intellisense.
What's wrong with my project settings?
The new feature of .NET Core and Class Library (Package) is that it targets multiple platform and will compile into multiple assemblies which get automatically packaged into a nuget package.
When your class library targets multiple targets, it will compile to all of them. So if a certain library is only available on full .NET framework but not on .NET Core or other target framework, then you may receive intellisense if your editor is set to .NET 4.5. More information can be found in my other recent answer.
You can switch back and forth with the pull down menu on top left of the coding window, show in the screenshot below.
If you do not want to target a certain framework, you have to remove it's moniker from the project.json file or use preprocessor directives to write platform specific code or libraries/replacements.
.NET Core is heavily modularized and most of only the core modules are referenced in the default project and if you need additional one you need to reference them within the dotnet5.x section.
Basically you have multiple places with "dependencies" in your project.json, a global one where you can add dependencies which are available on all targeted frameworks and one within each "frameworks" section for each of the targets only.
Though the other answer covers some basic concepts, it would require some attention on which classes are available and which are not.
Microsoft temporarily host a web site at http://packagesearch.azurewebsites.net to assist.
If you can find a suitable package for RC1 from there, then you can add it to your project.json file. If not, you will have to conditional compile it to a desktop profile or use other alternatives.
Related
We are upgrading our project to .NET 6 from .NET Framework 4.5. We have a windows form application. Many of windows form commands has been depriciated in .NET 6. So to tackle this, I changed one of the Windows Forms project in the solution from:
<PropertyGroup>
<TargetFramework>net6.0-windows</TargetFramework>
</PropertyGroup>
to
<PropertyGroup>
<TargetFrameworks>net45;net6.0-windows</TargetFrameworks>
</PropertyGroup>
Now after changing this, I get the below error:
Project <another_project> targets 'net6.0-windows'. It cannot be referenced by a project that targets '.NETFramework,Version=v4.7.2'.
I understand why another_project is throwing this error message which is because the another_project is referenced in this Windows Form project and another_project's TargetFramework is .NET 6. So, I can change the TargetFramework for another_project to include .NET 4.5 as well.
But my question is, if I change this TargetFramework to TargetFrameworks and add multiple Framework there, does that mean my project is not upgrading to .NET 6 completely. Since it's using .net45 to complie/build in those cases, where it's failing to build in .NET 6. How does TargetFrameworks work??
I found the below link also, TargetFramework vs. TargetFrameworks (plural). But was not much helpful to understand this.
I'm assuming that you've upgraded your project files to SDK-style.
<TargetFrameworks>net45;net6.0-windows</TargetFrameworks> will effectively build your project twice - once for .NET 6.0 and once for .NET Framework 4.5.
(I'm not sure why your .NET Framework project is still targeting .NET 4.5 - I would have thought you should have retargeted it to 4.8 a long time ago...)
The output folders for these two targets will be:
For the DEBUG build:
\bin\Debug\net6.0-windows
\bin\Debug\net48
For the RELEASE build:
\bin\Release\net6.0-windows
\bin\Release\net48
Now if you want to reference one of those assemblies in another project, you're going to need to decide which to use, depending on the target framework for the dependent project.
In your case, it seems that you should be referencing the one in the "net6.0-windows" folder, so you should change your other project to reference that.
However, if you want the dependent project to ALSO be multi-targeted, you will need to change the hint path in the dependent project to use a compile variable to select the correct one.
For example, suppose your multi-targeted dependent project currently references a DLL using the following hint path:
<Reference Include="YourLibraryName">
path to referenced dll\bin\debug\net45\YourLibrary.dll
</Reference>
(Where "path to referenced dll" is whatever path is needed to locate the library.)
Clearly that will only reference the DEBUG Net 4.5 version of the library. You want it to reference the correct debug or release version and the correct .Net 4.5 or .Net 6.0 version. To do that, you can change the hint path to:
<path to referenced dll>\bin\$(Configuration)\$(TargetFramework)\YourLibrary.dll
At build time, $(Configuration) is replaced with the correct DEBUG or RELEASE string, depending on whether you're building DEBUG or RELEASE.
Similarly, the $(TargetFramework) will be replaced with the current build target, taken from the <TargetFrameworks>net45;net6.0-windows</TargetFrameworks> setting - either "net45" or "net6.0-windows".
Doing this will cause the correct DLL to be chosen from your multi-targeted project on which this project depends.
Note that this only applies to references using HintPath as above. If you're using project references, things would be different.
Also note that it's also possible (and maybe better) to create a NuGet package which will handle the dependencies etc properly, but that's a whole different story.
TargetFrameworks is used to build same project to multiple frameworks (so you have binary for each of them in output). It's usually used by libraries so they can be consumed by app targeted for different frameworks or, much less frequently, by apps, so they could be run on different machines.
I guess neither of theses is your cases. You just need to rework your app so it uses only features available in .NET Core.
Since you have added both net45 and net6.0-windows to your project it means that it should be compliable for both frameworks (i.e. it will be compiled twice, for each of the target frameworks), but you are trying to add reference to net6.0 project, which can't be used from net45. You need to either upgrade both to net6.0 only, or add net45 to the another_project.
Though usually it is another way around (compared to what you are trying to do), you use multitargeting for library projects (i.e. another_project in this case if I understand correctly) and keep one version for the executables (i.e. WinForms project should keep it's version).
I have a library which is .NET standard version. This library will be used both .NET app and .NET Core apps. I want to use IConfiguration for .NET Core apps in my library but .NET apps throw an exception.
I need to check version or determine the application if .NET Core or .NET framework? I have tried get appsettings.json file to determine app type but getting root path different both .NET and .NET Core apps.
When I tried to get framework version of app it gives me library's version.
How can I distinguish which type of application it is? How can I achieve this?
There are several ways to solve your problem:
try to use more common parameters for your methods that requires string's, int's or custom classes instead. Is it really necessary to add a framework specific class or function or is there a better option?
You can use a multi-target configuration for your library which then requires #if NET45 and #elif NETSTANDARD2_0 code everywhere you have to use different logic for different frameworks. This could lead to not very well readable code.
Use two libraries, one for .NET Core apps (e.g. based on .NET Standard 2.1) and the other for .NET Framework (e.g. .NET FW 4.8). The .cs files from the .NET Standard library can then also be used in the .NET 4.8 library (if compatible features have been used). The .cs files can be selected e.g. in VS via "context menu > add existing element". When confirming the selected file(s), expand the dropdown option under "Add" and select "Add as Link". This way the file only needs to be maintained once (changes are applied in both libraries). Framework-specific files can then be added individually in the respective library, not as a link. Here's a good article about it.
These are just some examples, there might be of course other or better solutions to it.
Personally I would try to use independent arguments for my methods, if this is not possible I prefer the custom library solution for each framework version.
So my code which worked fine yesterday, screwed up when I added a .net 5.0 class library project to my solution.
Error CS1069 The type name 'Bitmap' could not be found in the namespace 'System.Drawing'. This type has been forwarded to assembly 'System.Drawing.Common, Version=0.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51' Consider adding a reference to that assembly.
There is just one problem, when i look at what replaced "References" it now says "Dependencies" and when I try to add a dependency, "Add reference" is gone and there are no more .net assemblies being shown except under COM projects and type libs and when I add system.drawing etc, the error still remains and the code remains unreadable.
There are multiple reasons for what you're experiencing, I'll try to explain with a variety of assorted (and unordered) bullet-points:
Why isn't System.Drawing in .NET Core?
".NET 5" is the next iteration of .NET Core 3.1, not the .NET Framework 4.8 (.NET 5 comes immediately after .NET Core 3.1, there was never was a ".NET Core 4" to avoid confusion with .NET Framework 4).
.NET Core (including .NET 5) is designed to be cross-platform (i.e. to support Windows, Linux, macOS) with a single runtime.
Whereas previously people had to target .NET Framework for Windows, and target Mono, Xamarin, Unity, UWP, Silverlight, etc - which made multi-platform development in C# a pain.
Note that while Windows, Linux, and macOS now all share the real McCoy .NET 5 (and Silverlight is dead), other platforms like Xamarin, Unity, Mono, and UWP still have their own separate implementations of .NET (CLR+BCL) hence the need for ".NET Standard". At least we don't need those weird "Shared Projects" and "Portable Framework" projects anymore, phew!
In the .NET Framework, the System.Drawing API is just a .NET wrapper over Win32's GDI/GDI+, which means it's not cross-platform.
While System.Drawing seems like a platform-independent API, if you look closely at public types and methods like Graphics, Brush, Bitmap, Image and so on you'll see that they're all just thin wrappers and leaky-abstractions over GDI+. Mono does have System.Drawing reimplemented for Linux, however they did it by reimplementing GDIPLUS.dll which is about as horrible as it sounds.
So because System.Drawing is not cross-platform it was removed from .NET Core's "in-box" API.
So now you're wondering how you can get System.Drawing in .NET Core...
How can I get System.Drawing in .NET Core?
Earlier questions asked on StackOverflow from when .NET Core was more anaemic (and not yet pitched as a replacement for .NET Framework 4) have suggested switching to completely different and incompatible (but cross-platform-by-design) library, such as ImageSharp or ImageProcessor, however a better solution for Windows-only applications exists: the official Microsoft Windows Compatibility Pack (note that the aforementioned blog article is from 2017; as of 2021 the Windows Compatibility Pack is pretty-much fully implemented now).
All you need to do is open the NuGet package manager built-in to Visual Studio and add Microsoft.Windows.Compatibility as a package-reference and magically System.Drawing will be available for use in your application. You can also access the NuGet package manager via the Dependencies context-menu in Solution Explorer.
If you're using the .NET CLI ("command-line interface", not the "common language infrastructure", hurrah for overloaded acronyms) then just run dotnet add package Microsoft.Windows.Compatibility.
But why can't I add assembly references in .NET Core like I used to in .NET Framework?
You can!. It's just that (as of April 2021, running Visual Studio 2019 16.9) the UI for adding an assembly reference is kinda horrible.
You can do it manually by editing your .csproj and adding a <Reference Include="pathToDll.dll" /> (in the same <ItemGroup> as the other references).
You can do it from within Visual Studio by ignoring the missing menu option and using the Add Project Reference dialog:
Follow these steps
Go Solution Explorer > Your Project > Dependencies > Add Project Reference.
In the popup dialog, choose the Browse tab:
Then click the Browse... button:
Then browse for your target assembly DLL:
Voila - the added assembly reference will appear under a new Assemblies node under Dependencies:
Do note that (generally speaking, there are exceptions) you can only reference assembly DLLs that target .NET Core or .NET Standard. Because most DLLs built for .NET Core and .NET Standard exist as NuGet packages anyway there isn't much need to add an assembly reference directly.
Microsoft seems to have migrated Add Reference to standard SDK assemblies to "Manage NuGet Packages".. a step I do not understand the point of since the correct assembly is mixed in with third party user contributed search results.
Simply click where references would have been and is now dependencies, and right-click and then click Manage Nuget Packages, do a search for the assembly and VERIFY that Microsoft published it and it meets the .net Core requirements.
Yeah they dropped the ball on this in my humble opinion. Took me a minute to figure out that standard assemblies do not appear to be installed on the system.
The package gets installed under your user account's home directory, not in a system-wide folder requiring elevated user permissions to access the dll, so if your account is bugged, you get to a nice infected copy of the assembly each and every time :)
I have a Visual Studio (2017) C# solution which is structured like this:
Solution
ExeProject
DLLProject
NuGet-Dependency to Stateless package ("Stateless" is the name of the package)
The DLLProject hides the dependency within its interfaces, i.e. the usage of the Stateless library is supposed to be an implementation detail of DLLProject.
The ExeProject accesses only the public interfaces and factories of DLLProject.
Due to reasons which go beyond the scope of this question, ExeProject targets .Net Framework 4.6.1, while DLLProject targets .Net Standard 2.0.
This compiles fine, but when debugging, the Stateless.dll is not found by the executable.
Is it possible to automatically deploy that DLL when linking against DLLProject without adding a Stateless NuGet dependency to the ExeProject?
In .NET Core this transitive NuGet dependencies work automatically.
On .NET Framework, there is a "Copy Local" option for referenced libraries. Make sure that it is set to True for the problematic one.
Update
For your case, .NET Framework App and .NET Standard lib, the setup requires manual modification of the .NET Framework app's .csproj file. Please follow:
Copy all dependencies from .Net Standard libraries to .Net Framework Console application
Will (or does) the DNX project support frameworks other than ASP.net (Such as WPF or windows forms)? I'd love to create some Wpf class libraries using the newer json project style (and native NuGet package support), but everything seems to be geared towards Asp.net.
Dnx is only for ASP.NET 5 projects (web, console or library).
It doesn't support WPF.
The project.json/xproj based project model (I would not call it DNX projects) can indeed be used to build nuget class libraries for scenarios beyond ASP.Net and DNX.
If you specify in your project.json a SDK like net451 you can additionally add frameworkassemblies like "PresentationCore" or "PresentationFramework" and then start coding in class files against WPF. So you can create a class library with it (i just tested it). It builds and packages itself to NuGet. That NuGet you can use then in your normal WPF project.
It is important to understand the concept of a SDK when talking about the new .Net Framework things: DNX is a SDK similar to UWP or the .Net Framework (WPF/WinForm). The SDK then specifies which CLR and BCL are used in combination with the features of the SDK. Consequently, this project format does not target the DNX SDK (from the architecture) but any SDK. In the end a class library is IL which has references to DLLs. Support for direct references with normal .csproj is planned (IMHO).
But there are restrictions: The project format is new, not yet well supported and integrated, there is no and maybe never will be a WPF designer etc.