Dans le monde du développement mobile moderne, les APIs REST sont devenues incontournables pour connecter les applications mobiles aux services backend. Avec l'écosystème .NET, nous disposons d'outils puissants comme ASP.NET Core pour créer des APIs robustes et performantes. Cet article explore en détail la création d'APIs REST pour applications mobiles avec les technologies .NET modernes.
Fondamentaux des APIs REST en .NET
Une API REST (Representational State Transfer) est un style d'architecture qui définit un ensemble de contraintes pour la création de services web. Dans le contexte .NET, ASP.NET Core Web API fournit un framework idéal pour implémenter ces principes.
Principes REST essentiels
- Interface uniforme
- Sans état (Stateless)
- Mise en cache possible
- Architecture client-serveur
- Système en couches
Implémentation avec ASP.NET Core
Voici un exemple de contrôleur API REST basique :
[ApiController]
[Route("api/[controller]")]
public class ProductsController : ControllerBase
{
private readonly IProductService _productService;
public ProductsController(IProductService productService)
{
_productService = productService;
}
// GET api/products
[HttpGet]
public async Task>> GetProducts()
{
var products = await _productService.GetAllAsync();
return Ok(products);
}
// GET api/products/5
[HttpGet("{id}")]
public async Task> GetProduct(int id)
{
var product = await _productService.GetByIdAsync(id);
if (product == null)
return NotFound();
return Ok(product);
}
}
Bonnes pratiques pour les APIs mobiles
Versioning
Implémentez le versioning de votre API pour gérer les évolutions :
[ApiVersion("1.0")]
[Route("api/v{version:apiVersion}/[controller]")]
public class ProductsController : ControllerBase
{
// ... implementation
}
Pagination
Exemple de pagination avec Entity Framework Core :
public class PaginationParameters
{
public int PageNumber { get; set; } = 1;
public int PageSize { get; set; } = 10;
}
[HttpGet]
public async Task>> GetProducts(
[FromQuery] PaginationParameters parameters)
{
var products = await _context.Products
.Skip((parameters.PageNumber - 1) parameters.PageSize)
.Take(parameters.PageSize)
.ToListAsync();
return Ok(new PagedResponse(products, parameters.PageNumber, parameters.PageSize));
}
Gestion des erreurs
Implémentez un middleware de gestion globale des exceptions :
public class ErrorHandlingMiddleware
{
private readonly RequestDelegate _next;
private readonly ILogger _logger;
public ErrorHandlingMiddleware(RequestDelegate next, ILogger logger)
{
_next = next;
_logger = logger;
}
public async Task InvokeAsync(HttpContext context)
{
try
{
await _next(context);
}
catch (Exception ex)
{
_logger.LogError(ex, "Une erreur est survenue");
await HandleExceptionAsync(context, ex);
}
}
private static Task HandleExceptionAsync(HttpContext context, Exception ex)
{
var result = JsonSerializer.Serialize(new {
Error = ex.Message
});
context.Response.ContentType = "application/json";
context.Response.StatusCode = ex switch
{
NotFoundException => StatusCodes.Status404NotFound,
ValidationException => StatusCodes.Status400BadRequest,
_ => StatusCodes.Status500InternalServerError
};
return context.Response.WriteAsync(result);
}
}
Sécurité et authentification
Intégration de l'authentification JWT :
public void ConfigureServices(IServiceCollection services)
{
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options =>
{
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = true,
ValidateAudience = true,
ValidateLifetime = true,
ValidateIssuerSigningKey = true,
ValidIssuer = Configuration["Jwt:Issuer"],
ValidAudience = Configuration["Jwt:Audience"],
IssuerSigningKey = new SymmetricSecurityKey(
Encoding.UTF8.GetBytes(Configuration["Jwt:Key"]))
};
});
}
Tests d'API
Exemple de tests avec xUnit :
public class ProductsControllerTests
{
private readonly ProductsController _controller;
private readonly Mock _serviceMock;
public ProductsControllerTests()
{
_serviceMock = new Mock();
_controller = new ProductsController(_serviceMock.Object);
}
[Fact]
public async Task GetProducts_ReturnsOkResult_WithProducts()
{
// Arrange
var expectedProducts = new List
{
new Product { Id = 1, Name = "Test Product" }
};
_serviceMock.Setup(x => x.GetAllAsync())
.ReturnsAsync(expectedProducts);
// Act
var result = await _controller.GetProducts();
// Assert
var okResult = Assert.IsType(result.Result);
var returnProducts = Assert.IsAssignableFrom>(
okResult.Value);
Assert.Equal(expectedProducts.Count, returnProducts.Count());
}
}
Performance et optimisation
Utilisez la mise en cache avec Redis :
public class CachedProductService : IProductService
{
private readonly IDistributedCache _cache;
private readonly IProductService _productService;
public async Task GetByIdAsync(int id)
{
var cacheKey = $"product-{id}";
var product = await _cache.GetAsync(cacheKey);
if (product == null)
{
product = await _productService.GetByIdAsync(id);
await _cache.SetAsync(cacheKey, product,
TimeSpan.FromMinutes(10));
}
return product;
}
}
Conclusion
La création d'APIs REST pour applications mobiles avec .NET nécessite une attention particulière à plusieurs aspects : architecture, sécurité, performance et testabilité. En suivant les bonnes pratiques présentées et en utilisant les outils modernes de l'écosystème .NET, vous pouvez créer des APIs robustes et maintena
bles.
Points clés à retenir :
- Utilisez ASP.NET Core pour créer des APIs RESTful modernes
- Implémentez le versioning et la pagination
- Gérez correctement les erreurs et les exceptions
- Sécurisez vos APIs avec JWT
- Testez rigoureusement avec xUnit
- Optimisez les performances avec la mise en cache