HttpClient Как поймать каждый ответ в одном месте - PullRequest
0 голосов
/ 10 марта 2020

Я работаю над приложением Xamarin.Forms, связанным с Web Api 2 Api, и все запросы и ответы работают с HttClient. Это мой код:

класс для всех моих запросов и определение HttpClient

  public class DataStore : IDataStore<object>
    {
        HttpClient client;

        public DataStore()
        {
            client = new HttpClient()
            {
                BaseAddress = new Uri($"{App.Uri}")
            };

        }

Пример одного из моих запросов:

   public async Task<User> GetProfileSetup()
        {
            try
            {
                if (CrossConnectivity.Current.IsConnected)
                {
                    string token = DependencyService.Get<ISharedFunctions>().GetAccessToken();

                    client.DefaultRequestHeaders.Clear();
                    client.DefaultRequestHeaders.Add("Accept", "application/json");
                    client.DefaultRequestHeaders.Add("Authorization", "Bearer " + token);

                    var response = await client.GetAsync(@"api/User/GetProfilSetup");
                    if (response.IsSuccessStatusCode)
                    {
                        string jsonMessage;
                        using (Stream responseStream = await response.Content.ReadAsStreamAsync())
                        {
                            jsonMessage = new StreamReader(responseStream).ReadToEnd();
                        }
                        User user = JsonConvert.DeserializeObject<User>(jsonMessage);


                        return user;
                    }
                    else
                    {
                        var m = response.Content.ToString();
                        return null;
                    }

                }
                else
                {
                    return null;
                }
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex);
                string error = ex.Message;
                return null;

            }
        }

Моя идея проверить каждый ответ (код статуса ответа) в одном месте. Мне это нужно для ошибок оповещения, для refre sh token et c. Есть ли возможный путь к этому? Я хочу контролировать каждый запрос / ответ.

Ответы [ 2 ]

1 голос
/ 16 марта 2020

если у кого-то есть проблемы с этим, просто нужно реализовать собственный обработчик, который унаследует форму DelegatingHandler. Пример моего кода:

  public class StatusCodeHandler : DelegatingHandler
    {
        public StatusCodeHandler(HttpMessageHandler innerHandler) : base(innerHandler) { }
        public GetStatusCode GetStatusCode = new GetStatusCode();
        protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
        {
            HttpResponseMessage response = null;
                response = await base.SendAsync(request, cancellationToken);
                if (response.IsSuccessStatusCode)
                {
                    return response;
                }
            else
            { 
                var status_code = (int)response.StatusCode;
                GetStatusCode.GetResponseCode(status_code);
            }
            return response;
        }

     }
0 голосов
/ 10 марта 2020

Это не относится к ксамарину, это вопрос абстракции в OOP. Вы можете и должны абстрагировать HttpClient и его методы, чтобы удалить весь шаблон.

Пример - GetAsync<T>(url) проверит соединение, запрос формы добавляет необходимые заголовки, ожидает ответа, проверяет статус ответа, читает ответ и, наконец, возвращает десериализованный ответ. Таким образом, если вы хотите добавить слой кэширования, это проще. Basi c OOP.

Абстрагирование вашего кода:

public async Task<T> GetAsync(string url)
{
    try
    {
        if (!CrossConnectivity.Current.IsConnected)
        {
            // throw custom exception?
            new NoNetworkException();
        }
        var token = DependencyService.Get<ISharedFunctions>().GetAccessToken();
        client.DefaultRequestHeaders.Clear();
        client.DefaultRequestHeaders.Add("Accept", "application/json");
        client.DefaultRequestHeaders.Add("Authorization", "Bearer " + token);
        var response = await client.GetAsync(url);
        if (!response.IsSuccessStatusCode)
        {
            // read response and throw for logging?
            new InvaidResponseException();// custom exceptions makes it easier for catching
        }
        using (Stream responseStream = await response.Content.ReadAsStreamAsync())
        {
            // there should be an async overload to read too
            var jsonMessage = new StreamReader(responseStream).ReadToEnd();
            return JsonConvert.DeserializeObject<T>(jsonMessage);
        }                
    }
    catch(NoNetworkException ex)
    {
        // handle
    }
    catch(InvaidResponseException ex)
    {
        // handle 
    }
}
...