Я пытаюсь использовать 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 ответ
Быстрые замечания:
Не делайте этого:
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