La gestion du versioning des APIs est un aspect crucial du développement d'applications modernes en .NET. Avec l'évolution constante des besoins métier et des technologies, il est essentiel de pouvoir faire évoluer nos APIs tout en maintenant la compatibilité avec les clients existants. Dans cet article, nous explorerons les différentes stratégies de versioning d'API dans le contexte .NET, avec un focus particulier sur ASP.NET Core.
Les fondamentaux du versioning d'API
Le versioning d'API permet de gérer l'évolution de nos services web tout en assurant la rétrocompatibilité. En .NET, plusieurs approches sont possibles :
- URI versioning
- Query string versioning
- Header versioning
- Media type versioning
Implémentation avec ASP.NET Core
Commençons par installer le package NuGet nécessaire :
dotnet add package Microsoft.AspNetCore.Mvc.Versioning
1. URI Versioning
Cette approche est la plus simple à implémenter et à comprendre :
// Program.cs
builder.Services.AddApiVersioning(options =>
{
options.DefaultApiVersion = new ApiVersion(1, 0);
options.AssumeDefaultVersionWhenUnspecified = true;
options.ReportApiVersions = true;
});
// WeatherForecastController.cs
[ApiController]
[Route("api/v{version:apiVersion}/[controller]")]
[ApiVersion("1.0")]
public class WeatherForecastController : ControllerBase
{
[HttpGet]
public IActionResult Get()
{
// Version 1.0 implementation
}
}
[ApiController]
[Route("api/v{version:apiVersion}/[controller]")]
[ApiVersion("2.0")]
public class WeatherForecastV2Controller : ControllerBase
{
[HttpGet]
public IActionResult Get()
{
// Version 2.0 implementation
}
}
2. Query String Versioning
// Program.cs
builder.Services.AddApiVersioning(options =>
{
options.DefaultApiVersion = new ApiVersion(1, 0);
options.AssumeDefaultVersionWhenUnspecified = true;
options.ApiVersionReader = new QueryStringApiVersionReader("api-version");
});
// Controller
[ApiController]
[Route("api/[controller]")]
[ApiVersion("1.0")]
[ApiVersion("2.0")]
public class ProductsController : ControllerBase
{
[HttpGet]
[MapToApiVersion("1.0")]
public IActionResult GetV1()
{
// Version 1.0 implementation
}
[HttpGet]
[MapToApiVersion("2.0")]
public IActionResult GetV2()
{
// Version 2.0 implementation
}
}
Bonnes pratiques de versioning
- Planification des versions : Définissez une stratégie claire de versioning dès le début du projet
- Documentation : Utilisez Swagger/OpenAPI pour documenter les différentes versions
- Rétrocompatibilité : Maintenez la compatibilité descendante autant que possible
- Deprecation : Implémentez un mécanisme de dépréciation pour les anciennes versions
Gestion des erreurs et validation
public class ApiVersioningErrorResponseProvider : IErrorResponseProvider
{
public IActionResult CreateResponse(ErrorResponseContext context)
{
var response = new
{
Message = "Version d'API non supportée",
SupportedVersions = context.SupportedVersions,
CurrentVersion = context.RequestedApiVersion
};
return new JsonResult(response)
{
StatusCode = StatusCodes.Status400BadRequest
};
}
}
Tests unitaires
public class ApiVersioningTests
{
[Fact]
public async Task Get_WithValidVersion_ReturnsSuccess()
{
// Arrange
var client = _factory.CreateClient();
client.DefaultRequestHeaders.Add("api-version", "1.0");
// Act
var response = await client.GetAsync("/api/products");
// Assert
response.EnsureSuccessStatusCode();
}
}
Patterns d'implémentation avancés
Feature Toggles avec versioning
public class FeatureVersioningService
{
private readonly IFeatureManager _featureManager;
public FeatureVersioningService(IFeatureManager featureManager)
{
_featureManager = featureManager;
}
public async Task HandleRequest(string version, Func> v1Action, Func> v2Action)
{
if (version == "2.0" && await _featureManager.IsEnabledAsync("V2Features"))
{
return await v2Action();
}
return await v1Action();
}
}
Considérations de performance
Pour optimiser les performances de vos APIs versionnées :
- Utilisez le caching avec des en-têtes de version
- Implémentez la compression de réponse
- Optimisez la sérialisation JSON
builder.Services.AddResponseCaching();
builder.Services.AddResponseCompression(options =>
{
options.EnableForHttps = true;
options.Providers.Add();
});
Monitoring et observabilité
Utilisez Application Insights pour suivre l'utilisation des différentes versions :
public class ApiVersionTelemetryInitializer : ITelemetryInitializer
{
public void Initialize(ITelemetry telemetry)
{
if (telemetry is RequestTelemetry requestTelemetry)
{
var apiVersion = // Extract API version
requestTelemetry.Properties["ApiVersion"] = apiVersion;
}
}
}
Conclusion
Le versioning d'API est un aspect crucial du développement d'applications .NET modernes. Les bonnes pratiques incluent :
- Choisir une stratégie de versioning adaptée à vos besoins
- Documenter clairement les changements entre versions
- Implémenter une gestion d'erreurs robuste
- Maintenir des tests automatisés
- Surveiller l'utilisation des différentes versions
En suivant ces recommandations, vous pourrez gérer efficacement l'évolution de vos APIs tout en maintenant une excellente expérience développeur pour vos clients.