# Convert a .NET 4.x project to .NET Core

Steps to convert .csproj to new VS 2017 format (.NET 4.5 to .NET Core)

- delete any files inside the project folder but not included in the project
- unload project from visual studio
- edit .csproj
- a .csproj template with nuget packages, nuget info, code analysis, style cop:

````
<Project Sdk="Microsoft.NET.Sdk">
	<PropertyGroup>
		<TargetFrameworks>net45;netstandard2.0</TargetFrameworks>
		<RootNamespace>TODO</RootNamespace>
		<Authors>TODO</Authors>
		<Company>TODO</Company>
		<Description>TODO</Description>
		<Copyright>TODO</Copyright>
		<PackageTags>TODO</PackageTags>
		<IncludeSymbols>True</IncludeSymbols>
		<IncludeSource>True</IncludeSource>
		<PackageProjectUrl>TODO</PackageProjectUrl>
		<PackageLicenseUrl>TODO</PackageLicenseUrl>
		<RepositoryUrl>TODO</RepositoryUrl>
		<RepositoryType>git</RepositoryType>
		<Version>0.0.1</Version>
		<CodeAnalysisRuleSet>..\main.ruleset</CodeAnalysisRuleSet>
	</PropertyGroup>
	<ItemGroup>
		<AdditionalFiles Include="..\stylecop.json" Link="stylecop.json" />
	</ItemGroup>
	<ItemGroup>
		<PackageReference Include="SOME.NUGET.PACKAGE" Version="1.0.0" />
		<PackageReference Include="ConfigureAwaitChecker.Analyzer" Version="1.0.1">
			<PrivateAssets>All</PrivateAssets>
		</PackageReference>
		<PackageReference Include="Microsoft.CodeAnalysis.FxCopAnalyzers" Version="2.6.0">
			<PrivateAssets>All</PrivateAssets>
		</PackageReference>
		<PackageReference Include="StyleCop.Analyzers" Version="1.1.0-beta006">
			<PrivateAssets>All</PrivateAssets>
		</PackageReference>
	</ItemGroup>
	<ItemGroup>
	  <ProjectReference Include="..\ANOTHER.PROJECT\ANOTHER.PROJECT.csproj" />
	</ItemGroup>
</Project>
````

Here a csproj for unit tests (nunit)

````
<Project Sdk="Microsoft.NET.Sdk">

	<PropertyGroup>
		<TargetFrameworks>net45;netstandard2.0</TargetFrameworks>
		
		<IsPackable>false</IsPackable>
	</PropertyGroup>

	<ItemGroup>
		<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.7.0" />
		<PackageReference Include="Moq" Version="4.8.2" />
		<PackageReference Include="NUnit" Version="3.10.1" />
		<PackageReference Include="NUnit3TestAdapter" Version="3.10.0" />
	</ItemGroup>

	<ItemGroup>
	  <ProjectReference Include="..\..\src\YOUR_PROJECT\YOUR_PROJECT.csproj" />
	</ItemGroup>

  <ItemGroup>
    <DotNetCliToolReference Include="Microsoft.DotNet.Watcher.Tools" Version="2.0.0" />
  </ItemGroup>
</Project>
````


- Carefully choose the right target framework. See [.NET Standard](https://docs.microsoft.com/en-us/dotnet/standard/net-standard) and [Target frameworks](https://docs.microsoft.com/en-us/dotnet/standard/frameworks).


To compile the solution you can run:

	dotnet build -c Release

Inside Visual Studio Code use `/property:GenerateFullPaths=true` to generate absolute file path and allow `$msCompile` problemMatcher to work.

To create nuget packages:

	dotnet pack -c Release /p:Version=7.7.7

To exclude a csproj from package generator add the property:

	<IsPackable>false</IsPackable>


To run unit tests:

	dotnet test -c Release

Add `--logger:trx` to generate test results.

Unfortunately this give a warning for each project that doesn't container tests.
See https://github.com/Microsoft/vstest/issues/705

A workaround is to write:

	dotnet test ./tests/Your.Project.UnitTests/Your.Project.UnitTests.csproj -c Release

or run all tests projects with

	Get-ChildItem ".\tests\" -recurse | where {$_.extension -eq ".csproj"} | % { dotnet test "`""$_.FullName"`"" -c Release --logger:trx}

## VSTS Tasks

On VSTS use these commands:

- Run tests

	Get-ChildItem "$env:BUILD_REPOSITORY_LOCALPATH\tests\" -recurse | where {$_.extension -eq ".csproj"} | % { dotnet test "`""$_.FullName"`"" -c Release --logger:trx}

- Create packages

	dotnet pack $(build.sourcesdirectory)/*.sln /p:Version=$(GitVersion.NuGetVersionV2) -c Release --output $(build.artifactstagingdirectory)/nuget-packages

- Some feed (like the one hosted on VSTS) doesn't support to publish .nupkg and .symbols.nupkg, it will conflict the second push.
  A solution is to set the variable "NuGet.UseLegacyFindFiles=true" and then use a pattern like  `$(Build.ArtifactStagingDirectory)/*.nupkg;-:$(Build.ArtifactStagingDirectory)/*.symbols.nupkg`
  See https://stackoverflow.com/a/45209008/209727 .

## Code analyzers (code linter)

I have choosen to use Microsoft.CodeAnalysis.FxCopAnalyzers + StyleCop.Analyzers. 
To enable it just add it as a nuget dependency, but remeber to set `<PrivateAssets>All</PrivateAssets>` to not include it in the dependencies.
See also
- https://codehollow.com/2016/08/use-code-analyzers-csharp-improve-code-quality/
- https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/Configuration.md

To disable rules see main.ruleset (for both stylecop and fxcop), to configure stylecop rules see stylecop.json.

For each project you should add these configuration inside .csproj:

	<PropertyGroup>
    <CodeAnalysisRuleSet>..\main.ruleset</CodeAnalysisRuleSet>
	</PropertyGroup>
  <ItemGroup>
    <AdditionalFiles Include="..\stylecop.json" Link="stylecop.json" />
  </ItemGroup>

## Add a nuget package

	cd YOUR_PROJECT
	dotnet add package PACKAGENAME

## Test watch mode

Add the following tools inside the .csproj of the project where you want to run tests

  <ItemGroup>
    <DotNetCliToolReference Include="Microsoft.DotNet.Watcher.Tools" Version="2.0.0" />
  </ItemGroup>

Exec

	cd YOUR_TEST_PROJECT
	dotnet restore

Execute tests in watch mode

	cd YOUR_TEST_PROJECT
	dotnet watch test

Execute a console application (old .exe projects)

	dotnet yourproject.dll

## Visual Studio Code

If using Visual Studio Code the `C#` extension is raccomanded and after packages restore a restart of the IDE is required.

You can use the following tasks.json to correctly build the solution:

	{
			"version": "2.0.0",
			"tasks": [
					{
							"label": "build",
							"command": "dotnet",
							"type": "process",
							"group": {
									"kind": "build",
									"isDefault": true
							},
							"args": [
									"build",
									"${workspaceFolder}",
									"--no-incremental",
									"/property:GenerateFullPaths=true"
							],
							"problemMatcher": "$msCompile"
					}
			]
	}