.net core cheat sheet

.NET Core Complete Developer Cheat Sheet - Commands, APIs & Best Practices

.NET Core Complete Cheat Sheet

Comprehensive Guide to .NET Core Commands, APIs, and Best Practices

🚀 CLI Commands

Project Management

dotnet new console -n MyApp // Create console app dotnet new webapi -n MyApi // Create Web API dotnet new mvc -n MyMvc // Create MVC app dotnet new classlib -n MyLib // Create class library dotnet new sln -n MySolution // Create solution dotnet sln add MyApp/MyApp.csproj // Add project to solution

Build & Run

dotnet restore // Restore dependencies dotnet build // Build project dotnet run // Run project dotnet watch run // Run with hot reload dotnet publish -c Release // Publish for production dotnet clean // Clean build outputs

Package Management

dotnet add package Newtonsoft.Json // Add NuGet package dotnet remove package PackageName // Remove package dotnet list package // List packages dotnet add reference ../MyLib/MyLib.csproj // Add project reference

Testing

dotnet test // Run all tests dotnet test --filter TestCategory=Unit // Run filtered tests dotnet test --collect:"XPlat Code Coverage" // Run with coverage

🏗️ Program.cs Structure (Minimal API)

var builder = WebApplication.CreateBuilder(args); // Add services to container builder.Services.AddControllers(); builder.Services.AddEndpointsApiExplorer(); builder.Services.AddSwaggerGen(); var app = builder.Build(); // Configure HTTP pipeline if (app.Environment.IsDevelopment()) { app.UseSwagger(); app.UseSwaggerUI(); } app.UseHttpsRedirection(); app.UseAuthorization(); app.MapControllers(); app.Run();

🎯 Dependency Injection

Service Lifetimes

Lifetime Method Usage
Transient AddTransient Created each time requested. Best for lightweight, stateless services
Scoped AddScoped Created once per request. Best for database contexts
Singleton AddSingleton Created once for application lifetime. Best for caching, config

Registration Examples

// Interface to implementation builder.Services.AddScoped<IUserService, UserService>(); // With factory builder.Services.AddSingleton<IConfig>(sp => new Config(sp.GetRequiredService<IOptions<Settings>>())); // With instance builder.Services.AddSingleton(new MyService()); // Multiple implementations builder.Services.AddTransient<INotification, EmailNotification>(); builder.Services.AddTransient<INotification, SmsNotification>();

📋 Controllers & Actions

Controller Template

[ApiController] [Route("api/[controller]")] public class UsersController : ControllerBase { private readonly IUserService _userService; public UsersController(IUserService userService) { _userService = userService; } [HttpGet] public async Task<ActionResult<IEnumerable<User>>> GetAll() { var users = await _userService.GetAllAsync(); return Ok(users); } [HttpGet("{id}")] public async Task<ActionResult<User>> GetById(int id) { var user = await _userService.GetByIdAsync(id); if (user == null) return NotFound(); return Ok(user); } [HttpPost] public async Task<ActionResult<User>> Create(User user) { var created = await _userService.CreateAsync(user); return CreatedAtAction(nameof(GetById), new { id = created.Id }, created); } [HttpPut("{id}")] public async Task<IActionResult> Update(int id, User user) { await _userService.UpdateAsync(id, user); return NoContent(); } [HttpDelete("{id}")] public async Task<IActionResult> Delete(int id) { await _userService.DeleteAsync(id); return NoContent(); } }

Common Action Results

Success Responses

Ok(data) // 200 Created(uri, data) // 201 NoContent() // 204 Accepted() // 202

Error Responses

BadRequest() // 400 Unauthorized() // 401 Forbidden() // 403 NotFound() // 404 Conflict() // 409

🗄️ Entity Framework Core

DbContext Setup

public class ApplicationDbContext : DbContext { public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options) : base(options) { } public DbSet<User> Users { get; set; } public DbSet<Product> Products { get; set; } protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.Entity<User>() .HasIndex(u => u.Email) .IsUnique(); modelBuilder.Entity<Product>() .Property(p => p.Price) .HasPrecision(18, 2); } }

Configuration in Program.cs

builder.Services.AddDbContext<ApplicationDbContext>(options => options.UseSqlServer(builder.Configuration.GetConnectionString("DefaultConnection"))); // Or PostgreSQL options.UseNpgsql(connectionString); // Or SQLite options.UseSqlite(connectionString);

Migrations

dotnet ef migrations add InitialCreate dotnet ef database update dotnet ef migrations remove dotnet ef database drop

Common CRUD Operations

// Read var users = await _context.Users.ToListAsync(); var user = await _context.Users.FindAsync(id); var filtered = await _context.Users .Where(u => u.Age > 18) .OrderBy(u => u.Name) .ToListAsync(); // Create _context.Users.Add(newUser); await _context.SaveChangesAsync(); // Update var user = await _context.Users.FindAsync(id); user.Name = "Updated Name"; await _context.SaveChangesAsync(); // Delete var user = await _context.Users.FindAsync(id); _context.Users.Remove(user); await _context.SaveChangesAsync(); // Include related data var users = await _context.Users .Include(u => u.Orders) .ThenInclude(o => o.Items) .ToListAsync();

