.Net Core for .Net Frameworkers
Tags: dotnet, csharp, tutorial
Published: 2020-05-13 15:02:54

---
title: .Net Core for .Net Frameworkers
published: true
description: What a .Net Framework developer should know before starting with .Net Core
tags: dotnet,csharp,tutorial
cover_image: https://dev-to-uploads.s3.amazonaws.com/i/w56q7j5yznzax7c8c6jm.png
---

The web is full of guides on how to switch from .Net Framework to .Net Core. As someone who had the chance to migrate a web app from Framework to Core, I realized that each article gives only a few parts of the whole picture. In order to switch between these frameworks, I had to understand the fundamentals changes (and the reasons behind these changes) in Microsoft's .Net projects.

In this article I give my recommendation on how one should approach this large task, and what I believe is important to know prior to starting a migration of a .Net Framework project. Each subject has a reference to a thorough documentation/article worth reading.

# From Framework to Core

It is important to understand that .Net Framework and [.Net Core](https://docs.microsoft.com/en-us/dotnet/core/about) aren’t two separate  frameworks with their own life-cycles and goals, but rather one is an extension of the other. .Net Core is meant to extend its predecessor framework and offer solutions to the same problems (desktop, web, mobile, cloud-native and more).

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/xn90qiss0puebaaqafah.png)

## Ok, then why Core ?

Apart from restructure and refactor of most .Net libraries, .Net Core brings a couple of key changes:

* It’s fully open-source. Microsoft’s teams and contributors publish all code.
  {% github dotnet/core no-readme %}
