Introduction
In this tip, I will show you how I could convert my old csproj file into the new version of csproj. I will also tell you what kind of failures and stumbling blocks you can get on the way.
Before You Begin
If you use some 3rd-party DLLs, you have to ensure that they support the chosen netstandard version. It is unusual but possible that one of them may support PCL but not netstandard. If they are installed through NuGet, you can check them by NuGet. If they are coming from an other provider, you have to check it yourself.
The Original csproj
The original csproj file looks like:
="1.0"="utf-8"
<Project ToolsVersion="14.0" DefaultTargets="Build"
xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props"
Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<MinimumVisualStudioVersion>10.0</MinimumVisualStudioVersion>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{53561B15-7A94-4375-B9F5-4615EF3E6DB6}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>***********</RootNamespace>
<AssemblyName>************</AssemblyName>
<DefaultLanguage>en-US</DefaultLanguage>
<FileAlignment>512</FileAlignment>
<ProjectTypeGuids>{786C830F-07A1-408B-BD7F-6EE04809D6DB};
{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
<TargetFrameworkProfile>Profile44</TargetFrameworkProfile>
<TargetFrameworkVersion>v4.6</TargetFrameworkVersion>
<SccProjectName>SAK</SccProjectName>
<SccLocalPath>SAK</SccLocalPath>
<SccAuxPath>SAK</SccAuxPath>
<SccProvider>SAK</SccProvider>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Compile Include="Common\CloseRequest.cs" />
<Compile Include="Common\IAsyncOperations.cs" />
.............
</ItemGroup>
<ItemGroup>
<ProjectReference Include="***************">
<Project>{4C9A9142-43F2-4FDB-B041-C073AED6C4D6}</Project>
<Name>*****************</Name>
</ProjectReference>
.............
</ItemGroup>
<ItemGroup>
<Folder Include="Events\" />
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />
</ItemGroup>
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\Portable\$(TargetFrameworkVersion)\
Microsoft.Portable.CSharp.targets" />
</Project>
As you can see, it is a portable class library, which targets the profile44
.
The New csproj
The new csproj file is really simple:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<SccProjectName>SAK</SccProjectName>
<SccLocalPath>SAK</SccLocalPath>
<SccAuxPath>SAK</SccAuxPath>
<SccProvider>SAK</SccProvider>
</PropertyGroup>
<PropertyGroup>
<TargetFramework>netstandard1.6</TargetFramework>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\DS.Publications.Common\DS.Publications.Common.csproj"/>
</ItemGroup>
</Project>
Now we are targeting .NET-Standard 1.6!
So you have to replace everything until the ItemGroup
section with the ProjectReference
entries in it with this:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<SccProjectName>SAK</SccProjectName>
<SccLocalPath>SAK</SccLocalPath>
<SccAuxPath>SAK</SccAuxPath>
<SccProvider>SAK</SccProvider>
</PropertyGroup>
<PropertyGroup>
<TargetFramework>netstandard1.6</TargetFramework>
</PropertyGroup>
Note that the files are not listed in the csproj any more.
In my last projects, I am using TFS as source control, so I need these SAK (Should Already Know) lines, too. If you use an other source code control, you can delete those lines, too.
Then, you can simplify the ProjectReference
entries. Name
and the GUID
are unnecessary.
<ProjectReference Include="..\DS.Publications.Common\DS.Publications.Common.csproj"/>
Embedded Resources
Do not delete ItemGroup
-s with EmbeddedResource
or Content
!
<ItemGroup>
<EmbeddedResource Include="Resources\Welle320x480.png" />
</ItemGroup>
<ItemGroup>
<Content Include="ConverterExtensions.tt">
<Generator>TextTemplatingFileGenerator</Generator>
<LastGenOutput>ConverterExtensions.cs</LastGenOutput>
</Content>
</ItemGroup>
If you delete these lines, the png file will still be there in the project, but it is not an embedded resource any more, and the T4-Template is not a Content any more. But do not worry, you can set these properties in Visual Studio again.
The NuGet Packages
It is recommended that you reinstall your NuGet packages. So take a look at your old packages.config file what entries you had before. Notice them and delete the packages.config file. The new csproj format can store NuGet-Entries in the csproj file itself.
So I had the following entries:
<packages>
<package id="CommonServiceLocator" version="1.3"
targetFramework="portable45-net45+win8" />
<package id="MvvmLightLibs" version="5.3.0.0"
targetFramework="portable45-net45+win8" />
</packages>
After I deleted my packages.config, I open my solution and install the NuGet packages again. Visual Studio will ask you where the NuGet-entries should be stored. Choose the option for the csproj.
Other References
If you had other 3rd party DLLs referenced, you have to keep those lines also, but you can simplify them.
<Reference Include="SuperThirdParty.dll">
<HintPath>..\Dependencies\netstandard1.6\SuperThirdParty.dll</HintPath>
</Reference>
Or you can notice them and assign them again in Visual Studio.
Test Projects
You can also convert a testproject to the new format. But it cannot target netstandard1.6. It has to target netcoreapp1.1. Then it can reference the netstandard1.6 assemblies.
AssemblyInfo.cs Problem
I suppose you have had an AssemblyInfo.cs file in your old project. The new csproj format works another way, and it does not need any assemblyinfo.cs. The assembly's properties are stored in the csproj file. There are some default values, and the AssemblyInfo.cs will be generated at compile time. So if you also have your original AssemblyInfo.cs, you get errors at compile, because you have the properties twice. E.g.:
error CS0579: Duplicate 'AssemblyVersion' attribute
To solve this problem, you can choose one of the following:
- Delete your original AssemblyInfo.cs and set the properties manually on the project-properties page
- or you can keep the original AssemblyInfo.cs and disable the automatic generation in the csproj file with:
<PropertyGroup>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
</PropertyGroup>
The Other Projects
Normally, you have some other projects, which reference your new netstandard projects. In those projects, you will need an entry.
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
If you do not have this entry, you can get some failures only at runtime. For example:
Unhandled Exception: System.IO.FileLoadException: Could not load file or assembly
'System.Runtime.InteropServices.RuntimeInformation, Version=4.0.1.0, Culture=neutral,
PublicKeyToken=b03f5f7f11d50a3a' or one of its dependencies.
The located assembly's manifest definition does not match the assembly reference.
(Exception from HRESULT: 0x80131040)
Older csproj files do not have this tag, you have to insert it manually! Keep it in mind, if you update your existing projects.
See this link.
References of the Referenced Assemblies
There is still a bug in Visual Studio: the references of the referenced netstandard projects will not be copied to the output folder. You have to explicitly reference them! At least in your main / startup project. Otherwise, you get exceptions only at runtime, that a DLL cannot be found.
It is recommended that you install the NuGet package "NetStandard Library
" in your normal project too.
netstandard1.3
I've tried to use a netstandard1.6 library in a WPF project. I've always got some errors in the XAML designer. I've got the experience, that WPF can only work with netstandard1.3 libraries.
See this link.
Thank you for reading!
I wonder what kind of experiences you get by converting your projects. Do not hesitate to write them in the comments.