Класс Generic Wrapper для методов HTTPClient

Я пытаюсь использовать HttpClient для вызовов API из другого домена, и для этой цели я создал следующий класс обслуживания после некоторых исследований. Это платформа 4.7.2, а не базовая система .NET. Я создал для этого библиотечный класс со следующими классами. Пожалуйста, дайте мне ваши ценные предложения по изменениям или улучшениям

Файл IRequestService.cs

public interface IRequestService
    {
        Task<TResult> GetAsync<TResult>(HttpClientNS client, string url);
        Task<string> GetStringAsync(HttpClientNS client, string url);
        Task<TResult> PostAsync<TRequest, TResult>(HttpClientNS client, TRequest t, string url);
        HttpClientNS GetClient();
    }

RequestService.cs

public class RequestService : IRequestService
    {
    private readonly string _hostWebApiUrl;
    private readonly string _apiAuthKey;

    public RequestService()
    {
        _hostWebApiUrl = Config.AppSettings["TestWebApiURL"];
        _apiAuthKey = Config.AppSettings["ApiKey"];
    }

    public RequestService(string hostWebApiUrl, string apiAuthKey)
    {
        _hostWebApiUrl = hostWebApiUrl;
        _apiAuthKey = apiAuthKey;
    }
    public HttpClientNS GetClient()
    {
        string _baseAddress = _hostWebApiUrl;
        var client = new HttpClientNS
        {
            BaseAddress = new Uri(_baseAddress)
        };

        client.DefaultRequestHeaders.Add("AuthApiKey", _apiAuthKey);
        return client;
    }

    public async Task<TResult> GetAsync<TResult>(HttpClientNS client, string url)
    {
        client.Timeout = TimeSpan.FromSeconds(30);
        var result = default(TResult);
        try
        {
            var response = await client.GetAsync(url);
            response.EnsureSuccessStatusCode();
            //var jsonString = await response.Content.ReadAsStringAsync();
            //var result = JsonConvert.DeserializeObject<TResult>(jsonString);


            await response.Content.ReadAsStringAsync().ContinueWith((Task<string> x) =>
            {
                if (x.IsFaulted)
                    throw x.Exception;

                result = JsonConvert.DeserializeObject<TResult>(x.Result);
            });



        }

        catch (Exception ex)
        {

        }
        return result;
    }

    public async Task<string> GetStringAsync(HttpClientNS client, string url)
    {
        var httpRequest = new HttpRequestMessage(new HttpMethod("GET"), url);
        var response = client.SendAsync(httpRequest).Result;
        var jsonString = await response.Content.ReadAsStringAsync();
        return jsonString;
    }


    public async Task<TResult> PostAsync<TRequest, TResult>(HttpClientNS client, TRequest t, string url)
    {
        var result = default(TResult);
        var json = JsonConvert.SerializeObject
        HttpContent httpContent = new StringContent(json);
        httpContent.Headers.ContentType = new MediaTypeHeaderValue("application/json");

        //response.EnsureSuccessStatusCode();
        //var jsonString = await response.Content.ReadAsStringAsync();
        //var result = JsonConvert.DeserializeObject<TResult>(jsonString);
        //return result;  


        var response = await client.PostAsync(url, httpContent).ConfigureAwait(false);

            response.EnsureSuccessStatusCode();

            await response.Content.ReadAsStringAsync().ContinueWith((Task<string> x) =>
            {
                if (x.IsFaulted)
                    throw x.Exception;

                result = JsonConvert.DeserializeObject<TResult>(x.Result);

            });
        

        return result;

    }

}

Я вызываю этот класс-оболочку, содержащий следующие общие методы:

public class TestApiClient
    {

        private IRequestService RequestService;
        private readonly string _apiUrl;
        public TestApiClient(IRequestService request)
        {
            RequestService = new RequestService();
            _apiUrl = "api/TestCustomer";
        }       

        public async Task<bool> IsCustomerVendor(int vendorId)
        {

            var url = string.Format(_apiUrl + "/IsCUstomerVendor?vendorId={0}", vendorId);
            var client = RequestService.GetClient();
            var result = await RequestService.GetAsync<bool>(client, url);

            return result;
        }



        public async Task<bool> IsCUstomerDataInvalid(int productId, int financeCompanyId, string balloonDealerState)
        {
             

            var url = _apiUrl + "/IsCUstomerDataInvalid";
            var content = new { CustomerId = customerId, CompanyId = companyId, DealerState = DealerState };
            //var result = _webClientHelper.PostContent<bool>(url, content);
            var client = RequestService.GetClient();
            var result = await RequestService.PostAsync<Object,bool>(client, content, url);

            return result;
        }

    }

1 ответ
1

Быстрые замечания:

  • Не делайте этого:

     public RequestService()
     {
         _hostWebApiUrl = Config.AppSettings["TestWebApiURL"];
         _apiAuthKey = Config.AppSettings["ApiKey"];
     }
    
     public RequestService(string hostWebApiUrl, string apiAuthKey)
     {
         _hostWebApiUrl = hostWebApiUrl;
         _apiAuthKey = apiAuthKey;
     }
    

    Вместо этого передайте полученные значения конструктору, который может принимать эти значения:

     public RequestService()
             : this(Config.AppSettings["TestWebApiURL"],
                     Config.AppSettings["ApiKey"])
     {
     }
    

    Я бы также сконцентрировал весь код, который извлекает значения из Config.AppSettings в одном классе вместо того, чтобы засорять мой код вызовами Config.AppSettings.

  • Не согласовываться с именами – это хорошая идея? "AuthApiKey" против _apiAuthKey меня, например, несколько сбивает с толку. (И тогда ключ настройки приложения "ApiKey", еще одно имя.)

  • Плохая идея – ловить исключение и ничего не делать с ним. Надеюсь увидеть хоть какой-то лог.

  • Почему бы не использовать Get собственностью HttpMethod?

  • GetStringAsync не обнаруживает ошибок или исключений. Что если что-то пойдет не так? То же самое верно и для многих других ваших методов, которые подключаются к API. Я бы предоставил способ регистрировать все эти вещи вместо того, чтобы ожидать, что все пойдет хорошо; поиск проблем, когда дела идут не так, как планировалось, и обнаружение отсутствия регистрации очень расстраивает.

    Я бы пошел еще дальше и предлагал ведение журнала для всех видов вещей: какой метод вызывается с каким значением и т. Д. Таким образом вы можете увидеть произошедший поток и, вероятно, легче определить, почему что-то пошло не так (потому что иногда просто регистрируется ошибка недостаточна).

  • Поэтому у вас есть IRequestService request (плохая репутация! это не “запрос”) в качестве параметра TestApiClient, еще не пользуетесь?

  • Почему ты используешь старую string.Format вместо строковая интерполяция?

  • “U” в IsCUstomerDataInvalid (и имя метода, и URL-адрес, используемый внутри этого метода) должны быть буквой «U»? Или это опечатка?

  • Спасибо BcdotWeb за рекомендации.

    – chiru1983

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *