Dotnet basic

November 20, 2025

I. Project / Package Name convention

Project name convention

II. Nuget offline

  1. Online: copy '%userprofile%\.nuget\package'
  2. Offline: place in a folder: c:\nugetrepo
  3. Offline: update 'nuget.config'
<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <packageSources>
    <add key="MyOfflineRepo" value="C:\nugetrepo" />
  </packageSources>
</configuration>
  1. Offline: run 'dotnet restore --source c:\nugetrepo'
  2. Offline: run dotnet build

III. Localization with .resx

Cách tốt nhất để tạo và sử dụng tệp Resources/AppStrings.resx là thông qua Visual Studio (hoặc Rider) để tận dụng tính năng tạo lớp truy cập chuỗi (Strongly-Typed Resource Accessor) tự động. Phức tạp và rắc rối hơn Java, bên Java chỉ cần file text .properties và nội dung là name = value.

File mặc định sẽ là English, có thể đặt tên AppStrings.en.resx, Restful nên dùng IStringLocalizer

- AppStrings.resx
- AppStrings.de.resx
- AppStrings.fr.resx
- AppStrings.it.resx

CáchĐề xuấtƯu điểmNhược điểm
IStringLocalizer + Factoryhỗ trợ DI, tự động cultureCần config chút
IStringLocalizer<T>Rất sạch, dễ testPhải tạo class dummy
Strongly-typed classKhôngIntellisense tốtPhải set Culture thủ công
ResourceManagerKhôngKhông cần DICũ, khó test

Cách dùng thì có 4 cách nhưng khuyến khích 2 cách đầu

  • Add thư mục Resources vào context, chứ không mặc định như Java và set default language trong startup.cs

IV. Extension Methods

Extension Method (Phương thức mở rộng):

Là một loại phương thức đặc biệt trong C# (và .NET) cho phép bạn thêm các phương thức mới vào một lớp (class), cấu trúc (struct), hoặc giao diện (interface) hiện có mà không cần phải:

  1. Sửa đổi mã nguồn gốc của lớp đó.
  2. Tạo lớp con kế thừa từ lớp đó.
  3. Biên dịch lại lớp gốc.
using System;
using System.Text.RegularExpressions;
// Step 1: Create a static class
public static class StringExtensions {
    // Step 2: Create a static method with 'this' keyword
    public static bool IsEmail(this string input)   {
        if (string.IsNullOrWhiteSpace(input)) {
            return false;
        }
        string pattern = @"^[^@\s]+@[^@\s]+\.[^@\s]+$";
        return Regex.IsMatch(input.Trim(), pattern);
    }

    // Another useful extension: Capitalize first letter
    public static string Capitalize(this string input) {
        if (string.IsNullOrEmpty(input)) {
            return input;
        }
        return char.ToUpper(input[0]) + input.Substring(1).ToLower();
    }
}

Cách Dùng

class Program {
  static void Main()  {
    string email = "john.doe@example.com";
    string name = "hello world";
    // These methods don't exist in System.String, but we can call them!
    Console.WriteLine(email.IsEmail());        // True
    Console.WriteLine("bad-email".IsEmail());  // False
    Console.WriteLine(name.Capitalize());      // Hello world
    // Works with null (be careful!)
    string nullString = null;
    Console.WriteLine(nullString.IsEmail()); // False (no NullReferenceException)
  }
}

V. Either, EitherAsync, Task<Either<...>>, Validation and LINQ

1. Either

Either<Left, Right>, Either<IError, Unit>

Left, Right chỉ là 2 giá trị nhưng có thể tận dụng vào validation

Left: false, Right: true (pass validation)

Either,Unit của thư viện LanguageExt.

IError: là Interface tự định nghĩa.

1.1 Unit = "void nhưng có thể truyền đi"

  • Định nghĩa
    • Chỉ có 1 giá trị duy nhất
    • Không mang data
    • Chỉ mang ý nghĩa: “thành công”
  • Khi nào dùng Unit
    • Không nên:
        Either<IError, void> // không compile
      
    • Đúng cách:
        Either<IError, Unit>
      
  • Example:
      Either<Error, Unit> ValidateUser(string userId)
      {
        if (string.IsNullOrEmpty(userId))
          return Error.New("Invalid user");
        return Unit.Default;
      }
    

2. LINQ: Select ... from ... where

var result = await (
          from _ in ValidationHelper.ValidateMandatoryParameter(query.UniqueId, query.RepositoryUniqueId).ToAsync()
          from _2 in SecurityHelper.ValidateId(query.UniqueId).ToAsync()
          from _3 in SecurityHelper.ValidateId(query.RepositoryUniqueId).ToAsync()            
          from binaryResponse in service.GetDocument(query).ToAsync()
          select binaryResponse);
  • _ là discard
  • Unit chỉ mang ý nghĩa PASS
  • select binaryResponse quyết định kết quả cuối

Model Right ──▶ Right ──▶ Right ──▶ Right ──▶ Right(binaryResponse) │
└── Left(error) ──▶ STOP

  • result: right khi tất cả là right
  • result: left, chỉ cần một bước trả left thì pipeline dừng lại và resultleft với lỗi đó.
  • pipeline: một chuỗi các bước xử lý dữ liệu, chạy theo thứ tự, đầu ra của bước trước là đầu vào của bước sau (giống như dây chuyền sản xuất), fail fast (bước nào fail thì dừng ngay)