Observação
O acesso a essa página exige autorização. Você pode tentar entrar ou alterar diretórios.
O acesso a essa página exige autorização. Você pode tentar alterar os diretórios.
Microsoft. O Identity.Web fornece três abordagens para chamar suas próprias APIs protegidas: IDownstreamApi, IAuthorizationHeaderProvider e MicrosoftIdentityMessageHandler.
Escolher uma abordagem
Ao chamar APIs REST personalizadas, você tem três opções principais, dependendo de suas necessidades:
| Abordagem | Complexidade | Flexibilidade | Caso de uso |
|---|---|---|---|
| IDownstreamApi | Baixo | Medium | APIs REST padrão com configuração |
| MicrosoftIdentityMessageHandler | Medium | Alto | HttpClient com DI e pipeline composable |
| IAuthorizationHeaderProvider | Alto | Muito alto | Controle total sobre solicitações HTTP |
Usar iDownstreamApi para cenários padrão
IDownstreamApi fornece uma abordagem simples e orientada por configuração para chamar APIs REST com aquisição automática de token.
Instalar o pacote
Adicione o pacote NuGet DownstreamApi ao seu projeto.
dotnet add package Microsoft.Identity.Web.DownstreamApi
Definir as configurações da API
Defina sua API em appsettings.json:
{
"AzureAd": {
"Instance": "https://login.microsoftonline.com/",
"TenantId": "your-tenant-id",
"ClientId": "your-client-id",
"ClientCredentials": [
{
"SourceType": "ClientSecret",
"ClientSecret": "your-client-secret"
}
]
},
"DownstreamApis": {
"MyApi": {
"BaseUrl": "https://api.example.com",
"Scopes": ["api://my-api-client-id/read", "api://my-api-client-id/write"],
"RelativePath": "api/v1",
"RequestAppToken": false
},
"PartnerApi": {
"BaseUrl": "https://partner.example.com",
"Scopes": ["api://partner-api-id/.default"],
"RequestAppToken": true
}
}
}
Configurar ASP.NET Core
Registre a autenticação e os serviços de API downstream em seu Program.cs arquivo.
using Microsoft.Identity.Web;
var builder = WebApplication.CreateBuilder(args);
// Add authentication
builder.Services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
.AddMicrosoftIdentityWebApp(builder.Configuration.GetSection("AzureAd"))
.EnableTokenAcquisitionToCallDownstreamApi()
.AddInMemoryTokenCaches();
// Register downstream APIs
builder.Services.AddDownstreamApis(
builder.Configuration.GetSection("DownstreamApis"));
builder.Services.AddControllersWithViews();
var app = builder.Build();
app.UseAuthentication();
app.UseAuthorization();
app.MapControllers();
app.Run();
Executar operações básicas de API
O controlador a seguir demonstra as operações GET, POST, PUT e DELETE em uma API downstream configurada.
using Microsoft.Identity.Abstractions;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
[Authorize]
public class ProductsController : Controller
{
private readonly IDownstreamApi _api;
public ProductsController(IDownstreamApi api)
{
_api = api;
}
// GET request
public async Task<IActionResult> Index()
{
var products = await _api.GetForUserAsync<List<Product>>(
"MyApi",
"products");
return View(products);
}
// Call downstream API with GET request with query parameters
public async Task<IActionResult> Details(int id)
{
var product = await _api.GetForUserAsync<Product>(
"MyApi",
$"products/{id}");
return View(product);
}
// Call downstream API with POST request
[HttpPost]
public async Task<IActionResult> Create([FromBody] Product product)
{
var created = await _api.PostForUserAsync<Product, Product>(
"MyApi",
"products",
product);
return CreatedAtAction(nameof(Details), new { id = created.Id }, created);
}
// Call downstream API with PUT request
[HttpPut("{id}")]
public async Task<IActionResult> Update(int id, [FromBody] Product product)
{
var updated = await _api.PutForUserAsync<Product, Product>(
"MyApi",
$"products/{id}",
product);
return Ok(updated);
}
// Call downstream API with DELETE request
[HttpDelete("{id}")]
public async Task<IActionResult> Delete(int id)
{
await _api.DeleteForUserAsync<Product>(
"MyApi",
$"products/{id}");
return NoContent();
}
}
Configurar opções avançadas do IDownstreamApi
Use essas opções para personalizar cabeçalhos de solicitação, substituir a configuração, adicionar parâmetros de consulta e ler cabeçalhos de resposta.
Adicionar cabeçalhos e opções personalizados
O exemplo a seguir adiciona cabeçalhos HTTP personalizados à solicitação de saída.
public async Task<IActionResult> GetDataWithHeaders()
{
var options = new DownstreamApiOptions
{
CustomizeHttpRequestMessage = message =>
{
message.Headers.Add("X-Custom-Header", "MyValue");
message.Headers.Add("X-Request-Id", Guid.NewGuid().ToString());
message.Headers.Add("X-Correlation-Id", HttpContext.TraceIdentifier);
}
};
var data = await _api.CallApiForUserAsync<MyData>(
"MyApi",
options,
content: null);
return Ok(data);
}
Substituir a configuração por solicitação
O exemplo a seguir substitui a URL base, os escopos e o tipo de token para uma única solicitação.
public async Task<IActionResult> CallDifferentEndpoint()
{
var options = new DownstreamApiOptions
{
BaseUrl = "https://alternative-api.example.com",
RelativePath = "v2/data",
Scopes = new[] { "api://alternative/.default" },
RequestAppToken = true
};
var data = await _api.CallApiForAppAsync<MyData>(
"MyApi",
options);
return Ok(data);
}
Adicionar parâmetros de consulta
O exemplo a seguir cria uma solicitação de pesquisa com parâmetros de consulta no caminho relativo.
public async Task<IActionResult> Search(string query, int page, int pageSize)
{
var options = new DownstreamApiOptions
{
RelativePath = $"search?q={Uri.EscapeDataString(query)}&page={page}&pageSize={pageSize}"
};
var results = await _api.GetForUserAsync<SearchResults>(
"MyApi",
options);
return Ok(results);
}
Você também pode usar o dicionário options.ExtraQueryParameters.
Manipular cabeçalhos de resposta
O exemplo a seguir lê as informações de limite de taxa nos cabeçalhos de resposta.
public async Task<IActionResult> GetWithHeaders()
{
var response = await _api.CallApiAsync<MyData>(
"MyApi",
options =>
{
options.RelativePath = "data";
});
// Access response headers
if (response.Headers.TryGetValues("X-RateLimit-Remaining", out var values))
{
var remaining = values.FirstOrDefault();
_logger.LogInformation("Rate limit remaining: {Remaining}", remaining);
}
return Ok(response.Content);
}
Adquirir tokens somente de aplicativo com IDownstreamApi
Use GetForAppAsync para chamar uma API com permissões de aplicativo em vez de permissões de usuário delegadas.
[ApiController]
[Route("api/[controller]")]
public class DataController : ControllerBase
{
private readonly IDownstreamApi _api;
public DataController(IDownstreamApi api)
{
_api = api;
}
[HttpGet("batch")]
public async Task<ActionResult> GetBatchData()
{
// Call with application permissions
var data = await _api.GetForAppAsync<BatchData>(
"MyApi",
"batch/process");
return Ok(data);
}
}
Use MicrosoftIdentityMessageHandler para integração com HttpClient
MicrosoftIdentityMessageHandler adiciona autenticação Microsoft Entra ao pipeline httpClient automaticamente.
Identificar quando usar MicrosoftIdentityMessageHandler
- Você precisa de controle refinado sobre solicitações HTTP
- Você deseja compor vários manipuladores de mensagens
- Você está integrando-se a um código existente baseado em HttpClient.
- Você precisa acessar o HttpResponseMessage bruto
Configurar sobrecargas do MicrosoftIdentityMessageHandler
MicrosoftIdentityMessageHandler é um DelegatingHandler que adiciona autenticação a solicitações HttpClient. Use esse manipulador quando precisar de recursos completos do HttpClient com aquisição automática de token.
Os métodos de extensão AddMicrosoftIdentityMessageHandler fornecem uma maneira flexível de configurar o HttpClient com autenticação Microsoft Entra ID automática:
- Sem parâmetros: para flexibilidade de configuração por solicitação
- Instância de opções: para objetos de opções pré-configurados
- Delegado de ação: para configuração embutida (mais comum)
- IConfiguration: Para configuração a partir de appsettings.json
Escolha a sobrecarga que melhor se ajusta ao seu cenário e aproveite a autenticação automática para suas chamadas à API downstream.
Usar a sobrecarga sem parâmetros para a configuração por solicitação
Configure as opções de autenticação por solicitação com essa sobrecarga.
services.AddHttpClient("FlexibleClient")
.AddMicrosoftIdentityMessageHandler();
// Later, in a service:
var request = new HttpRequestMessage(HttpMethod.Get, "/api/data")
.WithAuthenticationOptions(options =>
{
options.Scopes.Add("https://api.example.com/.default");
});
var response = await httpClient.SendAsync(request);
Passar uma instância de opções pré-configurada
Use essa sobrecarga quando você tiver um objeto de opções pré-configurado.
var options = new MicrosoftIdentityMessageHandlerOptions
{
Scopes = { "https://graph.microsoft.com/.default" }
};
options.WithAgentIdentity("agent-application-id");
services.AddHttpClient("GraphClient", client =>
{
client.BaseAddress = new Uri("https://graph.microsoft.com");
})
.AddMicrosoftIdentityMessageHandler(options);
Configurar inline com um delegado de ação
Use essa sobrecarga para a configuração embutida, o cenário mais comum.
services.AddHttpClient("MyApiClient", client =>
{
client.BaseAddress = new Uri("https://api.example.com");
})
.AddMicrosoftIdentityMessageHandler(options =>
{
options.Scopes.Add("https://api.example.com/.default");
options.RequestAppToken = true;
});
Carregar configurações de appsettings.json
Use essa sobrecarga para vincular as configurações diretamente ao seu arquivo de configuração.
appsettings.json:
{
"DownstreamApi": {
"Scopes": ["https://api.example.com/.default"]
},
"GraphApi": {
"Scopes": ["https://graph.microsoft.com/.default", "User.Read"]
}
}
Program.cs:
services.AddHttpClient("DownstreamApiClient", client =>
{
client.BaseAddress = new Uri("https://api.example.com");
})
.AddMicrosoftIdentityMessageHandler(
configuration.GetSection("DownstreamApi"),
"DownstreamApi");
services.AddHttpClient("GraphClient", client =>
{
client.BaseAddress = new Uri("https://graph.microsoft.com");
})
.AddMicrosoftIdentityMessageHandler(
configuration.GetSection("GraphApi"),
"GraphApi");
Examinar exemplos de configuração
Esses exemplos demonstram padrões de configuração comuns para o manipulador de mensagens.
Criar um cliente de API Web simples
O exemplo a seguir registra e consome um cliente de API de clima.
// Configure in Program.cs
services.AddHttpClient("WeatherApiClient", client =>
{
client.BaseAddress = new Uri("https://api.weather.com");
})
.AddMicrosoftIdentityMessageHandler(options =>
{
options.Scopes.Add("https://api.weather.com/.default");
});
// Use in a controller or service
public class WeatherService
{
private readonly HttpClient _httpClient;
public WeatherService(IHttpClientFactory factory)
{
_httpClient = factory.CreateClient("WeatherApiClient");
}
public async Task<WeatherForecast> GetForecastAsync(string city)
{
var response = await _httpClient.GetAsync($"/forecast/{city}");
response.EnsureSuccessStatusCode();
return await response.Content.ReadFromJsonAsync<WeatherForecast>();
}
}
Configurar vários clientes de API
O exemplo a seguir registra dois clientes de API separados com escopos e tipos de token diferentes.
// Configure multiple clients in Program.cs
services.AddHttpClient("ApiClient1")
.AddMicrosoftIdentityMessageHandler(options =>
{
options.Scopes.Add("https://api1.example.com/.default");
});
services.AddHttpClient("ApiClient2")
.AddMicrosoftIdentityMessageHandler(options =>
{
options.Scopes.Add("https://api2.example.com/.default");
options.RequestAppToken = true;
});
// Use in a service
public class MultiApiService
{
private readonly HttpClient _client1;
private readonly HttpClient _client2;
public MultiApiService(IHttpClientFactory factory)
{
_client1 = factory.CreateClient("ApiClient1");
_client2 = factory.CreateClient("ApiClient2");
}
public async Task<string> GetFromBothApisAsync()
{
var data1 = await _client1.GetStringAsync("/data");
var data2 = await _client2.GetStringAsync("/data");
return $"{data1} | {data2}";
}
}
Carregar opções complexas de appsettings.json
O exemplo a seguir associa várias configurações de API de uma seção de configuração compartilhada.
appsettings.json:
{
"DownstreamApis": {
"CustomerApi": {
"Scopes": ["api://customer-api/.default"]
},
"OrderApi": {
"Scopes": ["api://order-api/.default"]
},
"InventoryApi": {
"Scopes": ["api://inventory-api/.default"]
}
}
}
Program.cs:
var downstreamApis = configuration.GetSection("DownstreamApis");
services.AddHttpClient("CustomerApiClient", client =>
{
client.BaseAddress = new Uri("https://customer-api.example.com");
})
.AddMicrosoftIdentityMessageHandler(
downstreamApis.GetSection("CustomerApi"),
"CustomerApi");
services.AddHttpClient("OrderApiClient", client =>
{
client.BaseAddress = new Uri("https://order-api.example.com");
})
.AddMicrosoftIdentityMessageHandler(
downstreamApis.GetSection("OrderApi"),
"OrderApi");
services.AddHttpClient("InventoryApiClient", client =>
{
client.BaseAddress = new Uri("https://inventory-api.example.com");
})
.AddMicrosoftIdentityMessageHandler(
downstreamApis.GetSection("InventoryApi"),
"InventoryApi");
Opções de substituição por solicitação
Você pode substituir as opções padrão por solicitação usando o WithAuthenticationOptions método de extensão.
// Configure client with default options
services.AddHttpClient("ApiClient")
.AddMicrosoftIdentityMessageHandler(options =>
{
options.Scopes.Add("https://api.example.com/.default");
});
// Override for specific requests
public class MyService
{
private readonly HttpClient _httpClient;
public MyService(IHttpClientFactory factory)
{
_httpClient = factory.CreateClient("ApiClient");
}
public async Task<string> GetSensitiveDataAsync()
{
// Override scopes for this specific request
var request = new HttpRequestMessage(HttpMethod.Get, "/api/sensitive")
.WithAuthenticationOptions(options =>
{
options.Scopes.Clear();
options.Scopes.Add("https://api.example.com/sensitive.read");
options.RequestAppToken = true;
});
var response = await _httpClient.SendAsync(request);
response.EnsureSuccessStatusCode();
return await response.Content.ReadAsStringAsync();
}
}
Implementar cenários avançados
As seções a seguir abrangem a identidade do agente, a composição do manipulador e o tratamento automático de desafios.
Configurar a identidade do agente
Use a identidade do agente quando seu aplicativo precisar agir em nome de outro aplicativo:
services.AddHttpClient("AgentClient")
.AddMicrosoftIdentityMessageHandler(options =>
{
options.Scopes.Add("https://graph.microsoft.com/.default");
options.WithAgentIdentity("agent-application-id");
options.RequestAppToken = true;
});
Compor com outros manipuladores
Encadear vários manipuladores no pipeline para adicionar log, novas tentativas ou outras questões transversais.
services.AddHttpClient("ApiClient")
.AddMicrosoftIdentityMessageHandler(options =>
{
options.Scopes.Add("https://api.example.com/.default");
})
.AddHttpMessageHandler<LoggingHandler>()
.AddHttpMessageHandler<RetryHandler>();
Gerenciar desafios de autenticação WWW
O manipulador processa automaticamente desafios WWW-Authenticate para cenários de Acesso Condicional.
// No additional code needed - automatic handling
services.AddHttpClient("ProtectedApiClient")
.AddMicrosoftIdentityMessageHandler(options =>
{
options.Scopes.Add("https://api.example.com/.default");
});
// The handler will automatically:
// 1. Detect 401 responses with WWW-Authenticate challenges
// 2. Extract required claims from the challenge
// 3. Acquire a new token with the additional claims
// 4. Retry the request with the new token
Gerenciar erros
O exemplo a seguir captura a autenticação e os erros HTTP separadamente ao chamar uma API por meio do manipulador de mensagens.
public class MyService
{
private readonly HttpClient _httpClient;
private readonly ILogger<MyService> _logger;
public MyService(IHttpClientFactory factory, ILogger<MyService> logger)
{
_httpClient = factory.CreateClient("ApiClient");
_logger = logger;
}
public async Task<string> GetDataWithErrorHandlingAsync()
{
try
{
var response = await _httpClient.GetAsync("/api/data");
response.EnsureSuccessStatusCode();
return await response.Content.ReadAsStringAsync();
}
catch (MicrosoftIdentityAuthenticationException authEx)
{
_logger.LogError(authEx, "Authentication failed: {Message}", authEx.Message);
throw;
}
catch (HttpRequestException httpEx)
{
_logger.LogError(httpEx, "HTTP request failed: {Message}", httpEx.Message);
throw;
}
}
}
Usar IAuthorizationHeaderProvider para controle máximo
IAuthorizationHeaderProvider fornece acesso direto aos cabeçalhos de autorização para controle completo sobre solicitações HTTP.
Identificar quando usar IAuthorizationHeaderProvider
- Você precisa de controle total sobre a construção da solicitação HTTP
- Você está integrando com APIs HTTP não padrão
- Você precisa usar HttpClient sem DI
- Você está criando abstrações HTTP personalizadas
Executar operações básicas
O controlador a seguir recupera um cabeçalho de autorização e o anexa a uma solicitação HTTP manual.
using Microsoft.Identity.Abstractions;
[Authorize]
public class CustomApiController : Controller
{
private readonly IAuthorizationHeaderProvider _headerProvider;
private readonly ILogger<CustomApiController> _logger;
public CustomApiController(
IAuthorizationHeaderProvider headerProvider,
ILogger<CustomApiController> logger)
{
_headerProvider = headerProvider;
_logger = logger;
}
public async Task<IActionResult> GetData()
{
// Get authorization header (includes "Bearer " prefix)
var authHeader = await _headerProvider.CreateAuthorizationHeaderForUserAsync(
scopes: new[] { "api://my-api/read" });
using var client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", authHeader);
client.DefaultRequestHeaders.Add("X-Custom-Header", "MyValue");
var response = await client.GetAsync("https://api.example.com/data");
response.EnsureSuccessStatusCode();
var content = await response.Content.ReadAsStringAsync();
return Content(content, "application/json");
}
}
Adquirir tokens exclusivos para aplicativos
Use CreateAuthorizationHeaderForAppAsync para obter um token somente de aplicativo para cenários de plano de fundo ou daemon.
public async Task<IActionResult> GetBackgroundData()
{
// Get app-only authorization header
var authHeader = await _headerProvider.CreateAuthorizationHeaderForAppAsync(
scopes: new[] { "api://my-api/.default" });
using var client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", authHeader);
var response = await client.GetAsync("https://api.example.com/background");
var data = await response.Content.ReadFromJsonAsync<BackgroundData>();
return Ok(data);
}
Integrar com bibliotecas HTTP personalizadas
O exemplo a seguir usa IAuthorizationHeaderProvider com uma biblioteca HTTP de terceiros.
public async Task<IActionResult> CallWithRestSharp()
{
var authHeader = await _headerProvider.CreateAuthorizationHeaderForUserAsync(
scopes: new[] { "api://my-api/read" });
// Example with RestSharp
var client = new RestClient("https://api.example.com");
var request = new RestRequest("data", Method.Get);
request.AddHeader("Authorization", authHeader);
var response = await client.ExecuteAsync<MyData>(request);
return Ok(response.Data);
}
Configurar opções avançadas
O exemplo a seguir cria um AuthorizationHeaderProviderOptions objeto com escopos explícitos e configurações de aquisição de token.
public async Task<IActionResult> GetDataWithOptions()
{
var options = new AuthorizationHeaderProviderOptions
{
Scopes = new[] { "api://my-api/read" },
RequestAppToken = false,
AcquireTokenOptions = new AcquireTokenOptions
{
AuthenticationOptionsName = JwtBearerDefaults.AuthenticationScheme,
ForceRefresh = false,
Claims = null
}
};
var authHeader = await _headerProvider.CreateAuthorizationHeaderAsync(options);
using var client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", authHeader);
var response = await client.GetAsync("https://api.example.com/data");
var data = await response.Content.ReadFromJsonAsync<MyData>();
return Ok(data);
}
Comparar abordagens
Use os critérios a seguir para selecionar a melhor abordagem para seu cenário.
Use IDownstreamApi quando:
Chamando APIs REST padrão
Deseja uma abordagem baseada em configuração
Precisa de serialização/desserialização automática
Deseja código mínimo
Seguindo os padrões de Microsoft.Identity.Web
Exemplo:
var product = await _api.GetForUserAsync<Product>("MyApi", "products/123");
Use MicrosoftIdentityMessageHandler quando:
Precisa de recursos completos do HttpClient
Deseja compor vários manipuladores
Usando padrões de HttpClientFactory
Precisa de acesso ao HttpResponseMessage
Integração com o código HttpClient existente
Exemplo:
var response = await _httpClient.GetAsync("api/products/123");
var product = await response.Content.ReadFromJsonAsync<Product>();
Use IAuthorizationHeaderProvider quando:
Precisa de controle total sobre solicitações HTTP
Usando bibliotecas HTTP personalizadas
Criando abstrações personalizadas
Não é possível usar HttpClientFactory
Precisa construir solicitações manualmente
Exemplo:
var authHeader = await _headerProvider.CreateAuthorizationHeaderForUserAsync(scopes);
client.DefaultRequestHeaders.Add("Authorization", authHeader);
Gerenciar erros
As seções a seguir mostram padrões de tratamento de erros para cada abordagem.
Manipular os erros do IDownstreamApi
O exemplo a seguir captura desafios de consentimento, erros de status HTTP e exceções gerais.
try
{
var data = await _api.GetForUserAsync<MyData>("MyApi", "data");
}
catch (MicrosoftIdentityWebChallengeUserException ex)
{
// User needs to consent
_logger.LogWarning(ex, "Consent required for scopes: {Scopes}", string.Join(", ", ex.Scopes));
throw; // Let ASP.NET Core handle consent flow
}
catch (HttpRequestException ex) when (ex.StatusCode == System.Net.HttpStatusCode.NotFound)
{
return NotFound("Resource not found");
}
catch (HttpRequestException ex) when (ex.StatusCode == System.Net.HttpStatusCode.Unauthorized)
{
return Unauthorized("API returned 401");
}
catch (Exception ex)
{
_logger.LogError(ex, "API call failed");
return StatusCode(500, "An error occurred");
}
Manipulação de erros do MicrosoftIdentityMessageHandler
O exemplo a seguir inspeciona o código de status de resposta e registra informações detalhadas de erro.
try
{
var response = await _httpClient.GetAsync("api/data");
if (!response.IsSuccessStatusCode)
{
var error = await response.Content.ReadAsStringAsync();
_logger.LogError("API returned {StatusCode}: {Error}", response.StatusCode, error);
return StatusCode((int)response.StatusCode, error);
}
var data = await response.Content.ReadFromJsonAsync<MyData>();
return Ok(data);
}
catch (HttpRequestException ex)
{
_logger.LogError(ex, "HTTP request failed");
return StatusCode(500, "Failed to call API");
}
Seguir as práticas recomendadas
Aplique esses padrões para criar integrações de API confiáveis e manteneveis.
1. Configurar valores de tempo limite
Defina tempos limite explícitos para impedir que as solicitações sejam suspensas indefinidamente.
builder.Services.AddDownstreamApi("MyApi", options =>
{
options.BaseUrl = "https://api.example.com";
options.HttpClientName = "MyApi";
});
builder.Services.AddHttpClient("MyApi", client =>
{
client.Timeout = TimeSpan.FromSeconds(30);
});
2. Usar clientes tipados
Envolver IDownstreamApi em uma interface de cliente tipada para melhorar a testabilidade e o encapsulamento.
public interface IProductApiClient
{
Task<List<Product>> GetProductsAsync();
Task<Product> GetProductAsync(int id);
Task<Product> CreateProductAsync(Product product);
}
public class ProductApiClient : IProductApiClient
{
private readonly IDownstreamApi _api;
public ProductApiClient(IDownstreamApi api)
{
_api = api;
}
public Task<List<Product>> GetProductsAsync() =>
_api.GetForUserAsync<List<Product>>("MyApi", "products");
public Task<Product> GetProductAsync(int id) =>
_api.GetForUserAsync<Product>("MyApi", $"products/{id}");
public Task<Product> CreateProductAsync(Product product) =>
_api.PostForUserAsync<Product, Product>("MyApi", "products", product);
}
// Register
builder.Services.AddScoped<IProductApiClient, ProductApiClient>();
3. Detalhes da solicitação de log
Acompanhe a duração da chamada à API e os resultados para identificar gargalos de desempenho.
public async Task<IActionResult> GetDataWithLogging()
{
_logger.LogInformation("Calling MyApi for data");
var stopwatch = Stopwatch.StartNew();
try
{
var data = await _api.GetForUserAsync<MyData>("MyApi", "data");
stopwatch.Stop();
_logger.LogInformation("API call succeeded in {ElapsedMs}ms", stopwatch.ElapsedMilliseconds);
return Ok(data);
}
catch (Exception ex)
{
stopwatch.Stop();
_logger.LogError(ex, "API call failed after {ElapsedMs}ms", stopwatch.ElapsedMilliseconds);
throw;
}
}
Implementar o suporte ao OWIN
Use a integração do OWIN quando o seu aplicativo estiver sendo executado no pipeline clássico do ASP.NET em vez do ASP.NET Core.
using Microsoft.Identity.Web;
using Microsoft.Identity.Web.OWIN;
using Owin;
public class Startup
{
public void Configuration(IAppBuilder app)
{
OwinTokenAcquirerFactory factory = TokenAcquirerFactory.GetDefaultInstance<OwinTokenAcquirerFactory>();
app.AddMicrosoftIdentityWebApp(factory);
factory.Services
.AddDownstreamApis(factory.Configuration.GetSection("DownstreamAPI"))
.AddInMemoryTokenCaches();
factory.Build();
}
}
Explorar o conteúdo relacionado
Próximas etapas: examine a documentação principal para árvore de decisão e comparação de todas as abordagens.