Skip to main content

My .NET crash course

· 4 min read
Guster
Full-stack Staff Engineer

image

ASP.NET is a popular MVC framework for building web applications with C#. It's similar to Spring Boot if you come from a Java background and other web frameworks like Ruby on Rails and Laravel. Personally, I think it's more comparable to Spring Boot. We'll discuss this more later.

Follow the official documentation for installation.

File Structure

When I start learning a new framework, I usually relate its features to ones I'm familiar with. For example:

  • ApiController - Define a REST Controller, like @RestController in Spring Boot
  • DbContext - Think of it like a JpaRepository factory in Spring Boot, or ActiveRecord in ROR
  • Program.cs - The main class where the app initialisation is done, similar to SpringBootApplication
  • .csproj - Where we define the configs, dependencies, like the maven pom.xml or build.gradle in Java
  • /Migrations - A folder containing the db migration files, similar to the migrations in ROR.

C#

As a newcomer to C#, I found it surprisingly straightforward to learn. This is partly due to its similarities with other languages I'm familiar with, such as Java, JS, Kotlin, Ruby, and Dart. Here are a few examples:

  • The public, protected, private keywords
  • The var and const variable assignment keywords
  • The getter and setter shorthands get; set; in Kotlin
  • The attribute [...], which is equivalent to the annotation @ in Java
  • The async and await keywords

Development with VSCode

To run .NET directly from VSCode, you need to install these 2 extensions first.

Once these extensions are installed, please F5 to launch and debug.

CLI Commands

One thing I like about Ruby on Rails is its powerful CLI. It allows you to scaffold, generate classes, run migrations, and more. Fortunately, .NET also has its own CLI, and it’s actually pretty good.

Here are some commonly used commands in .NET:

  • dotnet new - Create a new .NET project

    dotnet new webapi --use-controllers -o dotnet-todo-api
  • dotnet add package - Add a package dependency

    dotnet add package Microsoft.EntityFrameworkCore.InMemory

    # If you are just starting, install these
    dotnet add package Microsoft.VisualStudio.Web.CodeGeneration.Design 1 ↵ guster@Gusters-MacBook-Air
    dotnet add package Microsoft.EntityFrameworkCore.Design
    dotnet add package Microsoft.EntityFrameworkCore.SqlServer
    dotnet add package Microsoft.EntityFrameworkCore.Tools
    dotnet tool uninstall -g dotnet-aspnet-codegenerator
    dotnet tool install -g dotnet-aspnet-codegenerator
    dotnet tool update -g dotnet-aspnet-codegenerator

    # for postgresql
    Aspire.Npgsql.EntityFrameworkCore.PostgreSQL
  • dotnet tool - Install a CLI extension

    # install the Entity Framework CLI tool for database migration
    dotnet tool install --global dotnet-ef
  • dotnet ef migrations - Generate a migration file

    dotnet ef migrations add InitialCreate
  • dotnet ef database update - Apply the migrations to database

  • dotnet aspnet-codegenerator - Scaffolding such as controller

    dotnet aspnet-codegenerator controller -name TodoItemsController -async -api -m TodoItem -dc TodoContext -outDir Controllers
  • dotnet run watch - Run the project with hot reloading

How-to List

  • How to enable CORS?

    If you are developing SPA with framework like React or Angular locally, you might hit CORS error when calling API to your local API server. To enable CORS, this is how you do it.

    How to

    In Program.cs, add the following codes.

    builder.Services.AddCors(options =>
    {
    options.AddDefaultPolicy(builder =>
    {
    builder.AllowAnyOrigin()
    .AllowAnyHeader()
    .AllowAnyMethod();
    });
    });

    var app = builder.Build();
    // ...
    app.UseCors();
  • Add a singleton

    In Program.cs, add the following changes, assuming you have created a service AuthService, then inject it in your class’s constructor as usual.

    builder.Services.AddSingleton<AuthService>()
  • Authorisation with JWT

    Setup

    To begin with, add the following service in your Program.cs

    builder.Services
    .AddAuthorization()
    .AddAuthentication(options =>
    {
    options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
    options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
    })
    .AddJwtBearer(options =>
    {
    options.TokenValidationParameters = new TokenValidationParameters
    {
    ValidateAudience = false,
    ValidateActor = false,
    ValidateIssuer = true,
    ValidateLifetime = true,
    ValidateIssuerSigningKey = true,
    LogValidationExceptions = true,
    ValidIssuer = "valid_issuer",
    IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("your_secret_key"))
    };
    });

    ...

    var app = builder.Build();

    // IMPORTANT: the order matters!
    app.UseAuthentication();
    app.UseAuthorization();

    Helper class to generate a JWT token (AuthService)

    public class AuthService
    {
    public string GenerateJwtToken(User user)
    {
    var tokenHandler = new JwtSecurityTokenHandler();
    var key = Encoding.ASCII.GetBytes("your_secret_key");
    var tokenDescriptor = new SecurityTokenDescriptor
    {
    Subject = new ClaimsIdentity(
    [
    new Claim("id", user.Id.ToString())
    ]),
    Issuer = "valid_issuer",
    Expires = DateTime.UtcNow.AddHours(1),
    SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature)
    };
    var token = tokenHandler.CreateToken(tokenDescriptor);
    return tokenHandler.WriteToken(token);
    }
    }

    Protect your API endpoints

    In your Controller, add this annotation [Authorize] to any endpoint method that required authorisation. Default is anonymous allowed.