Category Archives: C#

Remove obsolete nuget package references

To get rid of deprecated nuget packages in your solution follow the procedure below.

In Visual Studio first manage the nuget packages for your project (or solution) by right clicking the project in the solution explorer and choose Manage NuGet Packages…

Then the deprecated packages will show up in the list:

To remove those packages you have to remove them from the project file (or do an uninstall with the nuget package manager). I prefer to do this in the project file. So open the project file and remove the package entry (marked lines in the image below).

Now you have to add the FrameworkReference item to the project file. See the project file below and checkout the marked lines.

Check also this link for a more verbose explanation.

Share

Mollie Payments with C# / ASP.NET MVC Net Core

This post describes how to implement Mollie payments in your ASP.NET MVC Web application.

Begin by setting up an account at my.mollie.com. Ensure that you fully complete the registration process, which includes adding at least one payment method.

Following this, launch Visual Studio (or Visual Studio Code) and create a new MVC web application. The next step is to integrate the Mollie API. Do this by adding the NuGet package ‘Mollie.Api‘. As of the writing of this post, the current version is 3.3.0.

Continue reading
Share

Decorator pattern

The Decorator pattern allows you to dynamically add additional behavior or features to an object at runtime. In the context of a car, let’s create an example with a base Car class, a SportsCar class, and a LuxuryCar class. We’ll use decorators to add extra features to the cars.

First, let’s define the base Car class:

public interface ICar
{
    string GetDescription();
    double GetCost();
}

public class Car : ICar
{
    public string GetDescription()
    {
        return "Basic Car";
    }

    public double GetCost()
    {
        return 20000.0;
    }
}

Next, we’ll create the SportsCar class, which will act as a decorator and add sports car features:

public class SportsCar : ICar
{
    private readonly ICar _car;

    public SportsCar(ICar car)
    {
        _car = car;
    }

    public string GetDescription()
    {
        return _car.GetDescription() + ", Sports Car";
    }

    public double GetCost()
    {
        return _car.GetCost() + 15000.0;
    }
}

Now, let’s create the LuxuryCar class, which will be another decorator to add luxury features:

public class LuxuryCar : ICar
{
    private readonly ICar _car;

    public LuxuryCar(ICar car)
    {
        _car = car;
    }

    public string GetDescription()
    {
        return _car.GetDescription() + ", Luxury Car";
    }

    public double GetCost()
    {
        return _car.GetCost() + 30000.0;
    }
}

Finally, we can use the decorators to create different car configurations:

// Creating a basic car
ICar basicCar = new Car();
Console.WriteLine("Description: " + basicCar.GetDescription());
Console.WriteLine("Cost: $" + basicCar.GetCost());

// Adding sports car features to the basic car
ICar sportsCar = new SportsCar(basicCar);
Console.WriteLine("Description: " + sportsCar.GetDescription());
Console.WriteLine("Cost: $" + sportsCar.GetCost());

// Adding luxury features to the sports car
ICar luxuryCar = new LuxuryCar(sportsCar);
Console.WriteLine("Description: " + luxuryCar.GetDescription());
Console.WriteLine("Cost: $" + luxuryCar.GetCost());

Output:

Description: Basic Car
Cost: $20000
Description: Basic Car, Sports Car
Cost: $35000
Description: Basic Car, Sports Car, Luxury Car
Cost: $65000
Share

Dependency Injection: Singleton, Scoped and Transient

The three lifetime registrations for the out of the box DI functionality:

  • singleton (one and only forever)
  • scoped (one in every request)
  • transient (new everytime).

In the code below three objects are added to the DI container, a singleton, a scoped and a transient item.

When you run this code you can observe that the singleton is always the same date (even on different browser tabs). The scoped object will have the same date during the request, even when retrieved multiple times from the DI container it will have the same date and time. The transient object however will have a different date and time each time it is retrieved from the DI container.

using System;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;

var builder = WebApplication.CreateBuilder();

builder.Services.AddSingleton(x => new SingletonDate());
builder.Services.AddTransient(x => new TransientDate());
builder.Services.AddScoped(x => new ScopedDate());

