If you are a C# developer, chances are you have heard about this new .NET Core thing and the new version of the ASP.NET framework. You can continue to work with ASP.NET Web API or any other framework from the old ASP.NET you've known for years. But, ASP.NET Core is here to stay.
In case you missed it, "ASP.NET Core is a cross-platform, high-performance, open-source framework for building modern, cloud-based, Internet-connected applications". "ASP.NET Core is a redesign of ASP.NET 4.x, with architectural changes that result in a leaner, more modular framework".
ASP.NET Core has brought a lot of new features. For example, cross-platform development and deployment, built-in dependency injection, middlewares, health checks, out-of-the-box logging providers, hosted services, API versioning and much more.
Don't worry if you haven't started to work with ASP.NET Core yet. This is a new framework with lots of new features, but it has brought many other features from the previous version. So, you will feel like home.
TL;DR
- You can create projects from the command line.
- NuGet packages are listed on the
csproj
files.csproj
files don't list.cs
files anymore.- There's no
Web.config
, you have a json file instead.- There's no
Global.asax
, you haveStartup.cs
instead.- You have a brand new dependency injection (DI) container.
Every journey begins with the first step
If you are adventurous, download and install the ASP.NET Core developer (SDK) and create a new empty web project from Visual Studio. These are the files that you get from it.
|____appsettings.Development.json
|____appsettings.json
|____Program.cs
|____Properties
| |____launchSettings.json
|____<YourProjectName>.csproj
|____Startup.cs
ASP.NET Core has been created with other operating systems and IDEs in mind. Now you can create a project, compile it, and run the tests from the command line. For example, to create a new empty Web project, you can use $ dotnet new web
Where is the packages.config file?
If you installed a NuGet package into your brand new ASP.NET Core project, one thing you could notice is the missing packages.config
file. If you remember, it is an xml file that holds the packages installed. But, where in the world are those packages referenced now? In the csproj file of your project.
Now, a csproj file looks like this:
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
</ItemGroup>
</Project>
Nuget packages are referenced under ItemGroup
in a PackageReference
node. There you are Newtonsoft.Json! Goodbye, packages.config
!
Wait! What happened to the csproj file?
Csproj files have been simplified. Before, a csproj file listed every single file in the project. All your files with .cs
extension were in it. Now, every .cs
file within the folder structure of the project is part of it.
Before, things started to get complicated as time went by and the number of files increased. Sometimes, merge conflicts were a nightmare. There were files under version control not included in the csproj file. Were they meant to be excluded because they didn't apply anymore? Or somebody tried to solve a merge conflict and forgot to include them? This problem is no more!
Where is the Web.config file?
Another missing file is the Web.config
file. Instead you have a Json file: the appsettings.json
file. You can use strings, integers and booleans in your config file. There is even support for sections and subsections. Before, if you wanted to achieve that, you had to come up with a naming convention for your keys. For example, prepending the section and subsection name in every key name.
Probably, you have used ConfigurationManager
all over the place in your code to read configuration values. Now, you can have a class with properties mapped to a section or subsection of your config file. And you can inject it into your services.
// appsettings.json
{
"MySettings": {
"ASetting": "ASP.NET Core rocks",
"AnotherSetting": true
}
}
public class MySettings
{
public string ASetting { get; set; }
public bool AnotherSetting { get; set; }
}
public class YourService
{
public YourService(IOptions<MySettings> settings)
{
// etc
}
}
You still need to register that configuration into the dependency container! More on that later.
Additionally, you can override keys per environment. You can use the name of your environment in the file name. For example, appsettings.Development.json
or appsettings.QA.json
. You can specify the current environment with an environment variable or in the launchSettings.json
file.
There's even support for sensitive settings that you don't want to version control: secrets.json
file. You can manage this file from the command line too.
Where is the Global.asax?
Yet another missing file: Global.asax
. You used it to perform actions on application or session events. For example, when application started or ended. It was the place to do one-time setups, register filters or define routes.
But now we use the Startup.cs
file instead. It contains the initialization and all the settings needed to run the application. A Startup.cs
file looks like this:
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
public void ConfigureServices(IServiceCollection services)
{
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
}
}
It has two methods: ConfigureServices
and Configure
. The Configure
method replaces the Global.asax
file. It creates the app's request processing pipeline. This is the place to register a filter or a default route for your controllers. And the ConfigureServices
is to configure the services to be injected into the dependency container...Wait, what?
A brand new dependency container
Prior to ASP.NET Core, if you wanted to apply dependency injection, you had to bring a container and roll the discovery of services for your controllers. For example, you had an xml file to map your interfaces to your classes or did some assembly scanning to do it automatically.
Now, a brand new dependency container is included out-of-the-box. You can inject dependencies into your services, filters, middlewares and controllers. It lacks some of the features from your favorite dependency container, but it is meant to suit "90% of the scenarios".
If you are familiar with the vocabulary from another containers, AddTransient
, AddScoped
and AddSingleton
ring a bell. These are the lifetimes of the injected services, ranging from the shortest to the largest.
More specifically, a transient service is created every time a new instance is requested. An scoped service is created once per request. Plus, a singleton service is created only once per the application lifetime.
To register your services, you have to do it inside of the ConfigureServices
method of the Startup
class. Also, you bind your classes to a section or subsection of the config file here.
public void ConfigureServices(IServiceCollection services)
{
services.AddTransient<IMyService, MyService>();
var section = Configuration.GetSection("MySettings")
services.Configure<MySettings>(section);
}
Conclusion
You have only scratched the surface of ASP.Net Core. You have learned about some of the changes AspNet Core has brought. But, if you haven't started with ASP.NET Core, go and try it. You may be surprised by how things are done now.