* It’s cross-platform. It supports Linux, MacOS and Windows (obviously) runtimes for many application types (even [desktop](https://devblogs.microsoft.com/dotnet/net-core-3-for-windows-desktop/) apps 💪).

As mentioned above, even apps intended to find themselves running on windows should choose .Net Core simply because it’s the latest .Net offers and supports.

### Why I migrated to .Net Core

There are many reasons to make such a large change other than the will to get the latest .Net (new is always better? 🤔). In my case, I was working on a large web app that didn't scale that well. We had to throw in more and more servers to keep up with user traffic which made us more maintainers and less developers. In order to set us free of VMs babysitting, we decided to bring in Docker containers to the table. At the time, we didn't want to go for [Windows Containers](https://docs.microsoft.com/en-us/virtualization/windowscontainers/about/) because it was still fresh and unknown territory, so we were left with Linux containers. So, this is how .Net Core came in.

---

# .Net Framework/Standard/Core

In order to allow compatibility across multiple runtime environments, libraries had to find a common low level API that works on both Framework and Core. Here comes in .Net Standard, a common base build target that exposes interfaces that are eventually implemented for each OS and run environment.
Check out the official docs [here](https://docs.microsoft.com/en-us/archive/msdn-magazine/2017/september/net-standard-demystifying-net-core-and-net-standard) and [here](https://docs.microsoft.com/en-us/dotnet/standard/net-standard).

# C# is same ol’ C# #

Syntax, features and patterns are all the same. It doesn’t matter whichever .Net target you choose, C# stays the same on every level. Since C# has its own people working on it and making sure the language itself stays compatible with all .Net [BCL](https://docs.microsoft.com/en-us/dotnet/standard/framework-libraries) and targets. This is done at the [Roslyn](https://github.com/dotnet/roslyn/wiki/Roslyn%20Overview) compiler and by referencing common types present in all targets as a standard library (more on the relationship between language and frameworks [here](https://docs.microsoft.com/en-us/dotnet/csharp/whats-new/relationships-between-language-and-library)).

{% github dotnet/roslyn no-readme %}

One thing to keep in mind is that as of C# 8, the language specifically targets .Net Core and a few features are only partially supported by .Net Framework (as mentioned [here](https://docs.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-version-history#c-version-80)).

I Recommend checking out this awesome stack overflow answer:

{% stackoverflow 57020770 %}

# OK, then it's easy

If C# is the same, and all we have to do is target .Net Standard, then where is the hassle?
Well, the real pickle is at the platform level. Each platform (such as Asp.Net, Web Api, WPF, etc) had its infrastructure refurbished and open-sourced. As a result, developers had to make adjustments to use the new .Net Core versions of their platform.

## Some common noticeable changes

* Broader build output types are now available. EXE is no longer the obvious output to a console application, as it depends on the target OS. DLLs are still here since they are OS-agnostic (to a certain degree).

    Compiling to a linux target is as easy as:

    `dotnet publish -r linux-x64`

    And right away you can see a new build:

    ```powershell
  $ ls LinuxConsole\bin\Debug\netcoreapp3.1\linux-x64\
  createdump                                       System.IO.Compression.Native.so
  libclrjit.so                                     System.IO.Compression.ZipFile.dll*
  libcoreclr.so                                    System.IO.dll*
  libcoreclrtraceptprovider.so                     System.IO.FileSystem.AccessControl.dll*
  libdbgshim.so                                    System.IO.FileSystem.dll*
  libhostfxr.so                                    System.IO.FileSystem.DriveInfo.dll*
  libhostpolicy.so                                 System.IO.FileSystem.Primitives.dll*
  libmscordaccore.so                               System.IO.FileSystem.Watcher.dll*
  libmscordbi.so                                   System.IO.IsolatedStorage.dll*
  LinuxConsole                                     System.IO.MemoryMappedFiles.dll*
  LinuxConsole.deps.json                           System.IO.Pipes.AccessControl.dll*
  LinuxConsole.dll*                                System.IO.Pipes.dll*
  LinuxConsole.pdb                                 System.IO.UnmanagedMemoryStream.dll*
  LinuxConsole.runtimeconfig.dev.json              System.Linq.dll*
  LinuxConsole.runtimeconfig.json                  System.Linq.Expressions.dll*
  Microsoft.CSharp.dll*                            System.Linq.Parallel.dll*
  Microsoft.VisualBasic.Core.dll*                  System.Linq.Queryable.dll*
  Microsoft.VisualBasic.dll*                       System.Memory.dll*
  Microsoft.Win32.Primitives.dll*                  System.Native.a
  Microsoft.Win32.Registry.dll*                    System.Native.so
  mscorlib.dll*                                    System.Net.dll*
  netstandard.dll*                                 System.Net.Http.dll*
  publish/                                         System.Net.Http.Native.a
  SOS_README.md                                    System.Net.Http.Native.so
  System.AppContext.dll*                           System.Net.HttpListener.dll*
                                  ...
    ```

* Dependencies and their versions should be determined by support to the .Net Standard package version. Nuget packages compatibility used to be determined by simply the .Net Framework version of your project, but now we need to make sure our .Net Core version supports the .Net Standard library version. For example, take a look at the very popular [Newtonsoft](https://www.nuget.org/packages/Newtonsoft.Json/) package. Head over to the dependencies section and you can see which .Net Framework/Standard versions are supported:
  
    ![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/evu2v7cq5og2folgus2g.png)

    Now check out the .Net Standard supported versions of all .Net Core releases [here](https://docs.microsoft.com/en-us/dotnet/standard/net-standard#net-implementation-support) to see which .Net Standard version each .Net core version supports.
    *you can find out more about base .Net Core Nuget packages [here](https://docs.microsoft.com/en-us/dotnet/core/packages).*

* .csproj is greatly simplified. Just by creating two class library projects, one in .Net Core and one in .Net Framework, you can see the difference:
  
    *.Net Framework .csproj*

    ```xml
  <?xml version="1.0" encoding="utf-8"?>
  <Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props"
    Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
  <PropertyGroup>
    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
    <ProjectGuid>abd460f8-54fb-4f34-abf0-3cc184253329</ProjectGuid>
    <OutputType>Library</OutputType>
    ...
  </PropertyGroup>
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
    ...
  </PropertyGroup>
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
    ...
  </PropertyGroup>
  <ItemGroup>
    <Reference Include="System"/>
    <Reference Include="System.Core"/>
    <Reference Include="System.Xml.Linq"/>
    <Reference Include="System.Data.DataSetExtensions"/>
    <Reference Include="Microsoft.CSharp"/>
    <Reference Include="System.Data"/>
    <Reference Include="System.Net.Http"/>
    <Reference Include="System.Xml"/>
  </ItemGroup>
  <ItemGroup>
    <Compile Include="Class1.cs" />
    <Compile Include="Properties\AssemblyInfo.cs" />
  </ItemGroup>
  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
  </Project>
    ```

    *.Net Core .csproj*

    ```xml
  <Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <TargetFramework>netstandard2.0</TargetFramework>
  </PropertyGroup>
  </Project>
    ```

    Notice the `<Compile Include="...">`. .Net Core's csproj no longer requires you to specify every single file related to the project, if it’s in the folder it’s in the project (no more build fails after you forget to commit your new shinny class file 🎉).

*Microsoft published a basic guideline article on [porting .Net Framework projects to .Net Core](https://docs.microsoft.com/en-us/dotnet/core/porting/), you might want to take a look.*

## Platform changes

Let's assume we have an Asp.Net Web Api project. What would it take to migrate it to .Net Core?

Well, first of all, .Net Core does not have a new Web Api support. All .Net web applications development was mostly unified under the new Asp.Net Core project. That means you need to migrate to an almost new platform. But fear not, Asp.Net Core left most of the project structure the same.

{% github dotnet/aspnetcore no-readme %}

The main difference is the new classes and libraries used to create the application, such as controllers routing attributes, middlewares and more.

### Controllers

See how this **.Net Framework Web Api** controller:

```csharp
[RoutePrefix("forecast")] // <-
public class WeatherForecastController : ApiController
{
    private static readonly string[] Summaries = {
        "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm"
    };

    [HttpGet] // <-
    [Route("route")] // <-
    public IEnumerable<WeatherForecast> Get()
    {
        var rng = new Random();
        return Enumerable.Range(1, 5).Select(index => new WeatherForecast
            {
                Date = DateTime.Now.AddDays(index),
                TemperatureC = rng.Next(-20, 55),
                Summary = Summaries[rng.Next(Summaries.Length)]
            })
            .ToArray();
    }
}
```

Turns to this **.Net Core** controller:

```csharp
[ApiController] // <-
[Route("forecast")] // <-
public class WeatherForecastController : Controller
{
    private static readonly string[] Summaries = {
        "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm"
    };

    [HttpGet("route")] // <-
    public IEnumerable<WeatherForecast> Get()
    {
        var rng = new Random();
        return Enumerable.Range(1, 5).Select(index => new WeatherForecast
        {
            Date = DateTime.Now.AddDays(index),
            TemperatureC = rng.Next(-20, 55),
            Summary = Summaries[rng.Next(Summaries.Length)]
        })
        .ToArray();
    }
}
```

*Changes are highlighted with (<-)*

### Middleware & infrastructure code

Middleware pipelining stays pretty much the same in .Net Core (as does the startup file we all ❤️ so much), the changes you might find yourself doing are switching 'native' .Net libraries to their newer alternatives. Take this example:

#### A tale of Windows & Linux

Like many .Net Framework (on top of **Windows**) developers, you might have set up Windows Authentication which Worked perfectly with your `User is WindowsPrincipal` and your `Request.IsAuthenticated` with IIS. And be assured that a similar code will give you the same with `services.AddAuthentication(NegotiateDefaults.AuthenticationScheme)` on .Net Core and [Windows](https://docs.microsoft.com/en-us/aspnet/core/security/authentication/windowsauth?view=aspnetcore-3.1&tabs=visual-studio). However, if you intend to switch to Linux servers, more modifications are required, as Linux needs extra work in order to [integrate with Active Directory](https://docs.microsoft.com/en-us/aspnet/core/security/authentication/windowsauth?view=aspnetcore-3.1&tabs=visual-studio#linux-and-macos-environment-configuration).

Check out the [official Microsoft](https://docs.microsoft.com/en-us/aspnet/core/migration/webapi?view=aspnetcore-3.1) guide and this [Stackify](https://stackify.com/asp-net-core-web-api-guide/) guide.

### Kestrel

Another important feature you can notice in these guides is [Kestrel](https://docs.microsoft.com/en-us/aspnet/core/fundamentals/servers/kestrel?view=aspnetcore-3.1). Remember how you had to create a self-host console app project for your development environment? Well no more, Asp.Net Core ships with its own server implementations (for various runtime targets), the most popular of which is Kestrel which supports both Linux and Windows runtimes. Take a look at [this overview](https://docs.microsoft.com/en-us/aspnet/core/host-and-deploy/?view=aspnetcore-3.1) of hosting with .Net Core.

---

# The Roadmap

I really encourage Checking up [.Net Core's roadmap](https://github.com/dotnet/core/blob/master/roadmap.md) from time to time. It gives a clear map of where the .Net world is headed to.