var app = builder.Build();

app.Use(async (context, next) =>
{
    var single = context.RequestServices.GetService<SingletonDate>();
    var scoped = context.RequestServices.GetService<ScopedDate>();
    var transient = context.RequestServices.GetService<TransientDate>();

    await context.Response.WriteAsync("Open this page in two tabs \n");
    await context.Response.WriteAsync("Keep refreshing and you will see the three different DI behaviors\n");
    await context.Response.WriteAsync("----------------------------------\n");
    await context.Response.WriteAsync($"Singleton : {single.Date.ToString("MM/dd/yyyy hh:mm:ss.fff tt")}\n");
    await context.Response.WriteAsync($"Scoped: {scoped.Date.ToString("MM/dd/yyyy hh:mm:ss.fff tt")}\n");
    await context.Response.WriteAsync($"Transient: {transient.Date.ToString("MM/dd/yyyy hh:mm:ss.fff tt")}\n");
    await next.Invoke();
});

app.Run(async (context) =>
{
    await Task.Delay(3000);//delay for 100 ms

    var single = context.RequestServices.GetService<SingletonDate>();
    var scoped = context.RequestServices.GetService<ScopedDate>();
    var transient = context.RequestServices.GetService<TransientDate>();

    await context.Response.WriteAsync("----------------------------------\n");
    await context.Response.WriteAsync($"Singleton : {single.Date.ToString("MM/dd/yyyy hh:mm:ss.fff tt")}\n");
    await context.Response.WriteAsync($"Scoped: {scoped.Date.ToString("MM/dd/yyyy hh:mm:ss.fff tt")}\n");
    await context.Response.WriteAsync($"Transient: {transient.Date.ToString("MM/dd/yyyy hh:mm:ss.fff tt")}\n");
});

app.Run();

public class SingletonDate
{
    public DateTime Date { get; set; } = DateTime.Now;
}

public class TransientDate
{
    public DateTime Date { get; set; } = DateTime.Now;
}

public class ScopedDate
{
    public DateTime Date { get; set; } = DateTime.Now;
}
Share

Dependency injection: register all classes that implement a specific interface

You can register all classes in a project (or folder) that implement a certain interface. See the code below how to do this.

using System.Linq;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;

var builder = WebApplication.CreateBuilder();

var type = typeof(IBootstrap);
var types = System.AppDomain.CurrentDomain.GetAssemblies()
    .SelectMany(x => x.GetTypes())
    .Where(p => type.IsAssignableFrom(p) && p.IsClass);

foreach (var p in types)
{
    var config = (IBootstrap)System.Activator.CreateInstance(p)!;
    config.Register(builder.Services);
}

var app = builder.Build();

app.Run(context =>
{
    var person = context.RequestServices.GetService<Person>()!;
    var greeting = context.RequestServices.GetService<Greeting>()!;

    return context.Response.WriteAsync($"{greeting.Message} {person.Name}");
});

app.Run();

public interface IBootstrap
{
    void Register(IServiceCollection services);
}

public class Registration1 : IBootstrap
{
    public void Register(IServiceCollection services)
    {
        services.AddTransient(x => new Person { Name = "Mahmoud" });
    }
}

public class Registration2 : IBootstrap
{
    public void Register(IServiceCollection services)
    {
        services.AddTransient(x => new Greeting { Message = "Good Morning" });
    }
}

public class Person
{
    public string Name { get; set; } = string.Empty;
}

public class Greeting
{
    public string Message { get; set; } = string.Empty;
}
Share

JWT Tokens

Below the basic operations to create and validate JWT tokens

using Microsoft.IdentityModel.Tokens;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Security.Cryptography;
using System.Text;

public class JwtGenerator
{
    public static string GenerateSecureKey()
    {
        using var randomNumberGenerator = RandomNumberGenerator.Create();
        var key = new byte[32]; // 256 bits
        randomNumberGenerator.GetBytes(key);
        return Convert.ToBase64String(key);
    }

