0
maharatha created
Prerequisites
Please answer the following questions before submitting an issue. YOU MAY DELETE THE PREREQUISITES SECTION.
- What is your product version? v10.2.0
- What is your product type (Angular or MVC)? Angular
- What is product framework type (.net framework or .net core)? .net core
I am trying to consume a web api and below is what I have implemented :
Startup.cs
services.AddTransient<HtgAuthenticationDelegatingHandler>();
services.AddHttpClient<IMyServiceManager,MyServiceManager>(client =>
{
client.BaseAddress = new Uri(_appConfiguration["cccccccc"]);
client.DefaultRequestHeaders.Add("User-Agent", "myPortal");
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
client.DefaultRequestHeaders.CacheControl = CacheControlHeaderValue.Parse("no-cache");
})
//.AddPolicyHandler(GetRetryPolicy())
.AddHttpMessageHandler<MyAuthenticationDelegatingHandler>(); // This handler is on the inside, closest to the request.
public class MyAuthenticationDelegatingHandler : DelegatingHandler
{
private readonly TokenManager _tokenManager;
private readonly ICacheManager _cacheManager;
public HtgAuthenticationDelegatingHandler(TokenManager tokenManager, ICacheManager cacheManager)
{
_tokenManager = tokenManager;
_cacheManager = cacheManager;
}
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
var htgtoken = await _tokenManager.GetMyToken();
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", htgtoken);
try
{
var response = await base.SendAsync(request, cancellationToken);
if (response.StatusCode != HttpStatusCode.Unauthorized &&
response.StatusCode != HttpStatusCode.Forbidden)
return response;
request.Headers.Authorization =
new AuthenticationHeaderValue("Bearer", await _tokenManager.GetMyToken());
response = await base.SendAsync(request, cancellationToken);
return response;
}
catch (Exception e)
{
string exception = e.Message;
return new HttpResponseMessage()
{
StatusCode = HttpStatusCode.BadRequest,
ReasonPhrase = e.Message
};
}
}
}
public class TokenManager : ITransientDependency
{
private readonly IAmazonSecretsManager _secretManager;
public IConfiguration Configuration { get; }
private readonly IConfigurationRoot _appConfiguration;
private readonly ICacheManager _cacheManager;
public TokenManager(IAmazonSecretsManager secretManager, IConfiguration configuration,
IAppConfigurationAccessor configurationAccessor, ICacheManager cacheManager)
{
_secretManager = secretManager;
Configuration = configuration;
_cacheManager = cacheManager;
_appConfiguration = configurationAccessor.Configuration;
}
public async Task<string> GetHTGToken()
{
return await UpdateHtgTokenCacheAsync();
}
public static bool IsValidJwtToken(string accesstoken)
{
var tokenExpiryDate = JWTTokenExpiryTime(accesstoken);
return tokenExpiryDate > DateTime.UtcNow;
}
public static DateTime JWTTokenExpiryTime(string token)
{
var handler = new JwtSecurityTokenHandler();
if (!(handler.ReadToken(token) is JwtSecurityToken tokenread)) return DateTime.MinValue;
return tokenread.ValidTo;
}
private async Task<string> UpdateMyTokenCacheAsync()
{
//Get it from the app settings
var request = new HttpRequestMessage(HttpMethod.Post, _appConfiguration["Api:My:TokenEndPoint"]);
var clientId = xxxx;
var secret = yyyy;
request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
request.Headers.CacheControl = CacheControlHeaderValue.Parse("no-cache");
request.Headers.Authorization = new AuthenticationHeaderValue("Basic",
Convert.ToBase64String(System.Text.Encoding.UTF8.GetBytes($"{clientId}:{secret}")));
request.Content = new StringContent($"grant_type=client_credentials&scope=manage:all",
System.Text.Encoding.UTF8, "application/x-www-form-urlencoded");
var client = new HttpClient();
var response = await client.SendAsync(request);
var body = await response.Content.ReadAsStringAsync();
var token = JObject.Parse(body)["access_token"]?.ToString();
var tokencache = _cacheManager.GetCache("tokencache");
try
{
await tokencache.SetAsync(new KeyValuePair<string, object>[]
{
new KeyValuePair<string, object>("mytoken", token),
}, null, JWTTokenExpiryTime(token));
}
catch (Exception e)
{
Console.WriteLine(e);
throw;
}
return token;
}
}
public class MyServiceManager : MyDomainServiceBase, IMyServiceManager
{
private readonly HttpClient _httpClient;
public MyServiceManager(HttpClient httpClient)
{
_httpClient = httpClient;
}
public async Task<HttpResponseMessage> GetStates()
{
try
{
var response = await _httpClient.GetAsync(
"state?additionalProp1=&additionalProp2=&additionalProp3=");
return response;
}
catch (Exception ex)
{
return new HttpResponseMessage()
{
StatusCode = HttpStatusCode.BadRequest,
ReasonPhrase = ex.Message
};
}
}
}
<br> I am basically getting the token from an authentication server , storing that token and getting the token again if it has expired.
Eveyrthing works fine for the first time but my http client is getting disposed on the second time.
Any idea?
1 Answer(s)
-
0
Hi,
I couldn't understand why it is disposed but could you try using HttpClientFactory, it is the suggested way by ASP.NET Core, see https://docs.microsoft.com/en-us/dotnet/architecture/microservices/implement-resilient-applications/use-httpclientfactory-to-implement-resilient-http-requests