⚙️ Configuration

appsettings.json

{ "ConnectionStrings": { "DefaultConnection": "Server=...;Database=...;" }, "Logging": { "LogLevel": { "Default": "Information", "Microsoft.AspNetCore": "Warning" } }, "AppSettings": { "ApiKey": "your-api-key", "MaxPageSize": 100 } }

Reading Configuration

// Direct access var apiKey = builder.Configuration["AppSettings:ApiKey"]; // Strongly typed with Options pattern public class AppSettings { public string ApiKey { get; set; } public int MaxPageSize { get; set; } } builder.Services.Configure<AppSettings>( builder.Configuration.GetSection("AppSettings")); // Inject in controller public MyController(IOptions<AppSettings> options) { _settings = options.Value; }

🔒 Authentication & Authorization

JWT Authentication Setup

builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) .AddJwtBearer(options => { options.TokenValidationParameters = new TokenValidationParameters { ValidateIssuer = true, ValidateAudience = true, ValidateLifetime = true, ValidateIssuerSigningKey = true, ValidIssuer = builder.Configuration["Jwt:Issuer"], ValidAudience = builder.Configuration["Jwt:Audience"], IssuerSigningKey = new SymmetricSecurityKey( Encoding.UTF8.GetBytes(builder.Configuration["Jwt:Key"])) }; }); app.UseAuthentication(); app.UseAuthorization();

Authorization Attributes

[Authorize] // Requires authentication [AllowAnonymous] // Allows anonymous access [Authorize(Roles = "Admin")] // Requires role [Authorize(Policy = "MinAge18")] // Requires policy

Policy-Based Authorization

builder.Services.AddAuthorization(options => { options.AddPolicy("MinAge18", policy => policy.Requirements.Add(new MinimumAgeRequirement(18))); });

🌐 Middleware

Built-in Middleware Order

app.UseHttpsRedirection(); app.UseStaticFiles(); app.UseRouting(); app.UseCors(); app.UseAuthentication(); app.UseAuthorization(); app.MapControllers();

Custom Middleware

public class RequestLoggingMiddleware { private readonly RequestDelegate _next; private readonly ILogger _logger; public RequestLoggingMiddleware(RequestDelegate next, ILogger<RequestLoggingMiddleware> logger) { _next = next; _logger = logger; } public async Task InvokeAsync(HttpContext context) { _logger.LogInformation($"Request: {context.Request.Path}"); await _next(context); } } // Register middleware app.UseMiddleware<RequestLoggingMiddleware>();

📦 Model Validation

Data Annotations

public class User { [Required(ErrorMessage = "Name is required")] [StringLength(100, MinimumLength = 3)] public string Name { get; set; } [Required] [EmailAddress] public string Email { get; set; } [Range(18, 120)] public int Age { get; set; } [Url] public string Website { get; set; } [RegularExpression(@"^[0-9]{10}$")] public string Phone { get; set; } [Compare("Password")] public string ConfirmPassword { get; set; } }

Manual Validation in Controller

[HttpPost] public IActionResult Create(User user) { if (!ModelState.IsValid) { return BadRequest(ModelState); } // Process valid data return Ok(); }

🔧 Async/Await Patterns

// Good: Async all the way public async Task<User> GetUserAsync(int id) { return await _context.Users.FindAsync(id); } // Avoid: Blocking async code // var user = GetUserAsync(id).Result; // DON'T // Multiple async operations var task1 = _service.GetDataAsync(); var task2 = _service.GetOtherDataAsync(); await Task.WhenAll(task1, task2); // ConfigureAwait for library code await SomeMethodAsync().ConfigureAwait(false);

🧪 Testing

Unit Test Example (xUnit)

public class UserServiceTests { [Fact] public async Task GetUser_ReturnsUser_WhenUserExists() { // Arrange var mockRepo = new Mock<IUserRepository>(); mockRepo.Setup(r => r.GetByIdAsync(1)) .ReturnsAsync(new User { Id = 1, Name = "Test" }); var service = new UserService(mockRepo.Object); // Act var result = await service.GetUserAsync(1); // Assert Assert.NotNull(result); Assert.Equal("Test", result.Name); } [Theory] [InlineData(1)] [InlineData(2)] [InlineData(3)] public async Task GetUser_WithDifferentIds(int id) { // Test implementation } }
💡 Pro Tips:
• Use ILogger<T> for structured logging instead of Console.WriteLine
• Always dispose DbContext, HttpClient, and other IDisposable resources
• Use async/await throughout your entire call stack for better performance
• Implement global exception handling middleware for production apps
• Use configuration providers for different environments (Development, Staging, Production)
⚠️ Important Notes:
• .NET 6+ uses minimal hosting model with top-level statements
• Always validate user input and sanitize data before database operations
• Use [ApiController] attribute for automatic model validation
• Keep controllers thin - move business logic to services
• Use DTOs to separate internal models from API responses
Scroll to Top