I've got an OData connected service for V4 generated through a metadata file.
Since the service requires OAuth2, I have to obtain the token asynchronously from a web server before sent any message.
In order to achieve that, I've configured the service applying DI pattern using Microsoft.OData.Extensions.Client
:
services.AddODataClient(nameof(ApiServices))
.ConfigureODataClient(config =>
{
config.AddAndUpdateResponsePreference = DataServiceResponsePreference.IncludeContent;
config.Format.UseJson();
config.MergeOption = MergeOption.OverwriteChanges;
})
.AddHttpClient()
.AddHttpMessageHandler<BearerTokenAuthHandler>()
.Services
.AddTransient<BearerTokenAuthHandler>()
.AddTransient<ApiServices>()
.AddTransient<IServiceAuthentication, ApiServices>();
HttpMessageHandler
is:
internal partial class BearerTokenAuthHandler : DelegatingHandler
{
IAccessTokenProvider _tokenClient;
public BearerTokenAuthHandler(IServiceAuthentication service)
{
_tokenClient = service.AuthenticationProvider.AccessTokenProvider;
}
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
string url = string.Format(EntraApps.BcAuthorizationUrl, EntraApps.TenantId);
string token = await _tokenClient.GetAuthorizationTokenAsync(new Uri(url), null, cancellationToken);
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", token);
HttpRequestOptionsKey<string> option = new HttpRequestOptionsKey<string>("tenant");
request.Options.Set(option, EntraApps.BcTenantId);
return await base.SendAsync(request, cancellationToken);
}
}
Problem is: BearerTokenAuthHandler
is not instantiated when after building any query, ExecuteAsync()
is executed. So, no authorisation happens, and no data is retrieved and a DataServiceClientException
is thrown ("Unauthorised / The credentials provided are incorrect"):
ApiServices service = ServiceProvider.GetService<ApiServices>();
IEnumerable<Company> companies = await service .Companies.ExecuteAsync();
However, if I build same message using the query building and HttpClientFactory
from the service instance, there's no problem. Authorization is Ok and data is retrieved from the server:
ApiServices service = ServiceProvider.GetService<ApiServices>();
HttpClient client = service.HttpClientFactory.CreateClient(nameof(ApiServices));
Uri uri = service.Companies.RequestUri;
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, uri);
HttpResponseMessage response = await client.SendAsync(request);
Is something wrong with my code? It seems that OData ExecuteAsync()
doesn't use HttpClientFactory
after all.
SendingRequest2
event is of no use, since it's synchronous.
Any suggestion will be appreciated.