Aller au contenu principal

Bonnes pratiques

Recommandations pour une intégration optimale avec MCM.ApiProxy.

Architecture

Créer une couche de service

Ne pas injecter les clients MCM directement dans les contrôleurs. Créez une couche de service :

// BON - Couche de service
public class EmployeService
{
private readonly IEmployesClient _employesClient;

public EmployeService(IEmployesClient employesClient)
{
_employesClient = employesClient;
}

public async Task<EmployeDto?> GetEmployeAsync(string id)
{
var result = await _employesClient.GetEmployeById(id);
return result.IsError ? null : MapToDto(result.Value);
}
}

// Contrôleur utilise le service
public class EmployesController : ControllerBase
{
private readonly EmployeService _employeService;
// ...
}

Utiliser l'injection de dépendances

Toujours injecter les clients via le constructeur :

// BON
public class MonService
{
private readonly IEmployesClient _employesClient;

public MonService(IEmployesClient employesClient)
{
_employesClient = employesClient;
}
}

// MAUVAIS - Service locator
public class MonService
{
public void DoSomething(IServiceProvider services)
{
var client = services.GetService<IEmployesClient>();
}
}

Performance

Éviter les appels en boucle

// MAUVAIS - N appels API
foreach (var id in employeIds)
{
var result = await _employesClient.GetEmployeById(id);
// ...
}

// BON - Un seul appel
var allEmployes = await _employesClient.GetAllEmployes();
var filtered = allEmployes.Value.Where(e => employeIds.Contains(e.IdExterne));

Utiliser la synchronisation pour les lots

// BON - Un seul appel pour plusieurs opérations
await _syncClient.Sync(
employes,
employeurs,
objetsConsentement);

Mettre en cache quand approprié

public class CachedFormulaireService
{
private readonly IFormulaireClient _formulaireClient;
private readonly IMemoryCache _cache;

public async Task<List<B2BFormulaireItem>> GetFormulairesAsync()
{
return await _cache.GetOrCreateAsync("formulaires", async entry =>
{
entry.AbsoluteExpirationRelativeToNow = TimeSpan.FromHours(1);

var result = await _formulaireClient.GetAllFormulaires();
return result.IsError ? new List<B2BFormulaireItem>() : result.Value.ToList();
});
}
}

Gestion des erreurs

Logger systématiquement

public async Task<bool> CreateEmployeAsync(B2BUpdateEmployeDto employe)
{
using var _ = _logger.BeginScope(new { EmployeId = employe.IdExterne });

var result = await _employesClient.AddEmploye(employe);

if (result.IsError)
{
_logger.LogError(
"Échec création employé - Code: {ErrorCode}, Description: {ErrorDescription}",
result.FirstError.Code,
result.FirstError.Description);
return false;
}

_logger.LogInformation("Employé créé avec succès");
return true;
}

Ne pas ignorer les erreurs

// MAUVAIS - Erreur silencieuse
var result = await _employesClient.GetEmployeById(id);
return result.Value; // Exception si erreur!

// BON - Gestion explicite
var result = await _employesClient.GetEmployeById(id);
if (result.IsError)
{
throw new EmployeNotFoundException(id);
}
return result.Value;

Données

Valider avant d'envoyer

public async Task<ErrorOr<Success>> CreateEmployeAsync(CreateEmployeRequest request)
{
// Validation locale d'abord
if (string.IsNullOrWhiteSpace(request.IdExterne))
{
return Error.Validation("IdExterne.Required", "IdExterne est obligatoire");
}

if (!IsValidEmail(request.Courriel))
{
return Error.Validation("Courriel.Invalid", "Format de courriel invalide");
}

// Puis appel API
var dto = MapToDto(request);
return await _employesClient.AddEmploye(dto);
}

Utiliser des identifiants stables

// BON - Identifiant stable basé sur votre système
var employe = new B2BUpdateEmployeDto
{
IdExterne = $"HRIS-{employee.HrisId}", // Basé sur votre système RH
// ...
};

// MAUVAIS - Identifiant qui peut changer
var employe = new B2BUpdateEmployeDto
{
IdExterne = employee.Email, // L'email peut changer!
// ...
};

Tests

Mocker les clients dans les tests

public class EmployeServiceTests
{
[Fact]
public async Task GetEmploye_ReturnsEmploye_WhenFound()
{
// Arrange
var mockClient = new Mock<IEmployesClient>();
mockClient
.Setup(c => c.GetEmployeById("EMP-123"))
.ReturnsAsync(new B2BEmployeItem { IdExterne = "EMP-123", Nom = "Test" });

var service = new EmployeService(mockClient.Object);

// Act
var result = await service.GetEmployeAsync("EMP-123");

// Assert
Assert.NotNull(result);
Assert.Equal("Test", result.Nom);
}
}

Sécurité

Protéger la clé API

  • Utilisez les secrets utilisateur en développement
  • Utilisez Azure Key Vault ou équivalent en production
  • Ne loggez jamais la clé API
  • Faites la rotation régulièrement

Valider les entrées utilisateur

// Avant d'utiliser un ID fourni par l'utilisateur
public async Task<IActionResult> GetEmploye(string id)
{
if (string.IsNullOrWhiteSpace(id) || id.Length > 100)
{
return BadRequest("ID invalide");
}

// Seulement après validation
var result = await _employeService.GetEmployeAsync(id);
// ...
}