Blazor - Web API e HttpClientFactory - II


Neste tutorial veremos como criar uma aplicação Blazor Server que interage com uma WEb API externa usando o HttpClientFactory.

Continuando a primeira parte do artigo vamos criar agora nosso projeto Blazor Server e a seguir um componente para exibir uma lista de contatos.

Recursos usados:

Criando a projeto Blazor Server

Abra o projeto Blazor_Contatos criado no artigo anterior e a seguir no menu File selecione Add-> New Project e selecione o template Blazor App:

   

Clique em Next e informe o nome Blazor_Contatos.Web e clique em Create:

A seguir selecione o template Blazor Server App e clique em Create:

Ao final teremos o projeto Blazor Server criado na Solução:

Vamos incluir uma referência ao projeto Shared no projeto da Blazor.

Clique com o botão direito do mouse no projeto Blazor_Contatos.Web e selecione Add-> Reference; a seguir marque o projeto Blazor_Contatos.Shared e clique em OK:

A seguir inclua o namespace Blazor_Contatos.Shared.Models no arquivo _Imports.razor.

Agora vamos criar uma nova pasta chamada Services no projeto Blazor_Contatos.Web.

E nesta pasta vamos criar uma classe chamada ApiService.

Nesta classe ApiService vamos usar a interface IHttpClientFactory, que é a melhor maneira de usar o HttpClient em um aplicativo Blazor do servidor.

O HttpClientFactory garante que os soquetes associados a cada instância do HttpClient sejam compartilhados, evitando assim o problema de exaustão do soquete.

A seguir o código do serviço ApiService:

using Blazor_Contatos.Shared.Models;
using System.Collections.Generic;
using System.Net.Http;
using System.Text.Json;
using System.Threading.Tasks;
namespace Blazor_Contatos.Web.Services
{
    public class ApiService
    {
        public HttpClient _httpClient;
        public ApiService(HttpClient client)
        {
            _httpClient = client;
        }
        public async Task<List<Contato>> GetContatosAsync()
        {
            var response = await _httpClient.GetAsync("api/contatos");
            response.EnsureSuccessStatusCode();
            using var responseContent = await response.Content.ReadAsStreamAsync();
            return await JsonSerializer.DeserializeAsync<List<Contato>>(responseContent);
        }
        public async Task<Contato> GetContatoPorIdAsync(int id)
        {
            var response = await _httpClient.GetAsync($"api/contatos/{id}");
            response.EnsureSuccessStatusCode();
            using var responseContent = await response.Content.ReadAsStreamAsync();
            return await JsonSerializer.DeserializeAsync<Contato>(responseContent);
        }
    }
}

Implementamos dois métodos, o primeiro retorna uma lista de contato e o segundo vai retornar um contato pelo seu ID.

Agora precisamos registrar a interface HttpClientFactory, para isso abra o arquivo Startup.cs e localize o método ConfigureServices() e registre o serviço:

...
 public void ConfigureServices(IServiceCollection services)
 {
            services.AddRazorPages();
            services.AddServerSideBlazor();
           services.AddHttpClient<ApiService>(client =>
           {
              client.BaseAddress = new Uri("http://localhost:5001");
           });
 }
...

Assim o argumento do caminho no método GetAsync() da classe ApiService será anexado a esse endereço base, passando  "api/contatos" para o método, e buscando o resultado em http://localhost:5001/api/contatos.

Pronto já podemos usar o serviço no projeto Blazor Server para acessar informações dos contatos.

Criando o componente Contatos.razor

Vamos criar o componente Contatos.razor na pasta Pages do projeto Blazor.

Antes vamos remover os componentes Counter.razor e FetchData.razor da pasta Pages e a seguir alterar o código do arquivo NavMenu.razor a pasta Shared conforme abaixo:

...
<div class="@NavMenuCssClass" @onclick="ToggleNavMenu">
    <ul class="nav flex-column">
        <li class="nav-item px-3">
            <NavLink class="nav-link" href="" Match="NavLinkMatch.All">
                <span class="oi oi-home" aria-hidden="true"></span> Home
            </NavLink>
        </li>
        <li class="nav-item px-3">
            <NavLink class="nav-link" href="contatos">
                <span class="oi oi-plus" aria-hidden="true"></span> Contatos
            </NavLink>
        </li>
    </ul>
</div>
...

Aqui removemos os links para Counter e FetchData e incluimos um link para o componente Contatos.razor que iremos criar a seguir.

No menu Project clique em Add->New Item e selecione o template Razor Component informando o nome Contatos.razor e a seguir inclua o código abaixo no componente:

@page "/contatos"
@inject Services.ApiService apiService
<h3>Contatos</h3>
<hr />
@if (contatos == null)
{
    <p><em>Carregando...</em></p>
}
else
{
    <table class="table">
        <thead>
            <tr>
                <th>ID</th>
                <th>Nome</th>
                <th>Email</th>
                <th>Telefone</th>
            </tr>
        </thead>
        <tbody>
            @foreach (var contato in contatos)
            {
            <tr>
                <td>@contato.Id</td>
                <td>@contato.Nome</td>
                <td>@contato.Email</td>
                <td>@contato.Telefone</td>
            </tr>
            }
        </tbody>
    </table>
}
@code {
    List<Contato> contatos;
    protected override async Task OnInitializedAsync()
    {
        contatos = await apiService.GetContatosAsync();
    }
}

Neste código temos o seguinte:

1- Definimos a rota para acessar o componente usando a diretiva :  @page "/contatos"

2- Injetamos o serviço ApiService criado e registrado : @inject Services.ApiService apiService

2- No bloco de código @code definimos uma lista de contatos : List<Contato> contatos;

3- No método OnInitializedAsync() que é executando quando o componente é iniciado invocamos o método GetContatosAsync() do serviço que vai retornar todos os contatos :

    protected override async Task OnInitializedAsync()
    {
        contatos = await apiService.GetContatosAsync();
    }

4 - Finalmente montamos uma tabela HTML para exibir os dados dos contatos

Para testar o projeto e exibir os contatos temos que executar os projetos Web API e Blazor juntos. Para isso clique com o botão direito sobre a solução e marque a opção Multiple startup projects:



A seguir para o projeto API e Web define a Action como Start.

Executando o projeto teremos o resultado abaixo:

Vemos assim a exibição dos contatos pelo componente Contatos.razor.

Criamos assim um projeto do tipo .NET Standard onde definimos uma WEB API que foi acessada a partir de um projeto Blazor Server.

Você pode implementar os demais métodos no serviço como um exercício. Vou deixar implementando os links para incluir, editar e deletar e o resto fica por sua conta.

Pegue o código do projeto aqui: Blazor_Contatos2.zip (sem as referências)

"E este evangelho do reino será pregado em todo o mundo, em testemunho a todas as nações, e então virá o fim."
Mateus 24:14

Referências:


José Carlos Macoratti