Comparing our upgraded .NET Core 3 projects to new .NET Core 3 projects

Posted by

While we successfully upgraded our projects to ASP.NET core 3 last week, we noted there were a few differences compared to a brand new .NET core project. We are going to complete our .NET Core 3.0 upgrade, using a new a .NET Core project as comparison. This last step will ensure our projects don’t carry .NET 2.2 technical debt forward, and help us to understand some of the new features.

Upgrading ConfigureServices() in startup.cs

Below we have two ASP.NET Core 3.0 Web API projects. The project on the left was upgraded from ASP.NET Core 2.2, and the project on the right was created from scratch with Visual Studio as a 3.0 project. We have highlighted the 3 differences below in red, blue, and green.

The first change, in startup.cs, is in “ConfigureServices”, where the services.AddMvc() function was replaced by “services.AddControllers()”. Here is the code we have after our upgrade. It also has the option to disable endpoint routing that we fix in the green section below.

This is a very straight forward fix. We just replace with the “services.AddControllers” function. While the “AddMvc” function configured everything that MVC needed, in a Web API, things like views are not required and can be stripped back. “AddControllers()” is specifically for Web API’s, in that only what is needed for a Web API is initialized when it’s called.

In a MVC website, this changes slightly to “services.AddControllersWithViews()”, including all of the extra stuff a website needs, but an API doesn’t.

Upgrading Configure() in startup.cs

The next change is the addition of UseRouting() and UseEndpoints(). There is a slighting confusing, but important order of commands in here. If you call UseStaticFiles(), you should place this before UseRouting(), and if you use UseCors(), it should before UseRouting(). UseAuthenication(), should be after UseCors(), but before UseEndpoints(). This isn’t confusing at all.

We found it pretty difficult to find a simple explanation for what UseRouting() is for. Here goes: essentially the .NET core 3.0 routing is new middleware to give you more control over incoming requests. In our website, in the Configure function, our upgraded .NET Core 2.2 to 3.0 web project uses UseMvc() to define the default routes.

In a new .NET Core 3.0 project, this now uses the app.UseEndpoints() function to define the default routes, with a new MapControllerRoute function.

Upgrading Main() in program.cs

There have been some subtle changes to the Main function in program.cs too. Here is the current .NET Core 2.2 code, with the managed identity to load variables from the key vault:

    public static void Main(string[] args)
    {
        CreateWebHostBuilder(args).Build().Run();
    }

    public static IWebHostBuilder CreateWebHostBuilder(string[] args)
    {
        return WebHost.CreateDefaultBuilder(args)
            .ConfigureAppConfiguration((context, config) =>
            {
                //Load the appsettings.json configuration file
                IConfigurationRoot buildConfig = config.Build();

                //Load a connection to our Azure key vault instance
                AzureServiceTokenProvider azureServiceTokenProvider = new AzureServiceTokenProvider();
                KeyVaultClient keyVaultClient = new KeyVaultClient(new KeyVaultClient.AuthenticationCallback(azureServiceTokenProvider.KeyVaultTokenCallback));
                config.AddAzureKeyVault(buildConfig["AppSettings:KeyVaultURL"], keyVaultClient, new DefaultKeyVaultSecretManager());
            })
            .UseStartup<Startup>();
    }

With the .NET Core 3.0 upgrade, it starts to look like this. The new methods are very similar, but we are using the IHostBuilder interface instead of IWebHostBuilder .

        public static void Main(string[] args)
        {
            CreateHostBuilder(args).Build().Run();
        }

        public static IHostBuilder CreateHostBuilder(string[] args)
        {
            return Host.CreateDefaultBuilder(args)
                .ConfigureAppConfiguration((context, config) =>
                {
                    //Load the appsettings.json configuration file
                    IConfigurationRoot buildConfig = config.Build();

                    //Load a connection to our Azure key vault instance
                    AzureServiceTokenProvider azureServiceTokenProvider = new AzureServiceTokenProvider();
                    KeyVaultClient keyVaultClient = new KeyVaultClient(new KeyVaultClient.AuthenticationCallback(azureServiceTokenProvider.KeyVaultTokenCallback));
                    config.AddAzureKeyVault(buildConfig["AppSettings:KeyVaultURL"], keyVaultClient, new DefaultKeyVaultSecretManager());
                })
                .ConfigureWebHostDefaults(webBuilder =>
                {
                    webBuilder.UseStartup<Startup>();
                });
        }

Wrap up

Relatively subtle changes, but important, especially with .NET Core 3.1 LTS coming in November, and as we mentioned earlier, this helps to reduce the last of .NET 2.2 technical debt.

References

2 comments

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s