Telerik blogs

See how to integrate third-party APIs in Blazor WebAssembly applications, dealing with CORS issues and error handling.

Blazor WebAssembly has been involved in a first-class web framework for building interactive web applications using C# and .NET.

Besides offering simple and powerful APIs for user interface rendering, Blazor also integrates with internal and external APIs. In this article, we will explore how to consume APIs from Blazor WebAssembly and how to deal with common problems, such as CORS and error handling.

You can access the code used in this example on GitHub.

Calling APIs Using the HttpClient Type

The HttpClient type provides access to APIs. First, we need to register the HttpClient with the Client project (WebAssembly) and (because of prerendering) with the Server project (ASP.NET Core).

Server project:

builder.Services.AddHttpClient();

Client project:

builder.Services.AddScoped(sp =>
    new HttpClient
    {
        BaseAddress = new Uri(builder.HostEnvironment.BaseAddress)
    }
);

In the Client project, we use the HostEnvironment property on the builder object to access the BaseAddress of the Server project and set it as the BaseAddress of the HttpClient object. It allows us to provide relative paths in the Client project when accessing APIs from the Server project.

Now we use the @inject directive to inject an instance of the HttpClient type in the Weather page component in the Client project:

@inject HttpClient HttpClient

In the code section, we can now use the HttpClient object and its GetAsync method to load data from the /api/weather route.

Note: If you want to learn how to implement the server-side Controller that provides the API, you can access the code used in this example on GitHub.

@code {
    private WeatherForecast[]? forecasts;

    protected override async Task OnInitializedAsync()
    {
        var response = await HttpClient.GetAsync("/api/weather");
        var weatherForecasts = 
            await response.Content
                .ReadFromJsonAsync<IEnumerable<WeatherForecast>>();
        forecasts = weatherForecasts?.ToArray();
    }
}

After loading the data using the GetAsync method, we use the ReadFromJsonAsync method and provide a generic type argument of the type we expect from the API.

Finally, we assign the returned value to the private forecasts field to render the data on the page.

Use the Same API for Internal and External APIs

One of the best things about using the HttpClient for accessing APIs is that we can use the same type and the same methods to load data from internal APIs (Server project) and from remote APIs (foreign services).

Depending on your preference, you can register an HttpClient per external API and inject the respective instance to your Blazor components.

Alternatively, you can use the same instance for all API calls and provide a relative path for internal and an absolute path for external APIs.

Use a Dedicated SDK for Calling External Services

Some more advanced services, such as Sentry, provide a dedicated SDK for .NET development.

The advantage is that the SDK provides a native interface, such as types and methods that represent operations, instead of having to implement API calls using the HttpClient ourselves.

The integration of those APIs is simpler than accessing APIs using the HttpClient type. However, the HttpClient type provides a generic interface that allows you to access any HTTP API, including those without a dedicated SDK.

In the end, most dedicated SDKs use the HttpClient type in their implementation and provide wrapper methods around it.

Handling CORS Issues

When making API calls from web applications, we often hit Cross-Origin Resource Sharing (CORS) issues.

Since Blazor WebAssembly runs in the browser, the browser’s same-origin policy applies. You might encounter CORS errors if the API server doesn’t explicitly allow requests from your application’s origin.

Configuring CORS in ASP.NET Core

The simplest solution to resolving CORS issues is to configure the server correctly. In the case of an ASP.NET Core server application, we use the AddCors middleware and configure it accordingly.

services.AddCors(options =>
{
    options.AddPolicy("BlazorClientApp",
        builder => builder.WithOrigins("https://blazor-wasm-app.com")
                          .AllowAnyMethod()
                          .AllowAnyHeader());
});

app.UseCors("AllowBlazorApp");

We add a named policy and allowed the client application to access the server. We have full control over the HTTP methods and headers we want to allow or forbid.

Implement a Server-Side Proxy

If we do not have control over the server, we need to implement a server-side proxy.

Server-Side Proxy with a Blazor WebAssembly client application connecting to a server, which then connects to the third-party API.

We implement a wrapper API (API Proxy) on the server that consumes the third-party API and provides it to the client application. Since we control the server application, we can correctly configure the server application to allow connections from the Blazor WebAssembly client application.

It works because CORS is a client-side browser technology. If we connect to the API on the server, CORS does not apply. However, be aware that the API still has to allow access. For example, you need to provide an API key or another form of authentication.

Managing Async Data Fetching with Proper Error Handling

Asynchronous programming is the default in modern web development, and Blazor WebAssembly is no different.

Properly executing and managing API calls is essential for a smooth user experience.

Catch Exceptions When Using the HttpClient

The simplest starting point is adding try-catch statements around HttpClient calls to gracefully handle errors such as network failures or invalid HTTP responses.

try
{
  var url = "https://api.example.com/data";
  data = await Http.GetFromJsonAsync<List<string>>(url);
}
catch (Exception ex)
{
  error = ex.Message;
}

This code allows you to provide a custom error message to the user and log the error in your application logs.

Logging errors helps you find those errors that often occur. Without logging errors, you might not even notice mistakes that happen in your application.

Improve the User Experience with Loading State Indicators

Loading indicators allow you to notify the user that data is being fetched. This prevents the application from appearing unresponsive during longer operations, such as API calls.

There are several ways to implement a loading indicator when working with Blazor. I prefer the following approach:

private async Task LoadCustomers()
{
  _isLoading = true;
  StateHasChanged();
  _customers = await CustomerService.GetAllCustomers();
  _isLoading = false;
  StateHasChanged();
}

I define a private field of type bool to hold the information on whether the data is loading. I also implement an async Load method and set the _isLoading field to true. Next, I call the StateHasChanged method to make sure that the loading indicator shows on the screen.

You can implement a custom loading indicator and show it depending on the value of the _isLoading field, or you can use one of the existing components, such as the Blazor Loader from Progress Telerik UI for Blazor.

Debouncing and Throttling Requests

Some APIs limit the requests a client can send in a given time frame.

Implementing debouncing or throttling is an excellent strategy to minimize the number of requests sent within a short period.

Some libraries like Polly and Reactive Extensions (Rx.NET) help you in such a situation.

Conclusion

Modern web applications consume internal and external APIs. The web is connected, and our applications don’t work in an isolated silo.

The HttpClient type provides a modern, robust and performant asynchronous interface to access APIs using the HTTP protocol.

CORS is a common problem when working with APIs. Make sure to set the correct CORS headers by configuring your ASP.NET Core backend service. Implementing a server-side proxy might be the only option if you consume a third-party API.

Make sure to handle errors using a try-catch statement when using the HttpClient type to access APIs and use loading indicators to improve the user experience of your web application.

Polly helps with debouncing, throttling and retrying HTTP requests.

If you want to learn more about Blazor development, you can watch my free Blazor Crash Course on YouTube. And stay tuned to the Telerik blog for more Blazor Basics.


About the Author

Claudio Bernasconi

Claudio Bernasconi is a passionate software engineer and content creator writing articles and running a .NET developer YouTube channel. He has more than 10 years of experience as a .NET developer and loves sharing his knowledge about Blazor and other .NET topics with the community.

Related Posts

Comments

Comments are disabled in preview mode.