Designing Perfect REST APIs with ASP.NET Core
RESTful API'ler modern uygulamaların omurgasıdır. Bu rehber, ASP.NET Core ile profesyonel REST API'ler tasarlamayı öğretir.
REST Prensipleri
REST (Representational State Transfer) 6 ana prensiplerine dayanır:
- Client-Server Architecture: İstemci ve sunucu bağımsızdır
- Statelessness: Her istek, kendisini tanımlamak için gerekli tüm bilgiyi içerir
- Uniform Interface: Tutarlı bir arayüz, API kullanımını kolaylaştırır
- Cacheability: Yanıtlar cache edilebilir olmalıdır
- Layered System: Sistem katmanlandırılabilir olmalıdır
- Code on Demand: İsteğe bağlı olarak, sunucu kod gönderebilir
Routing
ASP.NET Core'da attribute-based routing kullanmak modern ve güvendir:
[ApiController]
[Route("api/[controller]")]
public class ProductsController : ControllerBase
{
[HttpGet("{id}")]
public async Task<ActionResult<ProductDto>> GetProduct(int id)
{
var product = await _service.GetProductAsync(id);
if (product == null)
return NotFound();
return Ok(product);
}
[HttpPost]
public async Task<ActionResult<ProductDto>> CreateProduct(CreateProductDto dto)
{
var product = await _service.CreateProductAsync(dto);
return CreatedAtAction(nameof(GetProduct), new { id = product.Id }, product);
}
}
Versioning
API versioning, geriye dönüş uyumluluğu sağlar:
[ApiController]
[Route("api/v{version:apiVersion}/products")]
[ApiVersion("1.0")]
[ApiVersion("2.0")]
public class ProductsController : ControllerBase
{
[HttpGet]
[MapToApiVersion("1.0")]
public async Task<ActionResult<IEnumerable<ProductDtoV1>>> GetProductsV1()
{
// V1 implementation
}
[HttpGet]
[MapToApiVersion("2.0")]
public async Task<ActionResult<IEnumerable<ProductDtoV2>>> GetProductsV2()
{
// V2 implementation with additional fields
}
}
Error Handling
Tutarlı error response'ları, API kullanıcılarını mutlu eder:
public class ApiErrorResponse
{
public string Type { get; set; }
public string Title { get; set; }
public int Status { get; set; }
public string Detail { get; set; }
public Dictionary<string, string[]> Errors { get; set; }
}
[ApiController]
[Route("api/[controller]")]
public class ProductsController : ControllerBase
{
[HttpPost]
public async Task<ActionResult<ProductDto>> CreateProduct(CreateProductDto dto)
{
try
{
var product = await _service.CreateProductAsync(dto);
return CreatedAtAction(nameof(GetProduct), new { id = product.Id }, product);
}
catch (ValidationException ex)
{
return BadRequest(new ApiErrorResponse
{
Type = "https://api.example.com/errors/validation",
Title = "Validation Failed",
Status = 400,
Detail = ex.Message,
Errors = ex.Errors
});
}
}
}
Authentication & Authorization
JWT tabanlı authentication kullanmak modern API'ler için standarttır:
builder.Services
.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options =>
{
options.Authority = "https://your-auth-server.com";
options.Audience = "your-api";
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = true,
ValidateAudience = true,
ValidateLifetime = true
};
});
[Authorize]
[HttpPost]
public async Task<ActionResult<ProductDto>> CreateProduct(CreateProductDto dto)
{
// Only authenticated users
}
Sonuç
Profesyonel REST API'ler tasarlamak, user experience'i ve sistem güvenilirliğini artırır.