    public static string GenerateToken(string secret)
    {
        JwtSecurityTokenHandler tokenHandler = new();
        byte[] key = Encoding.ASCII.GetBytes(secret);

        SecurityTokenDescriptor tokenDescriptor = new()
        {
            Subject = new ClaimsIdentity(new Claim[]
            {
                // Add any claims you need here
                new Claim(ClaimTypes.Name, "username"),
            }),
            Expires = DateTime.UtcNow.AddMinutes(60),
            SigningCredentials = 
                new SigningCredentials(
                        new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature)
        };

        SecurityToken token = tokenHandler.CreateToken(tokenDescriptor);
        return tokenHandler.WriteToken(token);
    }

    public static ClaimsPrincipal DecodeAndValidateToken(string token, string key)
    {
        var tokenValidationParameters = new TokenValidationParameters
        {
            ValidateIssuerSigningKey = true,
            IssuerSigningKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes(key)),
            ValidateIssuer = false,
            ValidateAudience = false,
            ClockSkew = TimeSpan.Zero
        };

        var tokenHandler = new JwtSecurityTokenHandler();

        try
        {
            var claimsPrincipal = tokenHandler.ValidateToken(token, tokenValidationParameters, out var validatedToken);
            return claimsPrincipal;
        }
        catch (SecurityTokenException)
        {
            Console.WriteLine("Invalid token.");
            return null;
        }
        catch (Exception ex)
        {
            Console.WriteLine($"An error occurred: {ex.Message}");
            return null;
        }
    }

    public static void Main()
    {
        string key = GenerateSecureKey();
        Console.WriteLine(key);

        Console.WriteLine();

        string token = GenerateToken(key);
        Console.WriteLine(token);

        var claimsPrincipal = DecodeAndValidateToken(token, key);
        foreach (var claim in claimsPrincipal.Claims)
        {
            Console.WriteLine($"Claim Type: {claim.Type}, Claim Value: {claim.Value}");
        }
    }
}

Share

Add StyleCop to your Visual Studio build

Add a file called Directory.Build.Props to your solution with the contents below.

<Project>
	<PropertyGroup>
		<TargetFramework>net7.0</TargetFramework>
	</PropertyGroup>

	<ItemGroup>
		<PackageReference Include="StyleCop.Analyzers" version="1.2.0-beta.435">
			<PrivateAssets>all</PrivateAssets>
			<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
		</PackageReference>
	</ItemGroup>
</Project>

Also add a .editorconfig to your solution to configure your code styling. The StyleCop analyzer and the .editorconfig file play together to configure your build process.

Share

Validating objects at creation time

If we have more complex validation logic, we could introduce a factory method and a Result object to handle the validations better:

public record Result<T>
{
    public bool IsSuccess { get; private init; }
    public T? Value { get; private init; }
    public string? ErrorMessage { get; private init; }

    private Result(){}

    public static Result<T> Success(T value) => new() 
    {
       IsSuccess = true, Value = value
    };
    public static Result<T> Failure(string errorMessage) => new()
    {
        IsSuccess = false, ErrorMessage = errorMessage
    };
}

Here we declare the generic Result record, so now let’s see how to create the factory method for the Money value object:

public record Money
{
    private static readonly IReadOnlyCollection<string> SupportedCurrencies = new[]{"USD", "EUR"};

    public decimal Amount { get; }
    public string Currency { get; }
    
    private Money(decimal amount, string currency)
    {
        Amount = amount;
        Currency = currency;
    }

    public static Result<Money> Create(decimal amount, string currency)
    {
        if(string.IsNullOrWhiteSpace(currency))
            return Result<Money>.Failure($"{nameof(currency)} cannot be null or whitespace.");

        if(!SupportedCurrencies.Contains(currency.ToUpperInvariant()))
            return Result<Money>.Failure($"'{currency}' is not supported.");
        
        return Result<Money>.Success(new(amount, currency));
    }
}

Instead of throwing exceptions (or simply returning False), we return a Failure result (with a specific message), allowing the caller to handle this in a cleaner fashion.

Share