.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
• 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)
• 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
• Keep controllers thin - move business logic to services
• Use DTOs to separate internal models from API responses
• .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
