.NET 6 new features using ASP.NET Core 6 and Visual Studio 2022
Published: Tuesday 31 August 2021
.NET 6 development is close to completion, and we will have a look at four new features which you can use in an ASP.NET Core 6 application.
It is due to be released in November 2021, alongside C# 10 and Visual Studio 2022.
C# coding challenges
As .NET 6 is still in preview, some features are still in development. However, the completed features can be used by downloading Visual Studio 2022 preview.
We will have a look at some of the completed features in this article.
Feature #1: Console template
The console template is one of the biggest changes in .NET 6.
Traditionally, a console application would have a namespace, class name and a Main
method. The Main
method would execute when the console application is started.
With an ASP.NET Core application, the Main
method is where web application instance would be built, configured and ran.
// Program.cs
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Hosting;
namespace RoundTheCode.DotNet6
{
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>();
});
}
}
However, with .NET 6, you can do away with the console application's namespace, class name and Main
method. As a result, the file just has the contents on the Main method included.
// Program.cs
using RoundTheCode.DotNet6;
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
}).Build().Run();
Feature #2: Merger of Program and the Startup class
In ASP.NET Core 5, there would be two classes to configure the application.
We looked at the Program
class above which builds and runs the application. In addition, there is a Startup
class, which is where we make our configuration changes, such as adding a database connection, or using dependency injection.
// Startup.cs
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
namespace RoundTheCode.DotNet6
{
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)
{
services.AddControllers();
services.AddSingleton<ITeamService, TeamService>();
services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1", new() { Title = "RoundTheCode.DotNet6", Version = "v1" });
});
}
// 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();
app.UseSwagger();
app.UseSwaggerUI(c => {
c.SwaggerEndpoint("/swagger/v1/swagger.json", "RoundTheCode.DotNet6 v1");
c.RoutePrefix = string.Empty;
});
}
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.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
});
}
}
}
However, with ASP.NET Core 6, these two classes have now been merged into the Program.cs
file.
And, with the elimination of namespace, class and Main method, it means we simply have one Program.cs file that creates the WebApplicationBuilder
instance, and configures the settings for the application.
// Program.cs
using RoundTheCode.DotNet6;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers();
builder.Services.AddSingleton<ITeamService, TeamService>();
builder.Services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1", new() { Title = "RoundTheCode.DotNet6", Version = "v1" });
});
var app = builder.Build();
if (app.Environment.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseSwagger();
app.UseSwaggerUI(c => {
c.SwaggerEndpoint("/swagger/v1/swagger.json", "RoundTheCode.DotNet6 v1");
c.RoutePrefix = string.Empty;
});
}
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.UseRouting();
app.UseAuthorization();
app.MapControllers();
app.Run();
Feature #3: Minimal APIs
ASP.NET Core 6 introduces Minimal APIs.
With ASP.NET Core 5, it was possible to use the mapping methods inside the UseEndpoints
method. However, the only parameter that was able to be passed through that was the HttpContext
instance.
As a result, the MVC route would have been a better solution as dependencies can be passed in as parameters.
But with ASP.NET Core 6, there are new mapping methods as part of the WebApplication
instance. And, they allow you to pass in dependencies as methods.
For example, a WebApplication
instance is created when the application calls builder.Build()
.
var app = builder.Build();
Within the WebApplication
instance, there are methods that represent each of the CRUD verbs.
MapGet
MapPost
MapPut
MapDelete
With that, we can go ahead and set up a new API endpoint by passing in the route, any parameters that we need, and then returning a response.
app.MapGet("team/{id}", (ITeamService teamService, int id) => teamService.Read(id));
If we were to run our API at this point, it would run fine. However, if we have Swagger configured for our Web API, it will not appear in the Swagger documentation.
We need to call the AddEndpointsApiExplorer
endpoint when building up our web application for it to appear in Swagger.
// Program.cs
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
builder.Services.AddControllers();
builder.Services.AddEndpointsApiExplorer(); // Need to add this in for it to appear in Swagger.
builder.Services.AddSingleton<ITeamService, TeamService>();
...
var app = builder.Build();
// Configure the HTTP request pipeline.
if (builder.Environment.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseSwagger();
app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "RoundTheCode.DotNet6 v1"));
}
app.MapGet("team/{id}", (ITeamService teamService, int id) => teamService.Read(id));
...
app.Run();
By running our application now, our endpoint will now appear in our Swagger documentation.
Feature #4: DateOnly and TimeOnly structs
A feature that is long overdue in .NET 6 is the ability to set an object that is just a date, or just a time.
Traditionally, the DateTime
struct would need to be used. That would mean that the time would exist, even if we were just using the date. And vice-versa with the time.
With the DateOnly
struct, we can add a new instance by specifying the year, month and day. And it has similar methods to the DateTime
struct.
Here is an example of how to add seven days to a DateOnly
struct.
var dayNow = new DateOnly(2021, 08, 30);
var dayWeekTime = dayNow.AddDays(7);
return dayWeekTime.ToShortDateString();
It's a similar story with TimeOnly
struct. Creating a new TimeOnly
struct allows for us to pass in parameters, such as hours, minutes and seconds.
From there, we can do things, like adding a certain number of hours. If the number of hours goes beyond 24, it will revert back to 0.
Here is an example of adding 8 hours to 18:00 in a TimeOnly
struct. The output would be 02:00.
var timeNow = new TimeOnly(18, 0, 0);
var timeNowEightHours = timeNow.AddHours(8);
return timeNowEightHours.ToString();
See these .NET 6 features in action
Checkout our video where we demonstrate these new features using an ASP.NET Core 6 Web API.
In addition, download our code example where you can download the code and try out these examples right now.
Check out more .NET 6 resources
These new features are available in preview 7 of .NET 6 and they are available to try out now.
This is the last release before the release candidate period. This means that the team will now be polishing .NET 6 up ready for it's release in November.
And like with C# 10, it has a high degree of simplifying stuff, making it a home for cleaner and tidier code.