ASP .NET Core - Injeção de dependência nas Views


A ASP .NET Core suporta a injeção de dependência nas Views. Este recurso pode ser útil para serviços específicos para views como localização ou quando os dados requeridos são usados apenas para exibir na view.

Existem muitas formas de fornecer dados para uma View; usar ViewBag, ViewData e ViewModel são as formas mais conhecidas.

Temos agora mais uma opção para fornecer os dados para uma view que é usando a injeção de dependência. Este recurso deve ser usado em casos específicos visto que não considerado uma boa prática.

Para poder usar este recurso usamos a diretiva : @inject

Esta diretiva é usada para injetar a dependência em uma View e possui a seguinte sintaxe:

@inject <type> <nome da instância>

onde:

- @inject é a diretiva usada para injetar as dependências;
- <type> é o tipo de classe de serviço;
- <nome da instância> é o nome da instância do serviço pelo qual podemos acessar os métodos de serviço;

Existem três etapas que devemos cumprir para conseguir isso:

1 -Criar o serviço;
2- Registrar o serviço na classe Startup;
3- Injetar o serviço na View;

Podemos também injetar valores obtidos a partir do arquivo de configuração appsettings.json.

Suponha que temos o seguinte código definido em um arquivo appsettings.json :

{
   "root": {
      "parent": {
         "child": "myvalue"
      }
   }
}

Para fazer a injeção na view usamos a sintaxe:

@using Microsoft.Extensions.Configuration
@inject IConfiguration Configuration

@{
   string myValue = Configuration["root:parent:child"];
   ...
}
...

Para ilustar vejamos um exemplo prático.

Recursos Usados:

Criando o projeto ASP .NET Core e o serviço

Podemos criar o projeto usando o Visual Studio 2019 Community ou a ferramenta de linha de comando Net CLI e o editor Visual Studio Code.

Vamos usar o VS 2019 Comunity e criar um projeto ASP .NET Core Web Appliction usando .NET Core 2.2 chamado AspCore_ViewDI :

Na pasta Models do projeto crie a classe CursosModelService que será o nosso serviço e que iremos injetar na view :

using System.Collections.Generic;

namespace AspCore_ViewDI.Models
{
    public class CursosModelService
    {
        public List<string> GetCursos()
        {
            return new List<string>()
            {
                "ASP .NET Core", "ASP .NET Core MVC- Criando um Site do Zero", "Web API ASP .NET Core Essencial", "Curso Entity Framework Core", "Curso C#"
            };
        }
    }
}

Registrando o serviço na classe Startup

Para usar o serviço criado na View, precisamos registrar esse serviço no método ConfigureServices da classe Startup. Existem três maneiras de registrar um serviço na classe Startup. Cada método tem seu próprio escopo e com base no requisito podemos registrar.

  1. AddTransient - Usado para mapear os tipos abstratos para serviços concretos que são instanciados separadamente para cada objeto que requer o serviço.A vida da instância de serviço é limitada a essa Visualização apenas se registrarmos o serviço usando o método AddTransient. Nesse método, os serviços transitórios são criados sempre que solicitado. Usado para serviços leves e sem estado;
     
  2. AddSingleton - Cria uma única instância em todo o aplicativo. Cria a instância de serviço quando for chamado pela primeira vez e reutilizará esse mesmo objeto em todas as chamadas.
     
  3. AddScoped - Cria o serviço uma vez por solicitação no escopo. É equivalente a um Singleton no escopo atual para solicitação. Cria uma instância em cada solicitação HTTP.

Se o serviço não for registrado ao tentar usá-lo na View, iremos obter uma exceção de operação inválida, com a mensagem :  "Nenhum serviço para o tipo xxx foi registrado".

Para o nosso exemplo vamos abrir o arquivo Startup e no método ConfigureServices registrar o serviço :

        public void ConfigureServices(IServiceCollection services)
        {
            services.Configure<CookiePolicyOptions>(options =>
            {
                options.CheckConsentNeeded = context => true;
                options.MinimumSameSitePolicy = SameSiteMode.None;
            });

            services.AddTransient<CursosModelService>();

            services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
        }

 

O parâmetro IServiceCollection permite configurar diferentes tipos de serviços, seja por criação de objeto ou correspondência a uma interface específica, e suporta os lifetimes mencionados.

Podemos também adicionar uma instância existente ao contêiner DI usando o método AddInstance.

Se você tiver muitos serviços para registrar, você pode criar um método de extensão para IServiceCollection e assim manter o código da classe Startup mais enxuto. O mesmo é usado por padrão para MVC e muitas outras ferramentas que você deseja usar em seu projeto.

Injetando o serviço na view via DI

Vamos usar o serviço em um controlador. Como nosso projeto MVC já tem o controlador HomeController criado por padrão na pasta Controllers vamos aproveitar a view Index.cshtml gerada para o método Action Index.

Agora vamos injetar o serviço na view Index.cshtml da pasta Views.

Abra o arquivo Index.cshtml e inclua o código abaixo:

@{
    ViewData["Title"] = "Home Page";
}
@inject AspCore_ViewDI.Models.CursosModelService cursoService
<div class="text-center">
    <h1 class="display-4">Cursos - Macoratti .net</h1>
    <p>Cursos disponíveis <a href="https://www.macoratti.net">Macoratti .net</a>.</p>
    <p>
        <ul>
            @foreach (var nome in cursoService.GetCursos())
            {
                <li>@nome</li>
            }
        </ul>
    </p>
</div>

A sintaxe básica usada é :   @inject <serviço>  <nome>

Onde :
  1. @inject - é a diretiva usada para injetar dependências;
  2. <serviço> - AspCore_ViewDI.Models.CursosModelService
  3. <nome> - cursoService

A seguir usamos um laço foreach e percorremos os cursos obtidos via método GetCursos().

Executando o projeto iremos obter o seguinte resultado:

Vimos assim a utilização do recurso da injeção de dependência na View. Você pode usar DI quase em todos os lugares da sua aplicação (exceto em HtmlHelpers, porque eles são métodos de extensão).

O recurso pode ser útil para preencher elementos de interface do usuário como um dropdownlist.

Agora atente para a recomendação de que "os dados renderizados pelas Views devem vir dos controladores", e , considere o recurso como uma ajuda cujo objetivo é reduzir a quantidade de código necessária nos controladores.

Pegue projeto aqui : AspCore_ViewDI.zip

"Bem-aventurado o homem que não anda segundo o conselho dos ímpios, nem se detém no caminho dos pecadores, nem se assenta na roda dos escarnecedores.
Antes tem o seu prazer na lei do Senhor, e na sua lei medita de dia e de noite."

Salmos 1:1,2

Referências:


José Carlos Macoratti