【问题标题】:How to catch an exception from Azure Mobile App Backend?如何从 Azure 移动应用后端捕获异常?
【发布时间】:2018-12-06 18:19:33
【问题描述】:

在我的 Azure 移动应用后端,我在 post 方法中验证了数据。在某些情况下,后端服务器会抛出异常,但在应用程序端,我无法捕获此异常。我该怎么做?

这就是我的方法

// POST tables/Paciente
public async Task<IHttpActionResult> PostPaciente(Paciente novoPaciente)
{   

    //other things

    if (paciente != null)
    {
        var responseMessage = new HttpResponseMessage(HttpStatusCode.BadRequest)
        {
            Content = new StringContent("Já existe um paciente com esse token cadastrado.")
        };

        //throw new HttpResponseException(responseMessage);
        return InternalServerError(new Exception("Já existe um paciente com esse token cadastrado."));
    }
}

我尝试抛出 HttpResponseException 并返回 InternalServerException,但没有任何效果。

【问题讨论】:

    标签: azure xamarin xamarin.forms azure-mobile-services


    【解决方案1】:

    您需要检查对您的 http 调用的响应的状态代码(应该有一个 IsSuccesStatusCode 属性要检查)。

    【讨论】:

      【解决方案2】:

      我推荐使用EnsureSuccessStatusCode(),它存在于HttpResponseMessage 类中。如果StatusCode 不是OK(或200 级状态码的某种变体),此方法将抛出异常。

      下面是一个通用类BaseHttpClientServices,我用它在我的所有项目中发出 REST API 请求。它遵循使用 HttpClient(如 Reusing HttpClientDeserializing JSON using Stream 和使用 ConfigureAwait(false))的所有最佳实践。

      在 Xamarin.Forms 中发送发布请求

      public abstract class HttpClientServices : BaseHttpClientServices
      {
          const string apiUrl = "your api url";
      
          public static void PostPaciente(Paciente novoPaciente)
          {    
              try
              {
                  var response = await PostObjectToAPI(apiUrl, novoPaciente);
                  response.EnsureSuccessStatusCode();
              }
              catch(Exception e)
              {
                  //Handle Exception
              }
          }
      }
      

      通用 HttpClient 实现

      using System;
      using System.IO;
      using System.Net;
      using System.Text;
      using System.Net.Http;
      using System.Threading.Tasks;
      using System.Net.Http.Headers;
      using System.Runtime.CompilerServices;
      
      using Newtonsoft.Json;
      
      using Xamarin.Forms;
      
      namespace NameSpace
      {
          public abstract class BaseHttpClientService
          {
              #region Constant Fields
              static readonly Lazy<JsonSerializer> _serializerHolder = new Lazy<JsonSerializer>();
              static readonly Lazy<HttpClient> _clientHolder = new Lazy<HttpClient>(() => CreateHttpClient(TimeSpan.FromSeconds(60)));
              #endregion
      
              #region Fields
              static int _networkIndicatorCount = 0;
              #endregion
      
              #region Properties
              static HttpClient Client => _clientHolder.Value;
              static JsonSerializer Serializer => _serializerHolder.Value;
              #endregion
      
              #region Methods
              protected static async Task<T> GetObjectFromAPI<T>(string apiUrl)
              {
                  using (var responseMessage = await GetObjectFromAPI(apiUrl).ConfigureAwait(false))
                      return await DeserializeResponse<T>(responseMessage).ConfigureAwait(false);
              }
      
              protected static async Task<HttpResponseMessage> GetObjectFromAPI(string apiUrl)
              {
                  try
                  {
                      UpdateActivityIndicatorStatus(true);
      
                      return await Client.GetAsync(apiUrl).ConfigureAwait(false);
                  }
                  catch (Exception e)
                  {
                      Report(e);
                      throw;
                  }
                  finally
                  {
                      UpdateActivityIndicatorStatus(false);
                  }
              }
      
              protected static async Task<TResponse> PostObjectToAPI<TResponse, TRequest>(string apiUrl, TRequest requestData)
              {
                  using (var responseMessage = await PostObjectToAPI(apiUrl, requestData).ConfigureAwait(false))
                      return await DeserializeResponse<TResponse>(responseMessage).ConfigureAwait(false);
              }
      
              protected static Task<HttpResponseMessage> PostObjectToAPI<T>(string apiUrl, T requestData) => SendAsync(HttpMethod.Post, apiUrl, requestData);
      
              protected static async Task<TResponse> PutObjectToAPI<TResponse, TRequest>(string apiUrl, TRequest requestData)
              {
                  using (var responseMessage = await PutObjectToAPI(apiUrl, requestData).ConfigureAwait(false))
                      return await DeserializeResponse<TResponse>(responseMessage).ConfigureAwait(false);
              }
      
              protected static Task<HttpResponseMessage> PutObjectToAPI<T>(string apiUrl, T requestData) => SendAsync(HttpMethod.Put, apiUrl, requestData);
      
              protected static async Task<TResponse> PatchObjectToAPI<TResponse, TRequest>(string apiUrl, TRequest requestData)
              {
                  using (var responseMessage = await PatchObjectToAPI(apiUrl, requestData).ConfigureAwait(false))
                      return await DeserializeResponse<TResponse>(responseMessage).ConfigureAwait(false);
              }
      
              protected static Task<HttpResponseMessage> PatchObjectToAPI<T>(string apiUrl, T requestData) => SendAsync(new HttpMethod("PATCH"), apiUrl, requestData);
      
              protected static async Task<TResponse> DeleteObjectFromAPI<TResponse>(string apiUrl)
              {
                  using (var responseMessage = await DeleteObjectFromAPI(apiUrl).ConfigureAwait(false))
                      return await DeserializeResponse<TResponse>(responseMessage).ConfigureAwait(false);
              }
      
              protected static Task<HttpResponseMessage> DeleteObjectFromAPI(string apiUrl) => SendAsync<object>(HttpMethod.Delete, apiUrl);
      
              static HttpClient CreateHttpClient(TimeSpan timeout)
              {
                  HttpClient client;
                  switch (Device.RuntimePlatform)
                  {
                      case Device.iOS:
                      case Device.Android:
                          client = new HttpClient();
                          break;
                      default:
                          client = new HttpClient(new HttpClientHandler { AutomaticDecompression = DecompressionMethods.GZip });
                          break;
                  }
      
                  client.Timeout = timeout;
                  client.DefaultRequestHeaders.AcceptEncoding.Add(new StringWithQualityHeaderValue("gzip"));
                  client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
      
                  return client;
              }
      
              static async Task<HttpResponseMessage> SendAsync<T>(HttpMethod httpMethod, string apiUrl, T requestData = default)
              {
                  using (var httpRequestMessage = await GetHttpRequestMessage(httpMethod, apiUrl, requestData).ConfigureAwait(false))
                  {
                      try
                      {
                          UpdateActivityIndicatorStatus(true);
      
                          return await Client.SendAsync(httpRequestMessage).ConfigureAwait(false);
                      }
                      catch (Exception e)
                      {
                          Report(e);
                          throw;
                      }
                      finally
                      {
                          UpdateActivityIndicatorStatus(false);
                      }
                  }
              }
      
              static void UpdateActivityIndicatorStatus(bool isActivityIndicatorDisplayed)
              {
                  if (isActivityIndicatorDisplayed)
                  {
                      Device.BeginInvokeOnMainThread(() => Application.Current.MainPage.IsBusy = true);
                      _networkIndicatorCount++;
                  }
                  else if (--_networkIndicatorCount <= 0)
                  {
                      Device.BeginInvokeOnMainThread(() => Application.Current.MainPage.IsBusy = false);
                      _networkIndicatorCount = 0;
                  }
              }
      
              static async ValueTask<HttpRequestMessage> GetHttpRequestMessage<T>(HttpMethod method, string apiUrl, T requestData = default)
              {
                  var httpRequestMessage = new HttpRequestMessage(method, apiUrl);
      
                  switch (requestData)
                  {
                      case T data when data.Equals(default(T)):
                          break;
      
                      case Stream stream:
                          httpRequestMessage.Content = new StreamContent(stream);
                          httpRequestMessage.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
                          break;
      
                      default:
                          var stringPayload = await Task.Run(() => JsonConvert.SerializeObject(requestData)).ConfigureAwait(false);
                          httpRequestMessage.Content = new StringContent(stringPayload, Encoding.UTF8, "application/json");
                          break;
                  }
      
                  return httpRequestMessage;
              }
      
              static async Task<T> DeserializeResponse<T>(HttpResponseMessage httpResponseMessage)
              {
                  httpResponseMessage.EnsureSuccessStatusCode();
      
                  try
                  {
                      using (var contentStream = await httpResponseMessage.Content.ReadAsStreamAsync().ConfigureAwait(false))
                      using (var reader = new StreamReader(contentStream))
                      using (var json = new JsonTextReader(reader))
                      {
                          if (json is null)
                              return default;
      
                          return await Task.Run(() => Serializer.Deserialize<T>(json)).ConfigureAwait(false);
                      }
                  }
                  catch (Exception e)
                  {
                      Report(e);
                      throw;
                  }
              }
      
              static void Report(Exception e, [CallerMemberName]string callerMemberName = "") => Debug.WriteLine(e.Message);
              #endregion
          }
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-12-11
        • 2015-09-14
        • 1970-01-01
        • 1970-01-01
        • 2010-10-29
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多