I consume an API and now I want to handle possible errors in catch
section. What I want to do now is to send email to given user when error is catched. My Email
method works fine and sends mails properly. CallAPI
method also works fine but when I add Email
method to catch
section then CallAPI
method get highlighted with info that 'not all code paths return a value'. I can't return anything in catch
except for sending an email. So how should I properly send email from catch
?
CallAPI
private static async Task<T> CallAPI<T>(string endpoint, string accessToken)
{
try
{
var request = new HttpRequestMessage(HttpMethod.Get,
new Uri(ApiUri, endpoint));
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
var _httpClient = new HttpClient();
var response = await _httpClient.SendAsync(request);
response.EnsureSuccessStatusCode();
var responseStream = await response.Content.ReadAsStreamAsync();
var responseObject = await JsonSerializer.DeserializeAsync<T>(responseStream);
return responseObject;
}
catch (Exception e)
{
await Email(e);
}
}
private static async Task Email(Exception e)
{
try
{
MailMessage message = new MailMessage();
SmtpClient smtp = new SmtpClient();
message.From = new MailAddress("[email protected]");
message.To.Add(new MailAddress("[email protected]"));
message.Subject = "Test test";
message.IsBodyHtml = true;
message.Body = e.ToString();
smtp.Port = 25;
smtp.Host = "mail.yyy.com";
await smtp.SendMailAsync(message);
}
catch (Exception ex) {
Console.WriteLine(ex.Message);
}
}
CodePudding user response:
The above answer might work for reference types but I don't suggest it for value types.
Say, if T
is an int
, default(T)
results in 0
, which might actually be an acceptable response.
Also, the caller must have a more explicit way to distinguish if the call went in error or not.
With a custom object, such as ResponseBase<T>
, you can easily detect that by a simple response.IsSuccess
call.
public class ResponseBase<T> {
public bool IsSuccess { get; set; } = true;
public T Output { get; set; }
}
private static async Task<ResponseBase<T>> CallAPI<T>(string endpoint, string accessToken) {
var result = new ResponseBase<T>(); // Added this
try {
var request = new HttpRequestMessage(HttpMethod.Get,
new Uri(ApiUri, endpoint));
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
var _httpClient = new HttpClient();
var response = await _httpClient.SendAsync(request);
response.EnsureSuccessStatusCode(); // Added this
var responseStream = await response.Content.ReadAsStreamAsync();
var responseObject = await JsonSerializer.DeserializeAsync<T>(responseStream);
result.Output = responseObject;
}
catch (Exception e) {
await Email(e);
result.IsSuccess = false; // Added this
}
return result; // Added this
}
CodePudding user response:
You didn't set the return result from your catch scope that you might return
generics type from Task<T>
One way you can try to return default(T)
catch (Exception e)
{
await Email(e);
return default(T);
}