🚀 .NET Core & C# Cheatsheet
Complete quick reference guide for .NET developers - Commands, Syntax, Best Practices & More
CLI Commands
Project Management
dotnet new console -n MyApp
dotnet new webapi -n MyAPI
dotnet new mvc -n MyMVC
dotnet new classlib -n MyLib
Build & Run
dotnet build
dotnet run
dotnet watch run
dotnet publish -c Release
Package Management
dotnet add package PackageName
dotnet remove package PackageName
dotnet restore
dotnet list package
C# Basics
Variable Declaration
int number = 10;
string text = "Hello";
var auto = "Type inferred";
const double PI = 3.14159;
double? nullable = null;
String Interpolation
var name = "World";
var msg = $"Hello, {name}!";
var raw = @"C:\path\to\file";
Collections
List<int> list = new() { 1, 2, 3 };
Dictionary<string, int> dict = new();
int[] array = { 1, 2, 3, 4, 5 };
HashSet<string> set = new();
LINQ Queries
// Query Syntax
var result = from item in items
where item.Price > 10
orderby item.Name
select item;
// Method Syntax
var result = items
.Where(x => x.Price > 10)
.OrderBy(x => x.Name)
.Select(x => x);
// Common Methods
.First() / .FirstOrDefault()
.Single() / .SingleOrDefault()
.Any() / .All() / .Count()
.Skip(10).Take(5)
.GroupBy(x => x.Category)
.Join() / .GroupJoin()
Async/Await
public async Task<string> GetDataAsync()
{
var data = await client.GetAsync(url);
return await data.Content
.ReadAsStringAsync();
}
// Multiple awaits
var task1 = GetData1Async();
var task2 = GetData2Async();
await Task.WhenAll(task1, task2);
// Cancellation
async Task DoWork(
CancellationToken token)
{
await Task.Delay(1000, token);
}
Dependency Injection
Register Services
services.AddSingleton<IService, Service>();
services.AddScoped<IRepository, Repo>();
services.AddTransient<IHelper, Helper>();
Constructor Injection
public class MyController
{
private readonly IService _service;
public MyController(IService service)
{
_service = service;
}
}
Lifetimes:
Singleton: One instance per app
Scoped: One per request
Transient: New each time
Singleton: One instance per app
Scoped: One per request
Transient: New each time
Entity Framework Core
DbContext
public class AppDbContext : DbContext
{
public DbSet<User> Users { get; set; }
protected override void OnModelCreating(
ModelBuilder builder)
{
builder.Entity<User>()
.HasKey(u => u.Id);
}
}
CRUD Operations
// Create
context.Users.Add(user);
await context.SaveChangesAsync();
// Read
var user = await context.Users
.FirstOrDefaultAsync(u => u.Id == id);
// Update
user.Name = "New Name";
await context.SaveChangesAsync();
// Delete
context.Users.Remove(user);
await context.SaveChangesAsync();
Migrations
dotnet ef migrations add InitialCreate
dotnet ef database update
dotnet ef migrations remove
Web API Controllers
[ApiController]
[Route("api/[controller]")]
public class UsersController : ControllerBase
{
[HttpGet]
public ActionResult<IEnumerable<User>>
GetAll() => Ok(users);
[HttpGet("{id}")]
public ActionResult<User> Get(int id)
{
var user = users.Find(id);
return user == null
? NotFound()
: Ok(user);
}
[HttpPost]
public ActionResult<User> Create(User user)
{
users.Add(user);
return CreatedAtAction(
nameof(Get),
new { id = user.Id },
user);
}
[HttpPut("{id}")]
public IActionResult Update(
int id, User user) => NoContent();
[HttpDelete("{id}")]
public IActionResult Delete(int id)
=> NoContent();
}
Middleware
Configure Pipeline
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseCors();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
Custom Middleware
public class CustomMiddleware
{
private readonly RequestDelegate _next;
public CustomMiddleware(
RequestDelegate next)
{
_next = next;
}
public async Task InvokeAsync(
HttpContext context)
{
// Before
await _next(context);
// After
}
}
Configuration
appsettings.json
{
"ConnectionStrings": {
"DefaultConnection": "Server=..."
},
"AppSettings": {
"ApiKey": "your-key"
}
}
Access Configuration
// Inject IConfiguration
private readonly IConfiguration _config;
// Get value
var key = _config["AppSettings:ApiKey"];
var conn = _config.GetConnectionString(
"DefaultConnection");
// Bind to object
var settings = new AppSettings();
_config.GetSection("AppSettings")
.Bind(settings);
Exception Handling
try
{
// Code that might throw
}
catch (SpecificException ex)
{
// Handle specific
_logger.LogError(ex, "Error");
}
catch (Exception ex)
{
// Handle general
throw; // Re-throw
}
finally
{
// Cleanup
}
// Global Exception Handler
app.UseExceptionHandler("/error");
// Custom Exception Filter
[ApiController]
[ExceptionFilter]
public class MyController : ControllerBase
{ }
Logging
public class MyService
{
private readonly ILogger<MyService> _log;
public MyService(
ILogger<MyService> logger)
{
_log = logger;
}
public void DoWork()
{
_log.LogInformation("Info");
_log.LogWarning("Warning");
_log.LogError("Error");
_log.LogDebug("Debug");
_log.LogCritical("Critical");
}
}
Log Levels: Trace → Debug → Information → Warning → Error → Critical
Authentication & Authorization
JWT Setup
services.AddAuthentication(
JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options =>
{
options.TokenValidationParameters =
new TokenValidationParameters
{
ValidateIssuer = true,
ValidateAudience = true,
ValidateLifetime = true,
ValidIssuer = "issuer",
ValidAudience = "audience",
IssuerSigningKey = key
};
});
Protect Endpoints
[Authorize]
public class SecureController
: ControllerBase
{
[AllowAnonymous]
public IActionResult Public() { }
[Authorize(Roles = "Admin")]
public IActionResult Admin() { }
}
Testing
Unit Test (xUnit)
public class CalculatorTests
{
[Fact]
public void Add_TwoNumbers_ReturnsSum()
{
// Arrange
var calc = new Calculator();
// Act
var result = calc.Add(2, 3);
// Assert
Assert.Equal(5, result);
}
[Theory]
[InlineData(1, 1, 2)]
[InlineData(2, 3, 5)]
public void Add_Multiple_Works(
int a, int b, int expected)
{
var result = calc.Add(a, b);
Assert.Equal(expected, result);
}
}
dotnet test
dotnet test --logger "console;verbosity=detailed"
Common Patterns
Repository Pattern
public interface IRepository<T>
{
Task<T> GetByIdAsync(int id);
Task<IEnumerable<T>> GetAllAsync();
Task AddAsync(T entity);
Task UpdateAsync(T entity);
Task DeleteAsync(int id);
}
public class Repository<T>
: IRepository<T> where T : class
{
private readonly DbContext _context;
private readonly DbSet<T> _dbSet;
}
Unit of Work
public interface IUnitOfWork
{
IRepository<User> Users { get; }
Task<int> CompleteAsync();
}
Performance Tips
Best Practices:
- Use AsNoTracking() for read-only queries
- Implement response caching
- Use ValueTask for hot paths
- Enable response compression
- Use Span<T> and Memory<T>
Response Caching
services.AddResponseCaching();
app.UseResponseCaching();
[ResponseCache(Duration = 60)]
public IActionResult Get() { }
Memory Cache
services.AddMemoryCache();
_cache.TryGetValue(key, out var data);
_cache.Set(key, data,
TimeSpan.FromMinutes(10));
Common NuGet Packages
| Package | Purpose |
|---|---|
| Newtonsoft.Json | JSON serialization |
| AutoMapper | Object mapping |
| FluentValidation | Input validation |
| Serilog | Structured logging |
| Dapper | Micro ORM |
| MediatR | CQRS pattern |
| Swashbuckle | Swagger/OpenAPI |
| Polly | Resilience & retry |
C# Modern Features
Records (C# 9+)
public record Person(
string Name, int Age);
var person = new Person("John", 30);
var older = person with { Age = 31 };
Pattern Matching
var result = value switch
{
null => "Null",
0 => "Zero",
> 0 and < 10 => "Single digit",
_ => "Other"
};
Null Coalescing
string name = user?.Name ?? "Guest";
name ??= "Default";
var first = list?[0];
Range & Index
var arr = new[] { 1, 2, 3, 4, 5 };
var last = arr[^1]; // Last element
var range = arr[1..4]; // Middle slice
Quick Reference Table
| Task | Command/Code |
|---|---|
| Create new solution | dotnet new sln -n MySolution |
| Add project to solution | dotnet sln add MyProject/MyProject.csproj |
| Add project reference | dotnet add reference ../OtherProject |
| Run with specific config | dotnet run --configuration Release |
| Clean build artifacts | dotnet clean |
| Format code | dotnet format |
| Install global tool | dotnet tool install -g ToolName |
