This article explains how to update an existing ASP.NET 5 project to ASP.NET 6. I am going to use a fully-functional .NET 5 MVC application to show how you can do it step by step.
You can get the same project in this GitHub repository: https://github.com/etrupja/complete-ecommerce-aspnet-mvc-application
To work with .NET 5 and .NET 6 frameworks you need to have Visual Studio 2022 installed. You can get the community edition from here.
Updating Target Framework
After you open the project on Visual Studio 2022, right-click on the project and then Edit Project File, you will see the target framework as below:
Change the Target Framework from net5.0 to net6.0, so it looks like this:
Update package references
After you have updated the target framework, you need to update all the packages in your project to match the target framework. So, in this case, you have to update them from .NET 5.0 to .NET 6.0.
The packages that we have installed are EntityFrameworkCore, Identity, SqlServer, and Tool and they all are set to Version=5.0.6.
To update the packages, you can either change the Version number in this project file, or you can use the Nuget package manager. To use NuGet package manager, Right-Click on the project then select the Manage NuGet Packages option.
In the NuGet packages manager view, select all the packages that you will update (in my case all of them), then click the update button. Clicking this button is going to update all the packages from 5.0.6 to 6.0.7
After the installation, you can go to the project file and you can see that all the packages were updated to the 6.0.7 version (this might be different for you)
Update Hosting Model (Remove Startup.cs)
The new .NET 6 minimal hosting model for ASP.NET Core apps requires only one file and a few lines of code. This new hosting model unifies multiple files into a single one.
The new hosting model unifies Startup.cs and Program.cs into a single Program.cs file.
In the Startup.cs we do have 2 methods, ConfigureServices and Configure method. The Startup.cs file looks like the below:
using eTickets.Data; using eTickets.Data.Cart; using eTickets.Data.Services; using eTickets.Models; using Microsoft.AspNetCore.Authentication.Cookies; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.HttpsPolicy; using Microsoft.AspNetCore.Identity; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; namespace eTickets { public class Startup { public Startup(IConfiguration configuration) { Configuration = configuration; } public IConfiguration Configuration { get; } // This method gets called by the runtime. Use this method to add services to the container. public void ConfigureServices(IServiceCollection services) { //DbContext configuration services.AddDbContext<AppDbContext>(options => options.UseSqlServer(Configuration.GetConnectionString("DefaultConnectionString"))); //Services configuration services.AddScoped<IActorsService, ActorsService>(); services.AddScoped<IProducersService, ProducersService>(); services.AddScoped<ICinemasService, CinemasService>(); services.AddScoped<IMoviesService, MoviesService>(); services.AddScoped<IOrdersService, OrdersService>(); services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>(); services.AddScoped(sc => ShoppingCart.GetShoppingCart(sc)); //Authentication and authorization services.AddIdentity<ApplicationUser, IdentityRole>().AddEntityFrameworkStores<AppDbContext>(); services.AddMemoryCache(); services.AddSession(); services.AddAuthentication(options => { options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme; }); services.AddControllersWithViews(); } // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } else { app.UseExceptionHandler("/Home/Error"); // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts. app.UseHsts(); } app.UseHttpsRedirection(); app.UseStaticFiles(); app.UseRouting(); app.UseSession(); //Authentication & Authorization app.UseAuthentication(); app.UseAuthorization(); app.UseAuthorization(); app.UseEndpoints(endpoints => { endpoints.MapControllerRoute( name: "default", pattern: "{controller=Movies}/{action=Index}/{id?}"); }); //Seed database AppDbInitializer.Seed(app); AppDbInitializer.SeedUsersAndRolesAsync(app).Wait(); } } }
The Program.cs looks like the below:
using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; namespace eTickets { public class Program { public static void Main(string[] args) { CreateHostBuilder(args).Build().Run(); } public static IHostBuilder CreateHostBuilder(string[] args) => Host.CreateDefaultBuilder(args) .ConfigureWebHostDefaults(webBuilder => { webBuilder.UseStartup<Startup>(); }); } }
With the new model, you can use a single file and have two separate sections in the file, the “Container Section”, and the “Pipeline Section”. In the “Container Section” which starts after the WebApplication.CreateBuilder(args)
, we do put all the code that is normally found in the ConfigureServices
method, and in the “Pipeline Section” which starts with builder.Build()
, we put all the code that is typically found in the Configure
method.
The new Program.cs class without any of our additional configuration code would look like this:
var builder = WebApplication.CreateBuilder(args); // Add container related code after this line //Code here var app = builder.Build(); // Add pipeline related code after this line //Code here app.Run(); //Add this line to run the project
Now, let us move all the ConfigureServices code to the new Program.cs file. After moving all the code to the new Program.cs file, this is how the container section will look like:
var builder = WebApplication.CreateBuilder(args); //DbContext configuration builder.Services.AddDbContext<AppDbContext>(options => options.UseSqlServer(builder.Configuration.GetConnectionString("DefaultConnectionString"))); //Services configuration builder.Services.AddScoped<IActorsService, ActorsService>(); builder.Services.AddScoped<IProducersService, ProducersService>(); builder.Services.AddScoped<ICinemasService, CinemasService>(); builder.Services.AddScoped<IMoviesService, MoviesService>(); builder.Services.AddScoped<IOrdersService, OrdersService>(); builder.Services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>(); builder.Services.AddScoped(sc => ShoppingCart.GetShoppingCart(sc)); //Authentication and authorization builder.Services.AddIdentity<ApplicationUser, IdentityRole>().AddEntityFrameworkStores<AppDbContext>(); builder.Services.AddMemoryCache(); builder.Services.AddSession(); builder.Services.AddAuthentication(options => { options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme; }); builder.Services.AddControllersWithViews();
Now, move all the code from Configure method to the pipeline section in the new Program class, after the var app = builder.Build(); After moving all the code this is how the pipeline section will look like:
var app = builder.Build(); if (app.Environment.IsDevelopment()) { app.UseDeveloperExceptionPage(); } else { app.UseExceptionHandler("/Home/Error"); // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts. app.UseHsts(); } app.UseHttpsRedirection(); app.UseStaticFiles(); app.UseRouting(); app.UseSession(); //Authentication & Authorization app.UseAuthentication(); app.UseAuthorization(); app.UseAuthorization(); app.UseEndpoints(endpoints => { endpoints.MapControllerRoute( name: "default", pattern: "{controller=Movies}/{action=Index}/{id?}"); });
Before the app.Run() you can also add the two data seed lines that you see. The final version of the file would look like the below (including the seed lines):
using eTickets.Data; using eTickets.Data.Cart; using eTickets.Data.Services; using eTickets.Models; using Microsoft.AspNetCore.Authentication.Cookies; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Identity; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; var builder = WebApplication.CreateBuilder(args); //DbContext configuration builder.Services.AddDbContext<AppDbContext>(options => options.UseSqlServer(builder.Configuration.GetConnectionString("DefaultConnectionString"))); //Services configuration builder.Services.AddScoped<IActorsService, ActorsService>(); builder.Services.AddScoped<IProducersService, ProducersService>(); builder.Services.AddScoped<ICinemasService, CinemasService>(); builder.Services.AddScoped<IMoviesService, MoviesService>(); builder.Services.AddScoped<IOrdersService, OrdersService>(); builder.Services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>(); builder.Services.AddScoped(sc => ShoppingCart.GetShoppingCart(sc)); //Authentication and authorization builder.Services.AddIdentity<ApplicationUser, IdentityRole>().AddEntityFrameworkStores<AppDbContext>(); builder.Services.AddMemoryCache(); builder.Services.AddSession(); builder.Services.AddAuthentication(options => { options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme; }); builder.Services.AddControllersWithViews(); var app = builder.Build(); if (app.Environment.IsDevelopment()) { app.UseDeveloperExceptionPage(); } else { app.UseExceptionHandler("/Home/Error"); // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts. app.UseHsts(); } app.UseHttpsRedirection(); app.UseStaticFiles(); app.UseRouting(); app.UseSession(); //Authentication & Authorization app.UseAuthentication(); app.UseAuthorization(); app.UseAuthorization(); app.UseEndpoints(endpoints => { endpoints.MapControllerRoute( name: "default", pattern: "{controller=Movies}/{action=Index}/{id?}"); }); //Seed database AppDbInitializer.Seed(app); AppDbInitializer.SeedUsersAndRolesAsync(app).Wait(); app.Run();
Final
Now, that everything is updated, it is time to check if everything works as expected. For that, remove the Startup.cs file because it is redundant. Then, run the project. If everything works as expected you should see the project running.