ASP.NET Core
Modern cross-platform web framework developed by Microsoft. Features high-performance Kestrel server, ideal for microservices.
GitHub Overview
dotnet/aspnetcore
ASP.NET Core is a cross-platform .NET framework for building modern cloud-based web applications on Windows, Mac, or Linux.
Topics
Star History
Framework
ASP.NET Core
Overview
ASP.NET Core is a high-performance, cross-platform web framework developed by Microsoft.
Details
ASP.NET Core is an open-source, cross-platform web framework developed by Microsoft, first released in 2016 as a complete redesign and rebuild of the traditional ASP.NET Framework. It runs on Windows, macOS, and Linux, providing high performance and scalability. The modular design allows you to include only the necessary features, enabling lightweight and fast application development. It supports multiple development models including MVC, Web API, Razor Pages, and Blazor, making it ideal for enterprise-level web application development. Built-in dependency injection, configuration system, logging, and authentication/authorization features enable the construction of robust and maintainable applications. With Docker support and cloud-native design, it's also suitable for modern microservices architecture.
Pros and Cons
Pros
- High Performance: Optimized runtime delivering fast processing
- Cross-Platform: Runs on Windows, macOS, and Linux
- Integrated Development Environment: Powerful development support with Visual Studio
- Enterprise-Ready: Optimized for large-scale application development
- Rich Features: Built-in authentication, authorization, caching, logging, and more
- Strong Type System: Type safety and IntelliSense with C#
- Active Ecosystem: Rich library ecosystem through NuGet
Cons
- Learning Curve: Need to master C# language and framework concepts
- Microsoft Ecosystem: Dependency on Microsoft technology stack
- Memory Usage: Higher memory consumption compared to JVM or Node.js
- Deployment Complexity: Requires .NET runtime installation
- Licensing: Some development tools are paid
Key Links
- ASP.NET Core Official Site
- ASP.NET Core Documentation
- ASP.NET Core GitHub Repository
- .NET Official Site
- Visual Studio
- NuGet Package Manager
Code Examples
Hello World (Basic Web App)
// Program.cs - Minimal API
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.MapGet("/", () => "Hello World!");
app.MapGet("/hello/{name}", (string name) => $"Hello {name}!");
app.Run();
// Program.cs - MVC
var builder = WebApplication.CreateBuilder(args);
// Service registration
builder.Services.AddControllersWithViews();
var app = builder.Build();
// Middleware pipeline
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Home/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
app.Run();
Controllers and Actions
using Microsoft.AspNetCore.Mvc;
namespace MyApp.Controllers
{
public class HomeController : Controller
{
public IActionResult Index()
{
return View();
}
public IActionResult About()
{
ViewData["Message"] = "This is an ASP.NET Core application.";
return View();
}
[HttpPost]
public IActionResult Contact(ContactModel model)
{
if (ModelState.IsValid)
{
// Form processing logic
return RedirectToAction("ContactSuccess");
}
return View(model);
}
[HttpGet]
public JsonResult GetUser(int id)
{
var user = new { Id = id, Name = "John", Email = "[email protected]" };
return Json(user);
}
}
public class ContactModel
{
public string Name { get; set; } = string.Empty;
public string Email { get; set; } = string.Empty;
public string Message { get; set; } = string.Empty;
}
}
Dependency Injection
// Service interface
public interface IUserService
{
Task<User> GetUserAsync(int id);
Task<IEnumerable<User>> GetAllUsersAsync();
}
// Service implementation
public class UserService : IUserService
{
private readonly ILogger<UserService> _logger;
private readonly HttpClient _httpClient;
public UserService(ILogger<UserService> logger, HttpClient httpClient)
{
_logger = logger;
_httpClient = httpClient;
}
public async Task<User> GetUserAsync(int id)
{
_logger.LogInformation("Getting user: {UserId}", id);
var response = await _httpClient.GetAsync($"/api/users/{id}");
response.EnsureSuccessStatusCode();
var json = await response.Content.ReadAsStringAsync();
return JsonSerializer.Deserialize<User>(json) ?? new User();
}
public async Task<IEnumerable<User>> GetAllUsersAsync()
{
var response = await _httpClient.GetAsync("/api/users");
response.EnsureSuccessStatusCode();
var json = await response.Content.ReadAsStringAsync();
return JsonSerializer.Deserialize<IEnumerable<User>>(json) ?? Enumerable.Empty<User>();
}
}
// Registration in Program.cs
builder.Services.AddScoped<IUserService, UserService>();
builder.Services.AddHttpClient<UserService>(client =>
{
client.BaseAddress = new Uri("https://api.example.com");
});
// Usage in controller
public class UsersController : Controller
{
private readonly IUserService _userService;
public UsersController(IUserService userService)
{
_userService = userService;
}
public async Task<IActionResult> Index()
{
var users = await _userService.GetAllUsersAsync();
return View(users);
}
}
Entity Framework Core
// Model definition
public class Blog
{
public int Id { get; set; }
public string Title { get; set; } = string.Empty;
public string Content { get; set; } = string.Empty;
public DateTime CreatedAt { get; set; }
public List<Post> Posts { get; set; } = new();
}
public class Post
{
public int Id { get; set; }
public string Title { get; set; } = string.Empty;
public string Content { get; set; } = string.Empty;
public int BlogId { get; set; }
public Blog Blog { get; set; } = null!;
}
// DbContext
using Microsoft.EntityFrameworkCore;
public class BlogContext : DbContext
{
public BlogContext(DbContextOptions<BlogContext> options) : base(options) { }
public DbSet<Blog> Blogs { get; set; }
public DbSet<Post> Posts { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Blog>()
.Property(b => b.Title)
.IsRequired()
.HasMaxLength(200);
modelBuilder.Entity<Post>()
.HasOne(p => p.Blog)
.WithMany(b => b.Posts)
.HasForeignKey(p => p.BlogId);
}
}
// Configuration in Program.cs
builder.Services.AddDbContext<BlogContext>(options =>
options.UseSqlServer(builder.Configuration.GetConnectionString("DefaultConnection")));
// Usage in controller
public class BlogsController : Controller
{
private readonly BlogContext _context;
public BlogsController(BlogContext context)
{
_context = context;
}
public async Task<IActionResult> Index()
{
var blogs = await _context.Blogs
.Include(b => b.Posts)
.ToListAsync();
return View(blogs);
}
[HttpPost]
public async Task<IActionResult> Create(Blog blog)
{
if (ModelState.IsValid)
{
blog.CreatedAt = DateTime.Now;
_context.Blogs.Add(blog);
await _context.SaveChangesAsync();
return RedirectToAction(nameof(Index));
}
return View(blog);
}
}
Middleware
// Custom middleware
public class RequestLoggingMiddleware
{
private readonly RequestDelegate _next;
private readonly ILogger<RequestLoggingMiddleware> _logger;
public RequestLoggingMiddleware(RequestDelegate next, ILogger<RequestLoggingMiddleware> logger)
{
_next = next;
_logger = logger;
}
public async Task InvokeAsync(HttpContext context)
{
var startTime = DateTime.UtcNow;
_logger.LogInformation("Request started: {Method} {Path}",
context.Request.Method, context.Request.Path);
await _next(context);
var duration = DateTime.UtcNow - startTime;
_logger.LogInformation("Request completed: {Method} {Path} - {StatusCode} ({Duration}ms)",
context.Request.Method, context.Request.Path, context.Response.StatusCode, duration.TotalMilliseconds);
}
}
// Extension method
public static class MiddlewareExtensions
{
public static IApplicationBuilder UseRequestLogging(this IApplicationBuilder builder)
{
return builder.UseMiddleware<RequestLoggingMiddleware>();
}
}
// Usage in Program.cs
app.UseRequestLogging();
// Error handling middleware
public class ErrorHandlingMiddleware
{
private readonly RequestDelegate _next;
private readonly ILogger<ErrorHandlingMiddleware> _logger;
public ErrorHandlingMiddleware(RequestDelegate next, ILogger<ErrorHandlingMiddleware> logger)
{
_next = next;
_logger = logger;
}
public async Task InvokeAsync(HttpContext context)
{
try
{
await _next(context);
}
catch (Exception ex)
{
_logger.LogError(ex, "An unhandled exception occurred");
context.Response.StatusCode = 500;
context.Response.ContentType = "application/json";
var response = new { error = "Internal server error occurred" };
await context.Response.WriteAsync(JsonSerializer.Serialize(response));
}
}
}
Web API and JSON Processing
[ApiController]
[Route("api/[controller]")]
public class ProductsController : ControllerBase
{
private readonly IProductService _productService;
private readonly ILogger<ProductsController> _logger;
public ProductsController(IProductService productService, ILogger<ProductsController> logger)
{
_productService = productService;
_logger = logger;
}
[HttpGet]
public async Task<ActionResult<IEnumerable<Product>>> GetProducts()
{
try
{
var products = await _productService.GetAllProductsAsync();
return Ok(products);
}
catch (Exception ex)
{
_logger.LogError(ex, "Error occurred while getting products");
return StatusCode(500, "Internal server error");
}
}
[HttpGet("{id}")]
public async Task<ActionResult<Product>> GetProduct(int id)
{
var product = await _productService.GetProductByIdAsync(id);
if (product == null)
{
return NotFound($"Product with ID {id} not found");
}
return Ok(product);
}
[HttpPost]
public async Task<ActionResult<Product>> CreateProduct([FromBody] CreateProductRequest request)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
var product = new Product
{
Name = request.Name,
Price = request.Price,
Description = request.Description,
CreatedAt = DateTime.UtcNow
};
var createdProduct = await _productService.CreateProductAsync(product);
return CreatedAtAction(
nameof(GetProduct),
new { id = createdProduct.Id },
createdProduct);
}
[HttpPut("{id}")]
public async Task<IActionResult> UpdateProduct(int id, [FromBody] UpdateProductRequest request)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
var existingProduct = await _productService.GetProductByIdAsync(id);
if (existingProduct == null)
{
return NotFound();
}
existingProduct.Name = request.Name;
existingProduct.Price = request.Price;
existingProduct.Description = request.Description;
existingProduct.UpdatedAt = DateTime.UtcNow;
await _productService.UpdateProductAsync(existingProduct);
return NoContent();
}
[HttpDelete("{id}")]
public async Task<IActionResult> DeleteProduct(int id)
{
var product = await _productService.GetProductByIdAsync(id);
if (product == null)
{
return NotFound();
}
await _productService.DeleteProductAsync(id);
return NoContent();
}
}
// DTO classes
public class CreateProductRequest
{
[Required(ErrorMessage = "Product name is required")]
[StringLength(100, ErrorMessage = "Product name must be 100 characters or less")]
public string Name { get; set; } = string.Empty;
[Range(0, double.MaxValue, ErrorMessage = "Price must be greater than or equal to 0")]
public decimal Price { get; set; }
[StringLength(500, ErrorMessage = "Description must be 500 characters or less")]
public string Description { get; set; } = string.Empty;
}
public class UpdateProductRequest
{
[Required]
[StringLength(100)]
public string Name { get; set; } = string.Empty;
[Range(0, double.MaxValue)]
public decimal Price { get; set; }
[StringLength(500)]
public string Description { get; set; } = string.Empty;
}