I'm trying to create a class that extends httpclient but still is abstract.
public abstract class Repository : HttpClient
{
public override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
//retry logic here
var response = await base.SendAsync(request, cancellationToken);
while (!IsValid(response))
{
Attempts++;
response = await Retry(request, cancellationToken);
}
Attempts = 0;
return response;
}
public int Attempts { get; set; }
public abstract bool IsValid(HttpResponseMessage response);
public abstract Task<HttpResponseMessage> Retry(HttpRequestMessage request, CancellationToken cancellationToken);
public abstract Type GetPageForUri(Uri uri);
public abstract Task<object> GetItems(Uri uri);
}
but when a subclass calls getStringAsync it does not call SendAsync in Repository
public class EmailClient : Repository
{
public override bool IsValid(HttpResponseMessage response)
{
return response.IsSuccessStatusCode;
}
public override Task<HttpResponseMessage> Retry(HttpRequestMessage request, CancellationToken cancellationToken)
{
return base.SendAsync(request, cancellationToken);
}
public override Type GetPageForUri(Uri uri)
{
return typeof(EmailPage);
}
public override async Task<object> GetItems(Uri uri)
{
var emails = await GetStringAsync(uri);
return emails;
}
}
How what am I doing wrong? should I make a HttpClientHandler and include that with HttpClient? Ive tried to read about virtual if that makes any diffrent. but i dont get it why it does not get called. Can anyone help me?
HttpClient is a thin wrapper around an HttpMessageHandler
implementation (typically HttpClientHandler
, which properties for features supported across most runtime implementations)
There's actually an HttpMessageHandler
base class intended for decorators like your retry scenario, DelegatingHandler
, which you could implement like this:
Something like:
public class RetryMessageHandler : DelegatingHandler
{
readonly int retryCount;
public RetryMessageHandler(int retryCount)
: this(new HttpClientHandler(), retryCount)
{
}
public RetryMessageHandler(HttpMessageHandler innerHandler, int retryCount)
: base(innerHandler)
{
this.retryCount = retryCount;
}
public override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
HttpResponseMessage response = null;
for (int i = 0; i<=retryCount; i++)
{
response = await base.SendAsync(request, cancellationToken);
if (response.IsSuccessStatusCode)
{
return response;
}
}
return response;
}
}
Which you would then use like this:
HttpClient httpClient = HttpClientFactory.CreatePipeline(new HttpClientHandler(),
new [] { new RetryMessageHandler(3) });
var response = await httpClient.SendAsync(request);
Additionally, I'd recommend your EmailClient
wraps/depends on HttpClient, rather than extending it. (Google "Composition vs Inheritance" for more information on why)