SlappingTheBass12
SlappingTheBass12

Reputation: 377

Better implementation of Blazor WASM Api response?

I have an http service injecting the HttpClient class in my Blazor WASM project. I have a method like this:

public async Task<CommunityDto> GetCommunity(Guid CommunityId)
{
   if (string.IsNullOrEmpty(CommunityId.ToString())) return null;
   var response = await _httpClient.GetAsync($"api/communities/{CommunityId}");
   if (response.IsSuccessStatusCode)
   {
      var content = await response.Content.ReadAsStringAsync();
      return JsonSerializer.Deserialize<CommunityDto>(content, new JsonSerializerOptions { PropertyNameCaseInsensitive = true });
   }
   else
   {
      throw new Exception(response.ReasonPhrase);
   }
}

In my component, I have the following:

protected async override Task OnInitializedAsync()
{
   try
   {
      CommunityFromAPI = await CommunityService.GetCommunity(Id);
   }
   catch (Exception ex)
   {
      ToastService.ShowError($"Failed to get community! {ex.Message}");
      NavManager.NavigateTo("/");
    }
}

Aside from global exception handling, is there a better way to deal with this? I'm intentionally returning a 400 error from my API and my "catch" isn't catching the exception and throwing the toast message. I'm new to Blazor so any help or pointers would be appreciated.

Upvotes: 0

Views: 549

Answers (2)

Steve Wong
Steve Wong

Reputation: 2256

Overall, your design is on definitely on the right track and kudos to you for providing user feedback on errors in your Blazor app.

I have a couple suggestions.

  1. Using the API client's exception.Message to present to your user is ok, but it couples your UI to errors in your API access layer. For example, let's say your API is unavailable and GetAsync throws an HttpRequestException, then you would show the user that error message text. One option is to introduce your own exception type, thrown by your API layer, caught by your UI, and displayed to the user intentionally. Another option is to have your API layer return null and then present the user a generic error message (like "Community unavailable") in your UI. And yet another option (already suggested) is to introduce a "return type" from your API layer that contains both the data and/or error state (but that implementation should be generic, ie, ApiResponse<TReturnData>). All options, including yours, will work fine. In considering options, I would ask myself "what error messages do I really want to show the user? what code would be easiest to maintain?"

  2. A second suggestion is if you can use the extension method ReadFromJsonAsync<> (https://learn.microsoft.com/en-us/dotnet/api/system.net.http.json.httpcontentjsonextensions.readfromjsonasync?view=net-5.0), then you can shorten this code to:

     if (response.IsSuccessStatusCode)
     {
          return await response.Content.ReadFromJsonAsync<CommunityDto>(
                          new JsonSerializerOptions { PropertyNameCaseInsensitive = true });
     }  
    

Upvotes: 0

Nathan Gallete
Nathan Gallete

Reputation: 168

I usually create a composite object like that:

public class ResultObj
    {
        public ResultObj(YourClass result, string errorCode = null, string errorMessage = null)
        {
            this.Result= resultados;
            this.ErrorCode = codigoErro;
            this.ErrorMessage = mensagemErro;
        }

        public string ErrorMessage { get; set; }
        public List<object> Result{ get; set; }
        public string ErrorCode { get; set; }
    }

In your Calls, you convert it inside a try catch block in case of failure in the serialization.

If the serialization works fine, then you check the ErrorCode and ErrorMessage fields and then call your toasts and so on.

Upvotes: -1

Related Questions