简体   繁体   中英

How can I properly send email (with error) from catch ()?

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);

    }
}

Email

private static async Task Email(Exception e)
{
    try
    {
        MailMessage message = new MailMessage();
        SmtpClient smtp = new SmtpClient();
        message.From = new MailAddress("mail@mail.com");
        message.To.Add(new MailAddress("mail@mail.com"));
        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);
    }
}

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);
}

Returning default(T) 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.
There should be a more explicit way for the caller 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();

        var responseStream = await response.Content.ReadAsStreamAsync();
        var responseObject = await JsonSerializer.DeserializeAsync<T>(responseStream);

        result.Output = responseObject; // Added this
    }
    catch (Exception e) {
        await Email(e);
        result.IsSuccess = false; // Added this
    }

    return result; // Added this
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM