Você está na página 1de 99

Machine Translated by Google

Machine Translated by Google

DOWNLOAD disponível em: https://aka.ms/blazor-ebook

EDIÇÃO v7.0 - Atualizado para .NET 7

Consulte o registro de alterações pelas atualizações do livro e contribuições da comunidade.

PUBLICADO POR

Equipes de produtos da Divisão de Desenvolvedores da Microsoft, .NET e Visual Studio

Uma divisão da Microsoft Corporation

Um jeito da Microsoft

Redmond, Washington 98052-6399

Copyright © 2023 da Microsoft Corporation

Todos os direitos reservados. Nenhuma parte do conteúdo deste livro pode ser reproduzida ou transmitida de qualquer forma ou
por qualquer meio sem a permissão por escrito do editor.

Este livro é fornecido “no estado em que se encontra” e expressa os pontos de vista e opiniões do autor. Os pontos de vista, opiniões
e informações expressas neste livro, incluindo URLs e outras referências a sites da Internet, podem mudar sem aviso prévio.

Alguns exemplos aqui representados são fornecidos apenas para ilustração e são fictícios. Nenhuma associação ou conexão real é
pretendida ou deve ser inferida.

Microsoft e as marcas registradas listadas em https://www.microsoft.com na página “Marcas registradas” são marcas registradas do
grupo de empresas Microsoft.

Mac e macOS são marcas comerciais da Apple Inc.

Todas as outras marcas e logotipos são propriedade de seus respectivos proprietários.

Autores:

Daniel Roth, Gerente Principal de Programa, Microsoft Corp.

Jeff Fritz, Gerente de Programa Sênior, Microsoft Corp.

Taylor Southwick, Engenheiro de software sênior, Microsoft Corp.

Scott Addie, Desenvolvedor de conteúdo sênior, Microsoft Corp.

Steve “@ardalis” Smith, Arquiteto e instrutor de software, NimblePros.com


Machine Translated by Google

Introdução
O .NET há muito oferece suporte ao desenvolvimento de aplicativos da web por meio do ASP.NET, um conjunto abrangente de
estruturas e ferramentas para construir qualquer tipo de aplicativo da web. ASP.NET tem sua própria linhagem de
estruturas e tecnologias da web, começando com as clássicas Active Server Pages (ASP). Estruturas como ASP.NET Web
Forms, ASP.NET MVC, ASP.NET Web Pages e, mais recentemente, ASP.NET Core fornecem uma maneira
produtiva e poderosa de criar aplicativos Web renderizados em servidor , onde o conteúdo da UI é gerado dinamicamente
no servidor em resposta a solicitações HTTP. Cada estrutura ASP.NET atende a um público e uma filosofia de construção de
aplicativos diferentes. ASP.NET Web Forms fornecidos com a versão original do .NET Framework e permitiram o
desenvolvimento web usando muitos dos padrões familiares aos desenvolvedores de desktop, como controles de UI
reutilizáveis com manipulação simples de eventos. No entanto, nenhuma das ofertas do ASP.NET fornece uma maneira
de executar código executado no navegador do usuário. Para fazer isso, é necessário escrever JavaScript e usar qualquer
uma das muitas estruturas e ferramentas de JavaScript que ganharam e perderam popularidade ao longo dos anos: jQuery,
Knockout, Angular, React e assim por diante.

Blazor é uma nova estrutura web que muda o que é possível ao construir aplicativos web com .NET.
Blazor é uma estrutura de UI da web do lado do cliente baseada em C# em vez de JavaScript. Com o Blazor, você pode
escrever sua lógica do lado do cliente e componentes de UI em C#, compilá-los em assemblies .NET normais e, em seguida,
executá-los diretamente no navegador usando um novo padrão da web aberto chamado WebAssembly. Ou,
alternativamente, o Blazor pode executar seus componentes de UI .NET no servidor e lidar com todas as interações de UI
de maneira fluida por meio de uma conexão em tempo real com o navegador. Quando combinado com o .NET em execução
no servidor, o Blazor permite o desenvolvimento web full-stack com .NET. Embora o Blazor compartilhe muitos pontos em
comum com o ASP.NET Web Forms, como ter um modelo de componente reutilizável e uma maneira simples de lidar
com eventos do usuário, ele também se baseia nos fundamentos do .NET para fornecer uma experiência de
desenvolvimento web moderna e de alto desempenho.

Este livro apresenta o Blazor aos desenvolvedores de Web Forms do ASP.NET de uma maneira familiar e
conveniente. Ele apresenta conceitos do Blazor em paralelo com conceitos análogos em ASP.NET Web Forms, ao mesmo
tempo que explica novos conceitos que podem ser menos familiares. Ele cobre uma ampla gama de tópicos e
preocupações, incluindo criação de componentes, roteamento, layout, configuração e segurança. E embora o conteúdo deste
livro seja principalmente para permitir novos desenvolvimentos, ele também cobre diretrizes e estratégias para
migrar formulários Web ASP.NET existentes para o Blazor quando você quiser modernizar um aplicativo existente.

Quem deve usar o livro


Este livro é para desenvolvedores de Web Forms ASP.NET que procuram uma introdução ao Blazor relacionada aos seus
conhecimentos e habilidades existentes. Este livro pode ajudá-lo a iniciar rapidamente um novo projeto baseado em Blazor
ou a traçar um roteiro para modernizar um aplicativo ASP.NET Web Forms existente.

Como usar o livro


A primeira parte deste livro cobre o que é Blazor e o compara ao desenvolvimento de aplicativos web com ASP.NET
Web Forms. O livro cobre uma variedade de tópicos do Blazor, capítulo por capítulo, e relaciona
Machine Translated by Google

cada conceito do Blazor ao conceito correspondente em ASP.NET Web Forms ou explica completamente
quaisquer conceitos completamente novos. O livro também se refere regularmente a um aplicativo de exemplo
completo implementado em ASP.NET Web Forms e Blazor para demonstrar os recursos do Blazor e fornecer um
estudo de caso para migrar de ASP.NET Web Forms para Blazor. Você pode encontrar ambas as implementações
do aplicativo de exemplo (versões ASP.NET Web Forms e Blazor) no GitHub.

O que este livro não cobre


Este livro é uma introdução ao Blazor, não um guia de migração abrangente. Embora inclua orientações sobre
como abordar a migração de um projeto do ASP.NET Web Forms para o Blazor, ele não tenta cobrir todas as
nuances e detalhes. Para obter orientações mais gerais sobre a migração do ASP.NET para o ASP.NET Core,
consulte as orientações de migração na documentação do ASP.NET Core.

Recursos adicionais
Você pode encontrar a página inicial oficial do Blazor e a documentação em https://blazor.net.
Machine Translated by Google

Conteúdo
Uma introdução ao Blazor para desenvolvedores de Web Forms do ASP.NET ........................................ .1

Um .NET de código aberto e multiplataforma .................................... .................................................. ...........................2

Desenvolvimento web do lado do cliente.................................... .................................................. ................................................3

WebAssembly atende a uma necessidade ............................................. .................................................. ................................................3

Blazor: desenvolvimento web full-stack com .NET........................................ .................................................. ...................4

Introdução ao Blazor................................................. .................................................. .................................................. ........4

Comparação de arquitetura de ASP.NET Web Forms e Blazor................................... .... 5

Formulários da Web ASP.NET......................................... .................................................. .................................................. ..............5

Blazor.................................................. .................................................. .................................................. ........................................6

Modelos de hospedagem de aplicativos Blazor............................................. .................................................. ..... 8

Aplicativos Blazor WebAssembly ........................................ .................................................. .................................................. 8

Aplicativos Blazor Server ........................................ .................................................. .................................................. ................9

Como escolher o modelo de hospedagem Blazor certo .......................................... .................................................. ........... 10

Implantar seu aplicativo................................................. .................................................. .................................................. ................. 11

Estrutura do projeto para aplicativos Blazor............................................. ........................................... 12

Arquivo do projeto.................................................. .................................................. .................................................. ............................ 12

Ponto de entrada................................................ .................................................. .................................................. ........................... 13

Arquivos estáticos ................................................ .................................................. .................................................. ............................ 15

Configuração................................................. .................................................. .................................................. .................... 15

Componentes da navalha ................................................ .................................................. .................................................. ........... 15

Páginas................................................. .................................................. .................................................. .................................... 16

Disposição.................................................. .................................................. .................................................. ................................... 16

Blazor Bootstrap.................................................. .................................................. .................................................. ................ 16

Saída da compilação ................................................... .................................................. .................................................. ........................ 18

Execute o aplicativo com Hot Reload......................................... .................................................. ............................................. 18

Inicialização do aplicativo................................................ .................................................. ........................... 21

Application_Start e Web Forms ........................................ .................................................. .................................. 21

Estrutura de inicialização do servidor Blazor............................................. .................................................. ........................................ 21

eu Conteúdo
Machine Translated by Google

Atualizando o Processo BundleConfig ............................................. .................................................. ........................... 23

Crie componentes de UI reutilizáveis com Blazor......................................... ............................ 24


Uma introdução ao Razor ............................................. .................................................. .................................................. .24

Usar componentes ................................................ .................................................. .................................................. ............... 27

Modificar o título da página dos componentes ............................................. .................................................. .............................. 28

Parâmetros do componente ................................................ .................................................. .................................................. .28

Parâmetros de string de consulta ............................................. .................................................. .............................................. 29

Componentes e limites de erro ............................................. .................................................. ................................ 29

Manipuladores de eventos.................................................. .................................................. .................................................. .................... 30

Ligação de dados ................................................ .................................................. .................................................. ........................ 32

Mudanças de estado ................................................ .................................................. .................................................. ....................33

Ciclo de vida do componente................................................ .................................................. .................................................. ........ 34

OnInitializado .................................................. .................................................. .................................................. .................. 34

OnParametersSet................................................. .................................................. .................................................. ........ 34

OnAfterRender................................................. .................................................. .................................................. ............. 34

IDescartável .................................................. .................................................. .................................................. .................... 35

Capturar referências de componentes ............................................. .................................................. .................................... 35

Capturar referências de elementos ............................................. .................................................. ........................................... 36

Componentes modelados ................................................ .................................................. .................................................. .36

Conteúdo infantil................................................ .................................................. .................................................. .................. 36

Parâmetros do modelo................................................ .................................................. .................................................. ..37

Código por trás............................................... .................................................. .................................................. ........................ 38

Recursos adicionais................................................ .................................................. .................................................. ........ 38

Páginas, roteamento e layouts......................................... .................................................. .... 39


Criar páginas................................................ .................................................. .................................................. ........................ 40

Componente do roteador................................................ .................................................. .................................................. ........... 41

Navegação ................................................... .................................................. .................................................. ........................... 41

URLs base.................................................. .................................................. .................................................. ............................ 42

Layout da página................................................ .................................................. .................................................. .......................... 42

Gestão do Estado.................................................. .................................................. .............. 45


Solicitar gerenciamento de estado com ViewState ............................................. .................................................. ............... 45

eu Conteúdo
Machine Translated by Google

Manter o estado com a Sessão ............................................. .................................................. ............................................... 46

Estado da aplicação ................................................ .................................................. .................................................. ............... 46

No navegador.................................................. .................................................. .................................................. ..................... 47

Formulários e validação ............................................. .................................................. ........... 48

Recursos adicionais................................................ .................................................. .................................................. ........ 50

Trabalhar com dados................................................... .................................................. ..................... 51

Estrutura de entidade ................................................ .................................................. .................................................. .............. 51

Código EF Primeiro................................................... .................................................. .................................................. .................... 52

Banco de dados EF primeiro .......................................... .................................................. .................................................. ........... 53

Interagir com serviços da web ............................................. .................................................. .................................................. 53

Módulos, manipuladores e middleware .......................................... ........................................ 55

Visão geral................................................. .................................................. .................................................. .............................. 55

Katana.................................................. .................................................. .................................................. ................................... 56

Middleware comum................................................. .................................................. .................................................. ...... 56

Middleware personalizado................................................. .................................................. .................................................. ......... 57

Configuração do aplicativo................................................ .................................................. ............... 59

Fontes de configuração.................................................. .................................................. .................................................. ..... 59

Formato e acesso appsettings.json .......................................... .................................................. ................................ 60

Segredos do usuário ................................................ .................................................. .................................................. ........................... 60

Variáveis ambientais................................................ .................................................. .................................................. ..... 60

Argumentos de linha de comando ............................................. .................................................. ................................................ 61

O retorno do web.config .......................................... .................................................. .................................................. ... 61

Ler configuração no aplicativo......................................... .................................................. ........................................... 62

Configuração fortemente digitada................................................. .................................................. ........................................... 62

Segurança: Autenticação e Autorização em ASP.NET Web Forms e Blazor........... 64

Provedores universais ASP.NET............................................. .................................................. ............................................... 64

Configuração de autorização em Web Forms ............................................. .................................................. ............ 65

Código de autorização em Web Forms ............................................. .................................................. ............................ 66

Identidade principal do ASP.NET................................................... .................................................. .................................................. ........ 67

Funções, reivindicações e políticas .......................................... .................................................. ............................................... 67

Guia de migração.................................................. .................................................. .................................................. ............ 69

iii Conteúdo
Machine Translated by Google

Criando o esquema de identidade principal do ASP.NET......................................... .................................................. ............. 69

Migrando dados de provedores universais para ASP.NET Core Identity ................................... ..................... 72

Migrando configurações de segurança do web.config para a inicialização do aplicativo................................... ................................... 73

Atualizando páginas individuais para usar abstrações de identidade do ASP.NET Core ........................................ .............. 74

Resumo ................................................. .................................................. .................................................. ............................ 75

Referências ................................................. .................................................. .................................................. ........................... 76

Migrar do ASP.NET Web Forms para o Blazor......................................... ............................ 77


Hospedagem do lado do servidor versus hospedagem do lado do cliente.................................. .................................................. .............................. 77

Criar um novo projeto................................................. .................................................. .................................................. .......... 78

Habilitar processo de inicialização................................................ .................................................. .................................................. ..... 79

Migrar módulos e manipuladores HTTP para middleware ........................................... .................................................. 82

Migrar arquivos estáticos ............................................. .................................................. .................................................. ............. 83

Migrar o pacote de tempo de execução e a configuração de minificação .................................... .................................................. .... 83

Migrar páginas ASPX ............................................. .................................................. .................................................. ......... 83

Validação de modelo no Blazor............................................. .................................................. ........................................... 87

Migrar configuração................................................... .................................................. .................................................. ..... 88

Migrar o acesso a dados ............................................. .................................................. .................................................. .......... 90

Mudanças arquitetônicas................................................ .................................................. .................................................. ...... 90

Conclusão da migração................................................ .................................................. .................................................. ....... 91

4 Conteúdo
Machine Translated by Google

CAPÍTULO 1

Uma introdução ao Blazor


para ASP.NET Web Forms
desenvolvedores
A estrutura ASP.NET Web Forms tem sido um elemento básico do desenvolvimento web do .NET desde o lançamento
do .NET Framework pela primeira vez em 2002. Na época em que a Web ainda estava em sua infância, o ASP.NET Web
Forms tornou a construção de aplicativos web simples e produtiva, adotando muitos dos padrões que foram usados para
desenvolvimento de desktop. Em ASP.NET Web Forms, as páginas da Web podem ser compostas rapidamente a partir de
controles de UI reutilizáveis. As interações do usuário são tratadas naturalmente como eventos. Existe um rico ecossistema de
Controles de UI de Web Forms fornecidos pela Microsoft e fornecedores de controle. Os controles facilitam os
esforços de conexão com fontes de dados e exibição de visualizações de dados ricas. Para os visualmente inclinados,
o designer de Web Forms fornece uma interface simples de arrastar e soltar para gerenciar controles.

Ao longo dos anos, a Microsoft introduziu novas estruturas web baseadas em ASP.NET para atender às
tendências de desenvolvimento web. Algumas dessas estruturas da web incluem ASP.NET MVC, páginas da
Web ASP.NET e, mais recentemente, ASP.NET Core. A cada nova estrutura, alguns previram o declínio iminente
dos Web Forms ASP.NET e criticaram-no como uma estrutura web desatualizada e obsoleta. Apesar dessas
previsões, muitos desenvolvedores da Web .NET continuam a considerar os ASP.NET Web Forms uma maneira
simples, estável e produtiva de realizar seu trabalho.

No momento em que este artigo foi escrito, quase meio milhão de desenvolvedores web usavam ASP.NET Web Forms
todos os meses. A estrutura ASP.NET Web Forms é estável a ponto de documentos, exemplos, livros e postagens de
blog de uma década atrás permanecerem úteis e relevantes. Para muitos desenvolvedores web .NET,
“ASP.NET” ainda é sinônimo de “ASP.NET Web Forms”, como era quando o .NET foi concebido. Argumentos sobre
os prós e os contras dos Web Forms do ASP.NET em comparação com outras novas estruturas da web .NET podem continuar.
ASP.NET Web Forms continua sendo uma estrutura popular para a criação de aplicativos web.

Mesmo assim, as inovações no desenvolvimento de software não estão a abrandar. Todos os desenvolvedores de software
precisam estar atualizados com as novas tecnologias e tendências. Vale a pena considerar duas tendências em particular:

1. A mudança para código aberto e plataforma cruzada


2. A mudança da lógica do aplicativo para o cliente

1 CAPÍTULO 1 | Uma introdução ao Blazor para desenvolvedores de Web Forms ASP.NET


Machine Translated by Google

Um .NET de código aberto e multiplataforma


Quando os Web Forms .NET e ASP.NET foram lançados pela primeira vez, o ecossistema da plataforma parecia muito diferente
do que é hoje. Os mercados de desktops e servidores foram dominados pelo Windows. Plataformas alternativas como macOS
e Linux ainda lutavam para ganhar força. O ASP.NET Web Forms é fornecido com o .NET Framework como um
componente somente do Windows, o que significa que os aplicativos ASP.NET Web Forms só podem ser executados em
máquinas Windows Server. Muitos ambientes modernos agora usam diferentes tipos de plataformas para servidores e
máquinas de desenvolvimento, de modo que o suporte multiplataforma para muitos usuários é um requisito absoluto.

A maioria das estruturas da web modernas agora também são de código aberto, o que traz vários benefícios. Os
usuários não ficam dependentes de um único proprietário do projeto para corrigir bugs e adicionar recursos. Os projetos
de código aberto proporcionam maior transparência sobre o progresso do desenvolvimento e as mudanças futuras. Os projetos
de código aberto contam com contribuições de toda uma comunidade e promovem um ecossistema de código aberto de apoio.
Apesar dos riscos do código aberto, muitos consumidores e colaboradores encontraram mitigações adequadas que lhes
permitem usufruir dos benefícios de um ecossistema de código aberto de uma forma segura e razoável.
Exemplos de tais mitigações incluem contratos de licença de contribuidor, licenças amigáveis, varreduras de pedigree e
fundações de apoio.

A comunidade .NET adotou o suporte multiplataforma e o código aberto. .NET Core é uma implementação de código
aberto e multiplataforma do .NET que roda em uma infinidade de plataformas, incluindo Windows, macOS e várias
distribuições Linux. O Xamarin fornece o Mono, uma versão de código aberto do .NET. O Mono funciona em Android, iOS e
em vários outros formatos, incluindo relógios e smart TVs. Em 2020, a Microsoft lançou o .NET 5 que reconciliou .NET
Core e Mono em “um único tempo de execução e estrutura .NET que pode ser usado em qualquer lugar e que tem
comportamentos de tempo de execução e experiências de desenvolvedor uniformes”.

Os Web Forms do ASP.NET se beneficiarão com a mudança para o suporte de código aberto e multiplataforma? A
resposta, infelizmente, é não, ou pelo menos não na mesma medida que o resto da plataforma. A equipe do .NET deixou
claro que os formulários da Web do ASP.NET não serão portados para o .NET Core ou .NET 7. Por que isso?

Houve esforços nos primeiros dias do .NET Core para portar o ASP.NET Web Forms. O número de alterações significativas
necessárias foi considerado muito drástico. Há também uma admissão aqui de que, mesmo para a Microsoft, há um limite para
o número de estruturas web que ela pode suportar simultaneamente. Talvez alguém na comunidade assuma a causa da
criação de uma versão de código aberto e multiplataforma do ASP.NET Web Forms. O código-fonte para formulários da
Web ASP.NET foi disponibilizado publicamente em formulário de referência. Mas, por enquanto, parece que o ASP.NET
Web Forms permanecerá apenas para Windows e sem um modelo de contribuição de código aberto. Se o suporte
multiplataforma ou código aberto se tornar importante para seus cenários, você precisará procurar algo novo.

Isso significa que o ASP.NET Web Forms está morto e não deve mais ser usado? Claro que não! Contanto que o .NET
Framework seja fornecido como parte do Windows, o ASP.NET Web Forms será uma estrutura com suporte.
Para muitos desenvolvedores de Web Forms, a falta de suporte multiplataforma e de código aberto não é um problema.
Se você não precisa de suporte multiplataforma, código-fonte aberto ou qualquer outro novo recurso do .NET Core
ou .NET 7, não há problema em usar o ASP.NET Web Forms no Windows. Os Formulários Web ASP.NET continuarão a ser
uma forma produtiva de escrever aplicativos Web por muitos anos.

Mas há outra tendência que vale a pena considerar: a mudança para o cliente.

2 CAPÍTULO 1 | Uma introdução ao Blazor para desenvolvedores de Web Forms ASP.NET


Machine Translated by Google

Desenvolvimento web do lado do cliente


Todas as estruturas web baseadas em .NET, incluindo ASP.NET Web Forms, historicamente tiveram uma coisa em comum:
elas são renderizadas pelo servidor. Em aplicativos web renderizados pelo servidor, o navegador faz uma solicitação ao servidor,
que executa algum código (código .NET em aplicativos ASP.NET) para produzir uma resposta. Essa resposta é enviada de
volta ao navegador para ser tratada. Neste modelo, o navegador é usado como um mecanismo de renderização fino.
O trabalho árduo de produzir a UI, executar a lógica de negócios e gerenciar o estado ocorre no
servidor.

No entanto, os navegadores tornaram-se plataformas versáteis. Eles implementam um número cada vez maior de padrões
web abertos que concedem acesso aos recursos da máquina do usuário. Por que não aproveitar o poder de
computação, o armazenamento, a memória e outros recursos do dispositivo cliente? As interações da interface do
usuário, em particular, podem se beneficiar de uma sensação mais rica e interativa quando tratadas, pelo menos parcial
ou totalmente, no lado do cliente. A lógica e os dados que deveriam ser tratados no servidor ainda podem ser tratados no
lado do servidor. Chamadas de API da Web ou até mesmo protocolos em tempo real, como WebSockets, podem ser usados.
Esses benefícios estão disponíveis gratuitamente para desenvolvedores web se eles estiverem dispostos a escrever
JavaScript. Estruturas de UI do lado do cliente, como Angular, React e Vue, simplificam o desenvolvimento web do lado do
cliente e cresceram em popularidade. Os desenvolvedores de Web Forms ASP.NET também podem se beneficiar do
aproveitamento do cliente e até mesmo ter algum suporte pronto para uso com estruturas JavaScript integradas, como ASP.NET AJAX.

Mas unir duas plataformas e ecossistemas diferentes (.NET e JavaScript) tem um custo.
É necessária experiência em dois mundos paralelos com diferentes linguagens, estruturas e ferramentas. Código e lógica não
podem ser facilmente compartilhados entre cliente e servidor, resultando em duplicação e sobrecarga de engenharia.
Também pode ser difícil acompanhar o ecossistema JavaScript, que tem um histórico de evolução a uma velocidade
vertiginosa. A estrutura de front-end e as preferências das ferramentas de construção mudam rapidamente. A indústria
observou a progressão do Grunt para o Gulp, para o Webpack e assim por diante. A mesma agitação inquieta ocorreu com
estruturas de front-end como jQuery, Knockout, Angular, React e Vue. Mas dado o monopólio do navegador JavaScript, havia
pouca escolha nesse assunto. Isto é, até que a comunidade da web se reunisse e fizesse um milagre acontecer!

WebAssembly atende a uma necessidade


Em 2015, os principais fornecedores de navegadores uniram forças em um grupo comunitário W3C para criar um novo
padrão web aberto chamado WebAssembly. WebAssembly é um código de bytes para a Web. Se você puder compilar seu
código para WebAssembly, ele poderá ser executado em qualquer navegador em qualquer plataforma em velocidade
próxima à nativa. Os esforços iniciais se concentraram em C/C++. O resultado foi uma demonstração dramática de
execução de mecanismos gráficos 3D nativos diretamente no navegador, sem plug-ins. Desde então, o WebAssembly
foi padronizado e implementado por todos os principais navegadores.

O trabalho na execução do .NET no WebAssembly foi anunciado no final de 2017 e lançado em 2020, incluindo suporte
no .NET 5 e além. A capacidade de executar código .NET diretamente no navegador permite o desenvolvimento web full-
stack com .NET.

3 CAPÍTULO 1 | Uma introdução ao Blazor para desenvolvedores de Web Forms ASP.NET


Machine Translated by Google

Blazor: desenvolvimento web full-stack com .NET


Por si só, a capacidade de executar código .NET em um navegador não oferece uma experiência completa para a criação de
aplicativos Web do lado do cliente. É aí que entra o Blazor. Blazor é uma estrutura de UI da web do lado do cliente baseada em C#
em vez de JavaScript. O Blazor pode ser executado diretamente no navegador via WebAssembly. Nenhum plug-in de
navegador é necessário. Como alternativa, os aplicativos Blazor podem ser executados no lado do servidor no .NET e lidar com
todas as interações do usuário por meio de uma conexão em tempo real com o navegador.

Blazor tem excelente suporte de ferramentas no Visual Studio e Visual Studio Code. A estrutura também inclui um modelo completo
de componentes de UI e possui recursos integrados para:

• Formulários e validação

Injeção de dependência

Roteamento do lado do cliente

Layouts

Depuração no navegador

Interoperabilidade JavaScript

O Blazor tem muito em comum com os Web Forms do ASP.NET. Ambas as estruturas oferecem modelos de programação de
UI com estado, baseados em componentes e orientados a eventos. A principal diferença arquitetônica é que o ASP.NET Web Forms
é executado apenas no servidor. O Blazor pode ser executado no cliente no navegador. Mas se você tem experiência em ASP.NET
Web Forms, há muitas coisas no Blazor que lhe parecerão familiares. Blazor é uma solução natural para desenvolvedores de
Web Forms ASP.NET que procuram uma maneira de aproveitar as vantagens do desenvolvimento do lado do cliente e do
futuro de código aberto e plataforma cruzada do .NET.

Este livro fornece uma introdução ao Blazor voltada especificamente para desenvolvedores de Web Forms ASP.NET. Cada
conceito do Blazor é apresentado no contexto de recursos e práticas análogas do ASP.NET Web Forms. Ao final deste
livro, você terá uma compreensão de:

• Como construir aplicativos Blazor.


• Como funciona o Blazor.

• Como o Blazor se relaciona com o .NET.



Estratégias razoáveis para migrar aplicativos ASP.NET Web Forms existentes para o Blazor, quando apropriado.

Comece com o Blazor


Começar a usar o Blazor é fácil. Acesse https://blazor.net e siga os links para instalar os modelos de projeto .NET SDK
e Blazor apropriados. Você também encontrará instruções para configurar as ferramentas do Blazor no Visual Studio ou no
Visual Studio Code.

4 CAPÍTULO 1 | Uma introdução ao Blazor para desenvolvedores de Web Forms ASP.NET


Machine Translated by Google

CAPÍTULO 2

Comparação de arquitetura
de ASP.NET Web Forms
e Blazor
Embora o ASP.NET Web Forms e o Blazor tenham muitos conceitos semelhantes, há diferenças na forma como eles
funcionam. Este capítulo examina o funcionamento interno e as arquiteturas do ASP.NET Web Forms e do Blazor.

Formulários Web ASP.NET


A estrutura ASP.NET Web Forms é baseada em uma arquitetura centrada em páginas. Cada solicitação HTTP para
um local no aplicativo é uma página separada com a qual o ASP.NET responde. À medida que as páginas são
solicitadas, o conteúdo do navegador é substituído pelos resultados da página solicitada.

As páginas consistem nos seguintes componentes:

• Marcação HTML
• Código C# ou Visual Basic

• Uma classe code-behind contendo recursos lógicos e de manipulação de eventos


• Controles

Os controles são unidades reutilizáveis de UI da web que podem ser colocadas programaticamente e interagidas em uma
página. As páginas são compostas de arquivos que terminam com .aspx contendo marcações, controles e algum código.
As classes code-behind estão em arquivos com o mesmo nome base e extensão .aspx.cs ou .aspx.vb , dependendo da
linguagem de programação utilizada. Curiosamente, o servidor web interpreta o conteúdo dos arquivos .aspx e os compila
sempre que eles são alterados. Esta recompilação ocorre mesmo se o servidor web já estiver em execução.

Os controles podem ser criados com marcação e entregues como controles de usuário. Um controle de usuário deriva
da classe UserControl e possui uma estrutura semelhante à Page. A marcação para controles de usuário é armazenada
em um arquivo .ascx . Uma classe code-behind que acompanha reside em um arquivo .ascx.cs ou .ascx.vb . Os controles
também podem ser construídos completamente com código, herdando da classe base WebControl ou CompositeControl .

5 CAPÍTULO 2 | Comparação de arquitetura de ASP.NET Web Forms e Blazor


Machine Translated by Google

As páginas também têm um extenso ciclo de vida de eventos. Cada página gera eventos para os eventos de inicialização, carregamento,

pré-renderização e descarregamento que ocorrem à medida que o tempo de execução do ASP.NET executa o código da página para cada

solicitação.

Os controles em uma página normalmente fazem postback na mesma página que apresentou o controle e carregam consigo uma carga útil de

um campo de formulário oculto chamado ViewState. O campo ViewState contém informações sobre o estado dos controles no

momento em que foram renderizados e apresentados na página, permitindo que o tempo de execução do ASP.NET compare e identifique

alterações no conteúdo submetido ao


servidor.

Blazor
Blazor é uma estrutura de UI da web do lado do cliente, de natureza semelhante às estruturas de front-end JavaScript, como Angular ou

React. O Blazor lida com as interações do usuário e renderiza as atualizações de IU necessárias. Blazor não é

baseado em um modelo de solicitação-resposta. As interações do usuário são tratadas como eventos que não estão no contexto de nenhuma

solicitação HTTP específica.

Os aplicativos Blazor consistem em um ou mais componentes raiz que são renderizados em uma página HTML.

A maneira como o usuário especifica onde os componentes devem ser renderizados e como os componentes são conectados para as interações

do usuário é específico do modelo de hospedagem .

Os componentes do Blazor são classes .NET que representam uma parte reutilizável da IU. Cada componente mantém seu próprio estado e

especifica sua própria lógica de renderização, que pode incluir a renderização de outros componentes.

Os componentes especificam manipuladores de eventos para interações específicas do usuário para atualizar o estado do componente.

Depois que um componente manipula um evento, o Blazor renderiza o componente e acompanha o que mudou na saída renderizada. Os

componentes não são renderizados diretamente no Document Object Model (DOM).

6 CAPÍTULO 2 | Comparação de arquitetura de ASP.NET Web Forms e Blazor


Machine Translated by Google

Em vez disso, eles são renderizados em uma representação do DOM na memória chamada RenderTree para que o
Blazor possa rastrear as alterações. O Blazor compara a saída recém-renderizada com a saída anterior para
calcular uma diferença de UI que então aplica de forma eficiente ao DOM.

Os componentes também podem indicar manualmente que devem ser renderizados se seu estado mudar fora de um
evento normal da UI. Blazor usa um SynchronizationContext para impor um único thread lógico de execução.
Os métodos de ciclo de vida de um componente e quaisquer retornos de chamada de evento gerados pelo Blazor
são executados neste SynchronizationContext.

7 CAPÍTULO 2 | Comparação de arquitetura de ASP.NET Web Forms e Blazor


Machine Translated by Google

CAPÍTULO 3

Modelos de hospedagem de aplicativos Blazor

Os aplicativos Blazor podem ser hospedados de uma das seguintes maneiras:


Lado do cliente no navegador no WebAssembly.

Lado do servidor em um aplicativo ASP.NET Core.

Aplicativos Blazor WebAssembly


Os aplicativos Blazor WebAssembly são executados diretamente no navegador em um tempo de execução .NET baseado em WebAssembly.

Os aplicativos Blazor WebAssembly funcionam de maneira semelhante às estruturas JavaScript front-end, como Angular ou React. No entanto, em

vez de escrever JavaScript, você escreve C#. O tempo de execução do .NET é baixado com o aplicativo junto com o assembly do aplicativo e

quaisquer dependências necessárias. Não são necessários plug-ins ou extensões de navegador.

Os assemblies baixados são assemblies .NET normais, como você usaria em qualquer outro aplicativo .NET.

Como o tempo de execução oferece suporte ao .NET Standard, você pode usar bibliotecas .NET Standard existentes com seu aplicativo

Blazor WebAssembly. No entanto, esses assemblies ainda serão executados na área restrita de segurança do navegador. Algumas

funcionalidades podem gerar uma PlatformNotSupportedException, como tentar acessar o sistema de arquivos ou abrir conexões de rede

arbitrárias.

Quando o aplicativo é carregado, o tempo de execução do .NET é iniciado e apontado para o assembly do aplicativo. A lógica de inicialização

do aplicativo é executada e os componentes raiz são renderizados. O Blazor calcula as atualizações da IU com base na saída renderizada

dos componentes. As atualizações do DOM são então aplicadas.

8 CAPÍTULO 3 | Modelos de hospedagem de aplicativos Blazor


Machine Translated by Google

Os aplicativos Blazor WebAssembly são executados exclusivamente no lado do cliente. Esses aplicativos podem ser implantados em

soluções de hospedagem de sites estáticos, como GitHub Pages ou Azure Static Website Hosting. O .NET não é necessário no servidor.
Links diretos para partes do aplicativo normalmente requerem uma solução de roteamento no servidor. A solução de roteamento

redireciona as solicitações para a raiz do aplicativo. Por exemplo, esse redirecionamento pode ser tratado usando regras de reescrita de
URL no IIS.

Para obter todos os benefícios do Blazor e do desenvolvimento web .NET full-stack, hospede seu aplicativo Blazor WebAssembly com

ASP.NET Core. Ao usar o .NET no cliente e no servidor, você pode facilmente compartilhar código e criar seu aplicativo usando um
conjunto consistente de linguagens, estruturas e ferramentas. Blazor fornece modelos convenientes para configurar uma

solução que contém um aplicativo Blazor WebAssembly e um projeto host ASP.NET Core. Quando a solução é criada, os arquivos

estáticos criados do aplicativo Blazor são hospedados pelo aplicativo ASP.NET Core com o roteamento de fallback já configurado.

Aplicativos Blazor Server


Lembre-se da discussão sobre a arquitetura do Blazor que os componentes do Blazor renderizam sua saída para uma abstração
intermediária chamada RenderTree. A estrutura Blazor então compara o que foi renderizado com o que foi renderizado

anteriormente. As diferenças são aplicadas ao DOM. Os componentes do Blazor são dissociados de como sua saída
renderizada é aplicada. Conseqüentemente, os próprios componentes não precisam ser executados no mesmo processo

que o processo de atualização da UI. Na verdade, eles nem precisam rodar na mesma máquina.

Nos aplicativos Blazor Server, os componentes são executados no servidor em vez de no lado do cliente no navegador. Os eventos
de UI que ocorrem no navegador são enviados ao servidor por meio de uma conexão em tempo real. Os eventos são

despachado para as instâncias de componentes corretas. Os componentes são renderizados e a diferença de UI calculada é serializada e

enviada ao navegador onde é aplicada ao DOM.

9 CAPÍTULO 3 | Modelos de hospedagem de aplicativos Blazor


Machine Translated by Google

O modelo de hospedagem do Blazor Server pode parecer familiar se você usou ASP.NET AJAX e o UpdatePanel ao controle. O

controle UpdatePanel lida com a aplicação de atualizações parciais de página em resposta a eventos acionadores na página. Quando acionado, o

UpdatePanel solicita uma atualização parcial e a aplica sem a necessidade de atualizar a página. O estado da UI é gerenciado usando

ViewState. Os aplicativos Blazor Server são um pouco diferentes porque o aplicativo requer uma conexão ativa com o cliente.

Além disso, todo o estado da UI é mantido no servidor. Além dessas diferenças, os dois modelos são conceitualmente semelhantes.

Como escolher o modelo de hospedagem Blazor certo


Conforme descrito na documentação do modelo de hospedagem do Blazor, os diferentes modelos de hospedagem do Blazor têm diferentes vantagens e
desvantagens.

O modelo de hospedagem Blazor WebAssembly tem os seguintes benefícios:


Não há dependência do servidor .NET. O aplicativo está totalmente funcionando depois de baixado para o cliente.


Os recursos e capacidades do cliente são totalmente aproveitados.

• O trabalho é transferido do servidor para o cliente.

• Não é necessário um servidor Web ASP.NET Core para hospedar o aplicativo. Os cenários de implantação sem servidor são
possível (por exemplo, servir o aplicativo a partir de uma CDN).

As desvantagens do modelo de hospedagem Blazor WebAssembly são:


Os recursos do navegador restringem o aplicativo.

É necessário hardware e software cliente competente (por exemplo, suporte WebAssembly).

O tamanho do download é maior e os aplicativos demoram mais para carregar.

10 CAPÍTULO 3 | Modelos de hospedagem de aplicativos Blazor


Machine Translated by Google


O tempo de execução e o suporte a ferramentas do .NET são menos maduros. Por exemplo, existem limitações no .NET Standard
suporte e depuração.

Por outro lado, o modelo de hospedagem Blazor Server oferece os seguintes benefícios:


O tamanho do download é muito menor do que o de um aplicativo do lado do cliente e o aplicativo carrega muito mais rápido.

• O aplicativo aproveita ao máximo os recursos do servidor, incluindo o uso de qualquer API compatível com .NET.

O .NET no servidor é usado para executar o aplicativo, portanto, as ferramentas .NET existentes, como depuração, funcionam conforme o
esperado.

Clientes finos são suportados. Por exemplo, os aplicativos do lado do servidor funcionam com navegadores que não suportam WebAssembly
e em dispositivos com recursos limitados.

• A base de código .NET/C# do aplicativo, incluindo o código do componente do aplicativo, não é veiculada aos clientes.

As desvantagens do modelo de hospedagem Blazor Server são:


Maior latência da IU. Cada interação do usuário envolve um salto de rede.

Não há suporte off-line. Se a conexão do cliente falhar, o aplicativo para de funcionar.

A escalabilidade é um desafio para aplicativos com muitos usuários. O servidor deve gerenciar múltiplas conexões de clientes e lidar
com o estado do cliente.

• É necessário um servidor ASP.NET Core para servir o aplicativo. Cenários de implantação sem servidor não são possíveis. Por exemplo,
você não pode veicular o aplicativo a partir de uma CDN.

A lista anterior de compensações pode ser intimidante, mas seu modelo de hospedagem pode ser alterado posteriormente.

Independentemente do modelo de hospedagem do Blazor selecionado, o modelo do componente é o mesmo. Em princípio, os mesmos

componentes podem ser usados com qualquer modelo de hospedagem. O código do seu aplicativo não muda; no entanto, é uma boa prática

introduzir abstrações para que seus componentes permaneçam hospedando independentes do modelo.

As abstrações permitem que seu aplicativo adote com mais facilidade um modelo de hospedagem diferente.

Implante seu aplicativo


Os aplicativos ASP.NET Web Forms normalmente são hospedados no IIS em uma máquina ou cluster do Windows Server. Os aplicativos Blazor

também podem:


Ser hospedado no IIS, como arquivos estáticos ou como um aplicativo ASP.NET Core.

Aproveite a flexibilidade do ASP.NET Core para ser hospedado em diversas plataformas e infraestruturas de servidor.
Por exemplo, você pode hospedar um aplicativo Blazor usando Nginx ou Apache no Linux. Para obter mais informações sobre como
publicar e implantar aplicativos Blazor, consulte Blazor Hosting e implantação
documentação.

Na próxima seção, veremos como os projetos dos aplicativos Blazor WebAssembly e Blazor Server são configurados.

11 CAPÍTULO 3 | Modelos de hospedagem de aplicativos Blazor


Machine Translated by Google

CAPÍTULO 4

Estrutura do projeto para aplicativos


Blazor

Apesar das diferenças significativas na estrutura do projeto, o ASP.NET Web Forms e o Blazor compartilham
muitos conceitos semelhantes. Aqui, veremos a estrutura de um projeto Blazor e a compararemos com um
projeto ASP.NET Web Forms.

Para criar seu primeiro aplicativo Blazor, siga as instruções nas etapas de primeiros passos do Blazor. Você pode
seguir as instruções para criar um aplicativo Blazor Server ou um aplicativo Blazor WebAssembly hospedado no
ASP.NET Core. Exceto pela lógica específica do modelo de hospedagem, a maior parte do código em ambos os projetos é o
mesmo.

Arquivo de projeto

Os aplicativos Blazor Server são projetos .NET. O arquivo de projeto para o aplicativo Blazor Server é o mais simples
possível:

<Projeto Sdk="Microsoft.NET.Sdk.Web">

<Grupo de Propriedades>
<TargetFramework>net7.0</TargetFramework>
</PropertyGroup>

</Projeto>

O arquivo de projeto para um aplicativo Blazor WebAssembly parece um pouco mais complicado (os números exatos da versão
podem variar):

<Projeto Sdk="Microsoft.NET.Sdk.BlazorWebAssembly">

<Grupo de Propriedades>
<TargetFramework>net7.0</TargetFramework>
<ImplicitUsings>ativar</ImplicitUsings>
</PropertyGroup>

<Grupo de Itens>
<PackageReference Inclui = "Microsoft.AspNetCore.Components.WebAssembly" Versão = "7.0.0"
/>
<PackageReference Inclui = "Microsoft.AspNetCore.Components.WebAssembly.DevServer"
Versão="7.0.0" PrivateAssets="todos" />
</ItemGroup>

12 CAPÍTULO 4 | Estrutura do projeto para aplicativos Blazor


Machine Translated by Google

</Projeto>

O projeto Blazor WebAssembly tem como alvo Microsoft.NET.Sdk.BlazorWebAssembly em vez de


Microsoft.NET.Sdk.Web SDK porque eles são executados no navegador em um tempo de execução .NET baseado
em WebAssembly. Você não pode instalar o .NET em um navegador da web como em um servidor ou máquina de desenvolvedor.
Consequentemente, o projeto faz referência à estrutura Blazor usando referências de pacotes individuais.

Em comparação, um projeto padrão do ASP.NET Web Forms inclui quase 300 linhas de XML em seu .csproj
arquivo, a maior parte listando explicitamente os vários arquivos de código e conteúdo do projeto. Desde o lançamento
do .NET 5, os aplicativos Blazor Server e Blazor WebAssembly podem compartilhar facilmente um tempo de execução
unificado.

Embora tenham suporte, as referências de assembly individuais são menos comuns em projetos .NET. A maioria das
dependências do projeto são tratadas como referências de pacote NuGet. Você só precisa fazer referência às dependências
de pacotes de nível superior em projetos .NET. As dependências transitivas são incluídas automaticamente. Em vez de usar o
arquivo packages.config comumente encontrado em projetos ASP.NET Web Forms para fazer referência a pacotes, as
referências de pacote são adicionadas ao arquivo de projeto usando o elemento <PackageReference> .

<Grupo de Itens>
<PackageReference Inclui = "Newtonsoft.Json" Versão = "13.0.2" />
</ItemGroup>

Ponto de entrada
O ponto de entrada do aplicativo Blazor Server é definido no arquivo Program.cs , como você veria em um aplicativo de
console. Quando o aplicativo é executado, ele cria e executa uma instância de host da Web usando padrões específicos
para aplicativos da Web. O host gerencia o ciclo de vida do aplicativo Blazor Server e configura serviços em nível de host.
Exemplos de tais serviços são configuração, registro em log, injeção de dependência e servidor HTTP. Este código é
principalmente clichê e geralmente permanece inalterado.

usando BlazorApp3.Areas.Identity;
usando BlazorApp3.Data;
usando Microsoft.AspNetCore.Components.Authorization;
usando Microsoft.AspNetCore.Identity;
usando Microsoft.EntityFrameworkCore;

var construtor = WebApplication.CreateBuilder(args);

//Adiciona serviços ao contêiner.


var connectionString = construtor.Configuration.GetConnectionString("DefaultConnection");
construtor.Services.AddDbContext<ApplicationDbContext>(opções =>
opções.UseSqlServer(connectionString));
construtor.Services.AddDatabaseDeveloperPageExceptionFilter();
construtor.Services.AddDefaultIdentity<IdentityUser>(options =>
options.SignIn.RequireConfirmedAccount = true)
.AddEntityFrameworkStores<ApplicationDbContext>();
construtor.Services.AddRazorPages();
construtor.Services.AddServerSideBlazor();
construtor.Services.AddScoped<AuthenticationStateProvider,
RevalidatingIdentityAuthenticationStateProvider<IdentityUser>>();
construtor.Services.AddSingleton<WeatherForecastService>();

13 CAPÍTULO 4 | Estrutura do projeto para aplicativos Blazor


Machine Translated by Google

var app= builder.Build();

// Configure o pipeline de solicitação HTTP.


if (app.Environment.IsDevelopment())
{
app.UseMigrationsEndPoint();
}
outro
{
app.UseExceptionHandler("/Erro");
// O valor padrão do HSTS é 30 dias. Talvez você queira alterar isso para cenários de produção, consulte
https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}

app.UseHttpsRedirection();

app.UseStaticFiles();

app.UseRouting();

app.UseAuthorization();

app.MapControllers();
app.MapBlazorHub();
app.MapFallbackToPage("/_Host");

app.Run();

Os aplicativos Blazor WebAssembly também definem um ponto de entrada em Program.cs. O código parece um pouco diferente.
O código é semelhante porque configura o host do aplicativo para fornecer os mesmos serviços em nível de host ao aplicativo. O
host do aplicativo WebAssembly, entretanto, não configura um servidor HTTP porque ele é executado diretamente no navegador.

Os aplicativos Blazor não usam um arquivo Global.asax para definir a lógica de inicialização do aplicativo. Em vez disso, essa
lógica está contida em Program.cs ou em uma classe de inicialização relacionada referenciada em Program.cs. De qualquer forma,
esse código é usado para configurar o aplicativo e quaisquer serviços específicos do aplicativo.

Em um aplicativo Blazor Server, o arquivo Program.cs mostrado é usado para configurar o ponto de extremidade para a conexão
em tempo real usada pelo Blazor entre os navegadores do cliente e o servidor.

Em um aplicativo Blazor WebAssembly, o arquivo Program.cs define os componentes raiz do aplicativo e onde eles devem ser
renderizados:

usando BlazorApp1;
usando Microsoft.AspNetCore.Components.Web;
usando Microsoft.AspNetCore.Components.WebAssembly.Hosting;

var construtor = WebAssemblyHostBuilder.CreateDefault(args);


construtor.RootComponents.Add<App>("#app");
construtor.RootComponents.Add<HeadOutlet>("head::after");

construtor.Services.AddScoped (sp => novo HttpClient { BaseAddress = novo


Uri(builder.HostEnvironment.BaseAddress) });

aguarde construtor.Build().RunAsync();

14 CAPÍTULO 4 | Estrutura do projeto para aplicativos Blazor


Machine Translated by Google

Arquivos estáticos

Ao contrário dos projetos ASP.NET Web Forms, nem todos os arquivos em um projeto Blazor podem ser solicitados como arquivos estáticos.

Somente os arquivos na pasta wwwroot são endereçáveis pela web. Esta pasta é conhecida como “raiz da web” do aplicativo. Qualquer coisa

fora da raiz da web do aplicativo não pode ser endereçada pela web. Esta configuração fornece um nível adicional de segurança que evita a

exposição acidental de arquivos de projeto na web.

Configuração
A configuração em aplicativos ASP.NET Web Forms normalmente é feita usando um ou mais arquivos web.config .

Os aplicativos Blazor normalmente não possuem arquivos web.config . Se o fizerem, o arquivo será usado apenas para definir

configurações específicas do IIS quando hospedado no IIS. Em vez disso, os aplicativos Blazor Server usam as abstrações de configuração do

ASP.NET Core. (Atualmente, os aplicativos Blazor WebAssembly não oferecem suporte às mesmas abstrações de configuração, mas isso pode

ser um recurso adicionado no futuro.) Por exemplo, o aplicativo Blazor Server padrão armazena algumas configurações em appsettings.json .

{
"Registro": {
"LogNível": {
"Padrão": "Informações",
"Microsoft": "Aviso",
"Microsoft.Hosting.Lifetime": "Informações"
}
},
"AllowedHosts": "*"
}

Você aprenderá mais sobre configuração em projetos ASP.NET Core na seção Configuração .

Componentes de navalha
A maioria dos arquivos em projetos Blazor são arquivos .razor . Razor é uma linguagem de modelo baseada em HTML e C# usada para gerar

UI da web dinamicamente. Os arquivos .razor definem componentes que compõem a IU do aplicativo. Na maior parte, os componentes são

idênticos para os aplicativos Blazor Server e Blazor WebAssembly. Os componentes do Blazor são análogos aos controles de usuário no

ASP.NET Web Forms.

Cada arquivo de componente do Razor é compilado em uma classe .NET quando o projeto é compilado. A classe gerada captura o estado do

componente, lógica de renderização, métodos de ciclo de vida, manipuladores de eventos e outras lógicas.

Você aprenderá mais sobre a criação de componentes em Construindo componentes de UI reutilizáveis com Blazor
seção.

Os arquivos *_Imports.razor* não são arquivos de componentes do Razor. Em vez disso, eles definem um conjunto de diretivas Razor para importar

para outros arquivos .razor dentro da mesma pasta e em suas subpastas. Por exemplo, um arquivo *_Imports.razor* é uma

forma convencional de adicionar diretivas using para namespaces comumente usados:

@usando System.Net.Http
@usando System.Net.Http.Json
@usando Microsoft.AspNetCore.Components.Forms
@usando Microsoft.AspNetCore.Components.Routing

15 CAPÍTULO 4 | Estrutura do projeto para aplicativos Blazor


Machine Translated by Google

@usando Microsoft.AspNetCore.Components.Web
@usando Microsoft.AspNetCore.Components.Web.Virtualization
@usando Microsoft.AspNetCore.Components.WebAssembly.Http
@usando Microsoft.JSInterop
@usando BlazorApp1
@usando BlazorApp1.Shared

Páginas

Onde estão as páginas nos aplicativos Blazor? O Blazor não define uma extensão de arquivo separada para
páginas endereçáveis, como os arquivos .aspx em aplicativos ASP.NET Web Forms. Em vez disso, as páginas são
definidas atribuindo rotas aos componentes. Uma rota normalmente é atribuída usando a diretiva @page Razor. Por
exemplo, o componente Counter criado no arquivo Pages/ Counter.razor define o seguinte
rota:

@página "/ contador"

O roteamento no Blazor é tratado no lado do cliente, não no servidor. Conforme o usuário navega no navegador, o Blazor
intercepta a navegação e então renderiza o componente com a rota correspondente.

As rotas do componente não são inferidas atualmente pelo local do arquivo do componente, como acontece com
páginas .aspx ou páginas ASP.NET Core Razor. Este recurso pode ser adicionado no futuro. Cada rota deve ser
especificada explicitamente no componente. Armazenar componentes roteáveis em uma pasta Pages não tem
significado especial e é puramente uma convenção.

Você aprenderá mais sobre roteamento no Blazor na seção Páginas, roteamento e layouts .

Disposição

Em aplicativos ASP.NET Web Forms, um layout de página comum é tratado usando páginas mestras (Site.Master). Nos
aplicativos Blazor, o layout da página é tratado usando componentes de layout (Shared/ MainLayout.razor). Os componentes
de layout são discutidos com mais detalhes na seção Página, roteamento e layouts .

Blazor de inicialização

Para inicializar o Blazor, o aplicativo deve:


Especifique onde na página o componente raiz (App.Razor) deve ser renderizado.

• Adicione o script de estrutura Blazor correspondente.

No aplicativo Blazor Server, a página host do componente raiz é definida no arquivo *_Host.cshtml*. Este arquivo define uma
Razor Page, não um componente. As páginas Razor usam a sintaxe Razor para definir uma página endereçável pelo
servidor, muito parecida com uma página .aspx .

@página "/"
@namespace BlazorApp3.Pages
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
@{
Layout = "_Layout";

16 CAPÍTULO 4 | Estrutura do projeto para aplicativos Blazor


Machine Translated by Google

<component type="typeof(App)" render-mode="ServerPrerendered" />

O atributo render-mode é usado para definir onde um componente de nível raiz deve ser renderizado. A opção
RenderMode indica a maneira como o componente deve ser renderizado. A tabela a seguir descreve as opções de
RenderMode suportadas .

Opção Descrição

RenderMode.Servidor Renderizado interativamente quando uma conexão com o navegador


é estabelecida

RenderMode.ServerPrerendered Primeiro pré-renderizado e depois renderizado interativamente

RenderMode.Static Renderizado como conteúdo estático

O arquivo *_Layout.cshtml* inclui o HTML padrão do aplicativo e seus componentes.

@usando Microsoft.AspNetCore.Components.Web
@namespace BlazorApp3.Pages
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers

<!DOCTYPEhtml>
<html lang="pt">
<head>
<meta charset="utf-8" /> <meta
name="viewport" content="width=device-width, escala inicial=1.0" /> <base href="~/" /> <link rel="
folha de estilo" href="css/
bootstrap/bootstrap.min.css" /> <link href="css/site.css" rel="stylesheet" /> <link
href="BlazorApp3.styles.css" rel="folha de estilo " />
<component type="typeof(HeadOutlet)" render-mode="ServerPrerendered" /
> </head> <body> @RenderBody()

<div id="blazor-error-ui">
<environment include="Staging,Production"> Ocorreu um
erro. Este aplicativo pode não responder mais até ser recarregado. </environment> <environment

include="Desenvolvimento">
Ocorreu uma exceção não tratada. Consulte as ferramentas de desenvolvimento do navegador
para obter detalhes.
</environment> <a href=""
class="reload">Recarregar</a>
<a class="dismiss"> </a> </div>

<script src="_framework/blazor.server.js"></script> </body> </html>

A referência do script a *_framework/blazor.server.js* estabelece a conexão em tempo real com o servidor e, em


seguida, trata de todas as interações do usuário e atualizações da UI.

No aplicativo Blazor WebAssembly, a página host é um arquivo HTML estático simples em wwwroot/ index.html.
O elemento <div> com id denominado app é usado para indicar onde o componente raiz deve ser renderizado.

17 CAPÍTULO 4 | Estrutura do projeto para aplicativos Blazor


Machine Translated by Google

<!DOCTYPEhtml >
<html lang="pt">

<cabeça>
<meta charset="utf-8" />
<meta name="viewport" content="largura=largura do dispositivo, escala inicial=1,0, escala máxima=1,0,
escalonável pelo usuário=não" / >
<title>BlazorApp1</title>
<base href="/" />
<link href="css/bootstrap/bootstrap.min.css" rel="stylesheet" />
<link href="css/app.css" rel="stylesheet" />
<link href="BlazorApp1.styles.css" rel="stylesheet" />
</head>

<corpo>
<div id="app">Carregando...</div>

<div id="blazor-error-ui">
Ocorreu um erro não tratado.
<a href="" class="reload"> Recarregar</a>
<a class="dispensar"> </a>
</div>
<script src="_framework/blazor.webassembly.js"></script>
</body>

</html>

O componente raiz a ser renderizado é especificado no arquivo Program.cs do aplicativo com a flexibilidade de registrar serviços por meio de

injeção de dependência. Para obter mais informações, consulte injeção de dependência do ASP.NET Core Blazor .

var construtor = WebAssemblyHostBuilder.CreateDefault(args);


construtor.RootComponents.Add<App>("#app");
construtor.RootComponents.Add<HeadOutlet>("head::after");

Saída de compilação

Quando um projeto Blazor é compilado, todos os componentes e arquivos de código do Razor são compilados em um único

assembly. Ao contrário dos projetos ASP.NET Web Forms, o Blazor não oferece suporte à compilação em tempo de execução da lógica da

interface do usuário.

Execute o aplicativo com Hot Reload

Para executar o aplicativo Blazor Server, pressione F5 no Visual Studio para executar com o depurador anexado ou Ctrl + F5 para executar sem

o depurador anexado.

Para executar o aplicativo Blazor WebAssembly, escolha uma das seguintes abordagens:


Execute o projeto cliente diretamente usando o servidor de desenvolvimento.

Execute o projeto do servidor ao hospedar o aplicativo com ASP.NET Core.

Os aplicativos Blazor WebAssembly podem ser depurados no navegador e no Visual Studio. Consulte Depurar ASP.NET Core Blazor

WebAssembly para detalhes.

18 CAPÍTULO 4 | Estrutura do projeto para aplicativos Blazor


Machine Translated by Google

Os aplicativos Blazor Server e Blazor WebAssembly suportam Hot Reload no Visual Studio. Hot Reload é um recurso
que atualiza automaticamente as alterações feitas em um aplicativo Blazor ao vivo, no navegador. Você pode
alternar se o Hot Reload está ativado em seu ícone na barra de ferramentas:

Selecionar o cursor ao lado do ícone revela opções adicionais. Você pode ativar ou desativar o Hot Reload, reiniciar
o aplicativo e definir se o Hot Reload deve ocorrer sempre que um arquivo for salvo.

Você também pode acessar opções de configuração adicionais. A caixa de diálogo de configuração permite
especificar se o Hot Reload deve ser habilitado durante a depuração (junto com Editar e Continuar), ao iniciar
sem depuração ou quando um arquivo é salvo.

19 CAPÍTULO 4 | Estrutura do projeto para aplicativos Blazor


Machine Translated by Google

O “loop interno do desenvolvedor” foi bastante simplificado com o Hot Reload. Sem o Hot Reload, um desenvolvedor
do Blazor normalmente precisaria reiniciar e executar novamente o aplicativo após cada alteração, navegando até a parte
apropriada do aplicativo conforme necessário. Com o Hot Reload, alterações podem ser feitas no aplicativo em execução
sem a necessidade de reiniciar na maioria dos casos. O Hot Reload ainda mantém o estado das páginas, portanto, não há
necessidade de inserir novamente os valores do formulário ou colocar o aplicativo de volta onde você precisa.

20 CAPÍTULO 4 | Estrutura do projeto para aplicativos Blazor


Machine Translated by Google

CAPÍTULO 5

Inicialização do aplicativo

Os aplicativos escritos para ASP.NET normalmente têm um arquivo global.asax.cs que define o evento
Application_Start que controla quais serviços são configurados e disponibilizados para renderização de HTML e
processamento de .NET. Este capítulo analisa como as coisas são um pouco diferentes com o ASP.NET Core e o
Blazor Server.

Application_Start e Formulários Web


O método Application_Start dos formulários da web padrão cresceu em função ao longo dos anos para lidar com muitas
tarefas de configuração. Um novo projeto de formulários web com o modelo padrão no Visual Studio 2022 agora contém
a seguinte lógica de configuração:


RouteConfig - Roteamento de URL do aplicativo

BundleConfig - agrupamento e minificação de CSS e JavaScript

Cada um desses arquivos individuais reside na pasta App_Start e é executado apenas uma vez no início do nosso
aplicativo. RouteConfig no modelo de projeto padrão adiciona FriendlyUrlSettings para formulários da web para permitir
que URLs de aplicativos omitam a extensão de arquivo .ASPX . O modelo padrão também contém uma diretiva que fornece
códigos de status de redirecionamento HTTP permanentes (HTTP 301) para as páginas .ASPX para a URL amigável com
o nome do arquivo que omite a extensão.

Com o ASP.NET Core e o Blazor, esses métodos são simplificados e consolidados no Startup
classe ou são eliminados em favor de tecnologias comuns da web.

Estrutura de inicialização do servidor Blazor


Os aplicativos Blazor Server residem em um ASP.NET Core 3.0 ou versão posterior. Os aplicativos Web ASP.NET Core
são configurados em Program.cs ou por meio de um par de métodos na classe Startup.cs . Um exemplo de arquivo
Program.cs é mostrado abaixo:

usando BlazorApp1.Data;
usando Microsoft.AspNetCore.Components;
usando Microsoft.AspNetCore.Components.Web;

var construtor = WebApplication.CreateBuilder(args);

//Adiciona serviços ao contêiner.


construtor.Services.AddRazorPages();
construtor.Services.AddServerSideBlazor();
construtor.Services.AddSingleton<WeatherForecastService>();

21 CAPÍTULO 5 | Inicialização do aplicativo


Machine Translated by Google

var app= builder.Build();

// Configure o pipeline de solicitação HTTP.


if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Erro");
// O valor padrão do HSTS é 30 dias. Talvez você queira alterar isso para cenários de produção, consulte
https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}

app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.MapBlazorHub();
app.MapFallbackToPage("/_Host");

app.Run();

Os serviços necessários do aplicativo são adicionados à coleção de serviços da instância WebApplicationBuilder .


É assim que os vários serviços da estrutura do ASP.NET Core são configurados com o contêiner de injeção de dependência
integrado da estrutura. Os vários métodos builder.Services.Add* adicionam serviços que permitem recursos como autenticação,
páginas razor, roteamento do controlador MVC, SignalR e interações do Blazor Server, entre muitos outros. Este método não
era necessário em formulários web, pois a análise e manipulação dos arquivos ASPX, ASCX, ASHX e ASMX foram definidas
referenciando o ASP.NET no arquivo de configuração web.config. Mais informações sobre injeção de dependência no ASP.NET
Core estão disponíveis na documentação online.

Depois que o aplicativo foi criado pelo construtor, o restante das chamadas no aplicativo configuram seu pipeline HTTP.
Com essas chamadas, declaramos de cima a baixo o Middleware que irá tratar cada requisição enviada à nossa aplicação. A maioria
desses recursos na configuração padrão foram espalhados pelos arquivos de configuração dos formulários da web e agora
estão em um só lugar para facilitar a referência.

A configuração da página de erro personalizada não é mais colocada em um arquivo web.config , mas agora está configurada
para ser sempre mostrada se o ambiente do aplicativo não estiver rotulado como Desenvolvimento.
Além disso, os aplicativos ASP.NET Core agora estão configurados para servir páginas seguras com TLS por padrão com a chamada
do método UseHttpsRedirection .

Em seguida, uma chamada de método de configuração inesperada é feita para UseStaticFiles. No ASP.NET Core, o suporte para
solicitações de arquivos estáticos (como JavaScript, CSS e arquivos de imagem) deve ser explicitamente habilitado, e somente os
arquivos na pasta wwwroot do aplicativo podem ser endereçados publicamente por padrão.

A próxima linha é a primeira que replica uma das opções de configuração dos formulários web: UseRouting.
Este método adiciona o roteador ASP.NET Core ao pipeline e pode ser configurado aqui ou nos arquivos individuais para os quais
pode considerar o roteamento. Mais informações sobre configuração de roteamento podem ser encontradas na seção Roteamento.

As chamadas app.Map* finais nesta seção definem os pontos de extremidade que o ASP.NET Core está escutando. Essas rotas
são os locais acessíveis pela web que você pode acessar no servidor web e receber algum conteúdo manipulado pelo .NET
e devolvido a você. A primeira entrada, MapBlazorHub configura um hub SignalR para uso no fornecimento de conexão persistente
e em tempo real ao servidor onde o estado e a renderização dos componentes Blazor são tratados. A chamada do método
MapFallbackToPage indica o local acessível pela Web da página que inicia o aplicativo Blazor e também configura o aplicativo
para

22 CAPÍTULO 5 | Inicialização do aplicativo


Machine Translated by Google

lidar com solicitações de links diretos do lado do cliente. Você verá esse recurso em funcionamento se abrir um
navegador e navegar diretamente para a rota manipulada pelo Blazor em seu aplicativo, como /counter no modelo
de projeto padrão. A solicitação é tratada pela página substituta *_Host.cshtml*, que então executa o roteador Blazor
e renderiza a página do contador.

A última linha inicia o aplicativo, algo que não era necessário em formulários web (já que dependia do IIS para funcionar).

Atualizando o processo BundleConfig


As tecnologias para agrupar ativos, como folhas de estilo CSS e arquivos JavaScript, mudaram significativamente, com
outras tecnologias fornecendo ferramentas e técnicas em rápida evolução para gerenciar esses recursos. Para
esse fim, recomendamos o uso de uma ferramenta de linha de comando do Node, como Grunt/Gulp/WebPack,
para empacotar seus ativos estáticos.

As ferramentas de linha de comando Grunt, Gulp e WebPack e suas configurações associadas podem ser adicionadas
ao seu aplicativo e o ASP.NET Core ignorará silenciosamente esses arquivos durante o processo de criação do
aplicativo. Você pode adicionar uma chamada para executar suas tarefas adicionando um Target dentro do arquivo do
seu projeto com sintaxe semelhante à seguinte, que acionaria um script gulp e o alvo mínimo dentro desse script:

<Target Name="MyPreCompileTarget" BeforeTargets="Build">


<Exec Command="gulp min" />
</alvo>

Mais detalhes sobre ambas as estratégias para gerenciar seus arquivos CSS e JavaScript estão disponíveis em Agrupar
e reduzir ativos estáticos no ASP.NET Core documentação.

23 CAPÍTULO 5 | Inicialização do aplicativo


Machine Translated by Google

CAPÍTULO 6

Crie componentes
de UI reutilizáveis com Blazor
Uma das vantagens do ASP.NET Web Forms é como ele permite o encapsulamento de partes reutilizáveis do código da interface do

usuário (UI) em controles de UI reutilizáveis. Os controles de usuário personalizados podem ser definidos na marcação usando

arquivos .ascx . Você também pode criar controles de servidor elaborados em código com suporte total do designer.

Blazor também oferece suporte ao encapsulamento de UI por meio de componentes. Um componente:

• É um pedaço independente da UI.


Mantém seu próprio estado e lógica de renderização.

Pode definir manipuladores de eventos de UI, vincular-se a dados de entrada e gerenciar seu próprio ciclo de vida.

Normalmente é definido em um arquivo .razor usando a sintaxe Razor.

Uma introdução ao Navalha


Razor é uma linguagem de modelagem de marcação leve baseada em HTML e C#. Com o Razor, você pode fazer uma transição

perfeita entre marcação e código C# para definir a lógica de renderização de seu componente. Quando o arquivo .razor é compilado, a

lógica de renderização é capturada de forma estruturada em uma classe .NET. O nome da classe compilada é obtido do nome do

arquivo .razor . O namespace é obtido do namespace padrão do projeto e do caminho da pasta, ou você pode especificar

explicitamente o namespace usando a diretiva @namespace (mais sobre as diretivas do Razor abaixo).

A lógica de renderização de um componente é criada usando marcação HTML normal com lógica dinâmica adicionada usando C#. O

caractere @ é usado para fazer a transição para C#. O Razor normalmente é inteligente para descobrir quando você voltou para HTML.

Por exemplo, o componente a seguir renderiza uma tag <p> com a hora atual:

<p>@DateTime.Agora</p>

Para especificar explicitamente o início e o fim de uma expressão C#, use parênteses:

<p>@(DateTime.Agora)</p>

O Razor também facilita o uso do fluxo de controle C# em sua lógica de renderização. Por exemplo, você pode renderizar

condicionalmente algum HTML assim:

24 CAPÍTULO 6 | Crie componentes de UI reutilizáveis com Blazor


Machine Translated by Google

@if (valor% 2 == 0)
{
<p>O valor foi par.</p>
}

Ou você pode gerar uma lista de itens usando um loop foreach C# normal como este:

<ul>
@foreach (var item em itens)
{
<li>@item.Text</li>
}
</ul>

As diretivas Razor, como as diretivas em ASP.NET Web Forms, controlam muitos aspectos de como um componente
Razor é compilado. Os exemplos incluem os componentes:

• Espaço para nome


• Classe base

Interfaces implementadas

Parâmetros genéricos

Namespaces importados
• Rotas

As diretivas Razor começam com o caractere @ e normalmente são usadas no início de uma nova linha no início do arquivo.
Por exemplo, a diretiva @namespace define o namespace do componente:

@namespace MeuComponentNamespace

A tabela a seguir resume as várias diretivas Razor usadas no Blazor e seus equivalentes em ASP.NET Web Forms, se
existirem.

Diretiva Descrição Exemplo Equivalente a formulários da Web

@attribute Adiciona um atributo de nível @atributo Nenhum

de classe ao [Autorizar]
componente

@código Adiciona classe @código {...} <script


membros para o runat="servidor">...</script>
componente

@implements Implementa a interface @implementa Usar code-behind


especificada IDisponível

@herda Herda do @herda <%@ Controle


classe base MeuComponentBase Herda = "MyUserControlBase" %>
especificada

@injetar Injeta um serviço no @inject IJSRuntime JS Nenhum

componente

25 CAPÍTULO 6 | Crie componentes de UI reutilizáveis com Blazor


Machine Translated by Google

Diretiva Descrição Exemplo Equivalente a formulários da Web

@layout Especifica um @layoutMainLayout <%@ Page


MasterPageFile="~/Site.Master" %>
componente de layout
para o componente

@namespace Define o @namespace Nenhum


Meu Namespace
namespace para o
componente

@página Especifica a rota para o @página "/produto/{id}" <%@ Página %>

componente

@typeparam Especifica um parâmetro de @typeparam TItem Usar code-behind

tipo genérico para o


componente

@usando Especifica @usando Adicionar namespace em web.config


MeuComponentNamespace
um namespace
para trazer para o escopo

Os componentes do Razor também fazem uso extensivo de atributos de diretiva em elementos para controlar vários aspectos
de como os componentes são compilados (manipulação de eventos, ligação de dados, referências de componentes e
elementos e assim por diante). Todos os atributos da diretiva seguem uma sintaxe genérica comum, onde os valores entre
parênteses são opcionais:

@diretiva(-sufixo(:nome))(="valor")

A tabela a seguir resume os vários atributos das diretivas Razor usadas no Blazor.

Atributo Descrição Exemplo

@attributes Renderiza um dicionário de atributos <input @attributes="ExtraAttributes" />

@vincular Cria uma ligação de dados bidirecional <input @bind="nomedeusuário"


@bind:event="oninput" />

@on{event} Adiciona um manipulador de eventos para o <button @onclick="IncrementCount">Clique em mim!</button>

evento especificado

@chave Especifica uma chave a ser usada pelo <DetalhesEditor @key="person"


Detalhes = "pessoa.Detalhes" />
algoritmo de comparação para preservar
elementos em uma coleção

@ref Captura uma referência ao <MyDialog @ref="myDialog" />

componente ou elemento HTML

Os vários atributos de diretiva usados pelo Blazor (@onclick, @bind, @ref e assim por diante) são abordados nas seções abaixo e
nos capítulos posteriores.

Muitas das sintaxes usadas em arquivos .aspx e .ascx possuem sintaxes paralelas no Razor. Abaixo está uma comparação
simples das sintaxes para ASP.NET Web Forms e Razor.

26 CAPÍTULO 6 | Crie componentes de UI reutilizáveis com Blazor


Machine Translated by Google

Recurso Formulários da Web Sintaxe Navalha Sintaxe

Diretivas <%@ Página %> @[diretiva] @page


<%@ [diretiva] %>

Blocos de código <% %> <% int x = 123; %> @{ } @{ int x = 123; }

<%:%> <%:DateTime.Agora @DateTime.Agora


Expressões Implícito: @
%> @(DataHora.Agora)
Explícito: @()
(codificado em HTML)

Comentários <%-- --%> <%-- Comentado -- @* *@ @* Comentou *@


%>

<%# %> <%# Vincular("Nome") @vincular <input


Ligação de dados
%> @bind="nomedeusuário" />

Para adicionar membros à classe de componente Razor, use a diretiva @code . Essa técnica é semelhante ao uso de um bloco <script

runat="server">...</script> em um controle de usuário ASP.NET Web Forms ou

página.

@código {
contagem interna = 0;

void IncrementCount()
{
contar++;
}
}

Como o Razor é baseado em C#, ele deve ser compilado de dentro de um projeto C# (.csproj). Você não pode compilar

arquivos .razor de um projeto Visual Basic (.vbproj). Você ainda pode fazer referência a projetos do Visual Basic do seu projeto Blazor. O

oposto também é verdadeiro.

Para obter uma referência completa da sintaxe do Razor, consulte Referência de sintaxe do Razor para ASP.NET Core.

Usar componentes
Além do HTML normal, os componentes também podem usar outros componentes como parte de sua lógica de renderização.

A sintaxe para usar um componente no Razor é semelhante a usar um controle de usuário em um aplicativo ASP.NET Web Forms. Os

componentes são especificados usando uma tag de elemento que corresponde ao nome do tipo do componente.

Por exemplo, você pode adicionar um componente Counter como este:

<Contador />

Ao contrário dos Web Forms do ASP.NET, os componentes do Blazor:


Não use um prefixo de elemento (por exemplo, asp:).

Não exige cadastro na página ou no web.config.

27 CAPÍTULO 6 | Crie componentes de UI reutilizáveis com Blazor


Machine Translated by Google

Pense nos componentes do Razor como você faria com os tipos .NET, porque é exatamente isso que eles são. Se a
montagem que contém o componente for referenciada, o componente estará disponível para uso. Para colocar o namespace
do componente no escopo, aplique a diretiva @using :

@usando MyComponentLib

<Contador />

Como visto nos projetos padrão do Blazor, é comum colocar diretivas @using em um arquivo *_Imports.razor* para que sejam
importadas para todos os arquivos .razor no mesmo diretório e em diretórios filhos.

Se o namespace de um componente não estiver no escopo, você poderá especificar um componente usando seu nome
completo de tipo, como em C#:

<MyComponentLib.Counter />

Modifique o título da página dos componentes


Ao criar aplicativos estilo SPA, é comum que partes de uma página sejam recarregadas sem recarregar a página inteira. Mesmo
assim, pode ser útil alterar o título da página com base no componente que está carregado no momento. Isso pode ser
feito incluindo a tag <PageTitle> na página Razor do componente:

@página "/"
<PageTitle>Página inicial</PageTitle>

O conteúdo deste elemento pode ser dinâmico, mostrando, por exemplo, a contagem atual de mensagens:

<PageTitle>@MessageCount mensagens</PageTitle>

Observe que se vários componentes em uma determinada página incluírem tags <PageTitle> , apenas o último será exibido (já
que cada um substituirá o anterior).

Parâmetros do componente
No ASP.NET Web Forms, você pode fluir parâmetros e dados para controles usando propriedades públicas. Essas propriedades
podem ser definidas na marcação usando atributos ou definidas diretamente no código. Os componentes do Razor funcionam
de maneira semelhante, embora as propriedades do componente também devam ser marcadas com o [Parâmetro]
atributo a ser considerado parâmetro de componente.

O seguinte componente Counter define um parâmetro de componente chamado IncrementAmount que pode ser usado para
especificar a quantidade que o contador deve ser incrementado cada vez que o botão é clicado.

<h1>Contador</h1>

<p>Contagem atual: @currentCount</p>

<button class="btn btn-primary" @onclick="IncrementCount">Clique em mim</button>

@código {

28 CAPÍTULO 6 | Crie componentes de UI reutilizáveis com Blazor


Machine Translated by Google

int ContagemAtual = 0;

[Parâmetro]
public int IncrementAmount { get; definir; } = 1;

void IncrementCount()
{
currentCount+=IncrementAmount;
}
}

Para especificar um parâmetro de componente no Blazor, use um atributo como faria em ASP.NET Web Forms:

<Counter IncrementAmount="10" />

Parâmetros de string de consulta


Os componentes do Razor também podem aproveitar valores da cadeia de caracteres de consulta da página em que são
renderizados como fonte de parâmetro. Para habilitar isso, adicione o atributo [SupplyParameterFromQuery] ao parâmetro.
Por exemplo, a seguinte definição de parâmetro obteria seu valor da solicitação no formato ?IncBy=2:

[Parâmetro]
[SupplyParameterFromQuery(Nome = "IncBy")]
public int IncrementAmount { get; definir; } = 1;

Se você não fornecer um Nome personalizado no atributo [SupplyParameterFromQuery] , por padrão ele corresponderá
ao nome da propriedade (IncrementAmount neste caso).

Componentes e limites de erro


Por padrão, os aplicativos Blazor detectarão exceções não tratadas e mostrarão uma mensagem de erro na parte inferior
da página sem detalhes adicionais. Para restringir as partes do aplicativo que são afetadas por um erro não
tratado, por exemplo, para limitar o impacto a um único componente, a tag <ErrorBoundary> pode ser agrupada em torno
das declarações do componente.

Por exemplo, para se proteger contra possíveis exceções geradas pelo componente Counter , declare-o dentro de um
<ErrorBoundary> e, opcionalmente, especifique uma mensagem a ser exibida se houver uma exceção:

<Limite de erro>
<Conteúdo Infantil>
<Contador />
</ChildContent>
<ErroConteúdo>
Ops! O contador não está funcionando no momento; por favor, tente novamente mais tarde.
</ErrorContent>
</ErrorBoundary>

Se você não precisar especificar o conteúdo de erro personalizado, basta agrupar o componente diretamente:

<Limite de erro>
<Contador />
</ErrorBoundary>

29 CAPÍTULO 6 | Crie componentes de UI reutilizáveis com Blazor


Machine Translated by Google

Uma mensagem padrão informando “Ocorreu um erro”. será exibido se ocorrer uma exceção não tratada no componente
encapsulado.

Manipuladores de eventos

Tanto o ASP.NET Web Forms quanto o Blazor fornecem um modelo de programação baseado em eventos para lidar com
eventos de UI. Exemplos de tais eventos incluem cliques em botões e entrada de texto. No ASP.NET Web Forms, você usa
controles de servidor HTML para manipular eventos de UI expostos pelo DOM ou pode manipular eventos expostos por controles
de servidor web. Os eventos são apresentados no servidor por meio de solicitações de postback de formulário. Considere o
seguinte exemplo de clique em botão de Web Forms:

Contador.ascx

<asp:Button ID="ClickMeButton" runat="server" Text="Clique em mim!"


OnClick="ClickMeButton_Click" />

Contador.ascx.cs

Contador de classe parcial pública : System.Web.UI.UserControl


{
protegido vazio ClickMeButton_Click (objeto remetente, EventArgs e)
{
Console.WriteLine("O botão foi clicado!");
}
}

No Blazor, você pode registrar manipuladores para eventos de UI DOM diretamente usando atributos de diretiva no formato
@on{event}. O espaço reservado {event} representa o nome do evento. Por exemplo, você pode ouvir cliques em botões como
este:

<button @onclick="OnClick">Clique em mim!</button>

@código {
void OnClick()
{
Console.WriteLine("O botão foi clicado!");
}
}

Os manipuladores de eventos podem aceitar um argumento opcional específico do evento para fornecer mais informações
sobre o evento. Por exemplo, eventos de mouse podem receber um argumento MouseEventArgs , mas isso não é obrigatório.

<button @onclick="OnClick">Clique em mim!</button>

@código {
void OnClick(MouseEventArgs e)
{
Console.WriteLine($"Mouse clicado em {e.ScreenX}, {e.ScreenY}.");
}
}

Em vez de se referir a um grupo de métodos para um manipulador de eventos, você pode usar uma expressão lambda.
Uma expressão lambda permite fechar outros valores no escopo.

30 CAPÍTULO 6 | Crie componentes de UI reutilizáveis com Blazor


Machine Translated by Google

@foreach (var buttonLabel em buttonLabels) {

<button @onclick="() => Console.WriteLine($"O botão {buttonLabel} foi


clicado!")">@buttonLabel</button> }

Os manipuladores de eventos podem ser executados de forma síncrona ou assíncrona. Por exemplo, o seguinte manipulador
de eventos OnClick é executado de forma assíncrona:

<button @onclick="OnClick">Clique em mim!</button>

@code
{ tarefa assíncrona
OnClick() {
var resultado = aguarda Http.GetAsync("api/valores");
}
}

Depois que um evento é tratado, o componente é renderizado para dar conta de quaisquer alterações de estado do componente.
Com manipuladores de eventos assíncronos, o componente é renderizado imediatamente após a conclusão da execução
do manipulador. O componente é renderizado novamente após a conclusão da tarefa assíncrona . Este modo de execução
assíncrona oferece uma oportunidade de renderizar alguma UI apropriada enquanto a tarefa assíncrona ainda está em
andamento.

<button @onclick="ShowMessage">Receber mensagem</button>

@if (showMessage) {

@if (mensagem == nulo) {

<p><em>Carregando...</em></p>

}
outro {
<p>A mensagem é: @message</p>
}
}

@código
{
bool showMessage = falso;
mensagem de sequência;

tarefa assíncrona pública ShowMessage()


{
mostrarMensagem = true;
mensagem = aguarda MessageService.GetMessageAsync();
}
}

Os componentes também podem definir seus próprios eventos definindo um parâmetro de componente do tipo
EventCallback<TValue>. Os retornos de chamada de eventos oferecem suporte a todas as variações de manipuladores de
eventos da UI do DOM: argumentos opcionais, síncronos ou assíncronos, grupos de métodos ou expressões lambda.

<button class="btn btn-primary" @onclick="OnClick">Clique em mim!</button>

@código {

31 CAPÍTULO 6 | Crie componentes de UI reutilizáveis com Blazor


Machine Translated by Google

[Parâmetro]
public EventCallback<MouseEventArgs> OnClick { get; definir; }
}

Ligação de dados
O Blazor fornece um mecanismo simples para vincular dados de um componente de IU ao estado do componente. Essa abordagem
difere dos recursos do ASP.NET Web Forms para vincular dados de fontes de dados a controles de UI. Abordaremos o
tratamento de dados de diferentes fontes de dados na seção Lidando com dados .

Para criar uma ligação de dados bidirecional de um componente de UI para o estado do componente, use o atributo de
diretiva @bind . No exemplo a seguir, o valor da caixa de seleção está vinculado ao campo isChecked .

<input type="checkbox" @bind="isChecked" />

@code
{ bool isChecked;
}

Quando o componente é renderizado, o valor da caixa de seleção é definido como o valor do campo isChecked .
Quando o usuário alterna a caixa de seleção, o evento onchange é acionado e o campo isChecked é definido com o novo valor. A
sintaxe @bind neste caso é equivalente à seguinte marcação:

<input value="@isChecked" @onchange="(UIChangeEventArgs e) => isChecked = e.Value" />

Para alterar o evento usado para a ligação, use o atributo @bind:event .

<input @bind="text" @bind:event="oninput" /> <p>@text</


p>

@código
{string texto;
}

Os componentes também podem oferecer suporte à vinculação de dados aos seus parâmetros. Para vincular dados, defina um
parâmetro de retorno de chamada de evento com o mesmo nome do parâmetro vinculável. O sufixo “Alterado” é adicionado ao
nome.

PasswordBox.razor

Senha: <input
value="@Password"
@oninput="OnPasswordChanged"
type="@(showPassword ? "text" : "password")" />

<label><input type="checkbox" @bind="showPassword" />Mostrar senha</label>

@code
{private bool showPassword;

[Parâmetro]
public string Senha { get; definir; }

[Parâmetro]

32 CAPÍTULO 6 | Crie componentes de UI reutilizáveis com Blazor


Machine Translated by Google

public EventCallback<string> PasswordChanged { get; definir; }

tarefa privada OnPasswordChanged(ChangeEventArgs e) {

Senha = e.Value.ToString(); retornar


SenhaChanged.InvokeAsync(Senha);
}
}

Para encadear uma vinculação de dados a um elemento de UI subjacente, defina o valor e manipule o evento
diretamente no elemento de UI em vez de usar o atributo @bind .

Para vincular a um parâmetro de componente, use um atributo @bind-{Parameter} para especificar o parâmetro ao
qual deseja vincular.

<PasswordBox @bind-Password="senha" />

@código
{string senha;
}

Mudanças de estado
Se o estado do componente tiver mudado fora de um evento de UI normal ou retorno de chamada de evento,
o componente deverá sinalizar manualmente que precisa ser renderizado novamente. Para sinalizar que o estado
de um componente foi alterado, chame o método StateHasChanged no componente.

No exemplo abaixo, um componente exibe uma mensagem de um serviço AppState que pode ser atualizado
por outras partes do aplicativo. O componente registra seu método StateHasChanged com o evento
AppState.OnChange para que o componente seja renderizado sempre que a mensagem for atualizada.

classe pública AppState {

string pública Mensagem { obter; }

// Permite que os componentes recebam notificações de


alterações public event Action OnChange;

public void UpdateMessage(string mensagem) {

Mensagem = mensagem;
NotifyStateChanged();
}

private void NotifyStateChanged() => OnChange?.Invoke();


}

@inject AppState AppState

<p>Mensagem do aplicativo: @AppState.Message</p>

@code
{substituição protegida void OnInitialized() {

33 CAPÍTULO 6 | Crie componentes de UI reutilizáveis com Blazor


Machine Translated by Google

AppState.OnChange += StateHasChanged
}
}

Ciclo de vida do componente


A estrutura ASP.NET Web Forms possui métodos de ciclo de vida bem definidos para módulos, páginas
e controles. Por exemplo, o controle a seguir implementa manipuladores de eventos para Init, Load e UnLoad
eventos do ciclo de vida:

Contador.ascx.cs

Contador de classe parcial pública : System.Web.UI.UserControl


{
protegido void Page_Init (objeto remetente, EventArgs e) { ... }
protegido void Page_Load (objeto remetente, EventArgs e) { ... }
protegido void Page_UnLoad (objeto remetente, EventArgs e) { ... }
}

Os componentes do Razor também têm um ciclo de vida bem definido. O ciclo de vida de um componente pode ser usado para
inicializar o estado do componente e implementar comportamentos avançados do componente.

Todos os métodos de ciclo de vida de componentes do Blazor têm versões síncronas e assíncronas.
A renderização de componentes é síncrona. Você não pode executar lógica assíncrona como parte da renderização do componente.
Toda lógica assíncrona deve ser executada como parte de um método de ciclo de vida assíncrono .

OnInitializado
Os métodos OnInitialized e OnInitializedAsync são usados para inicializar o componente. Um componente normalmente é
inicializado após ser renderizado pela primeira vez. Depois que um componente é inicializado, ele pode ser renderizado diversas
vezes antes de ser eventualmente descartado. O método OnInitialized é semelhante ao evento Page_Load em páginas e controles
de Web Forms ASP.NET.

substituição protegida void OnInitialized() { ... }


substituição protegida tarefa assíncrona OnInitializedAsync() {await ...}

OnParametersSet
Os métodos OnParametersSet e OnParametersSetAsync são chamados quando um componente recebe parâmetros de seu
pai e o valor é atribuído às propriedades. Esses métodos são executados após a inicialização do componente e sempre que o
componente é renderizado.

substituição protegida void OnParametersSet() { ... }


substituição protegida tarefa assíncrona OnParametersSetAsync() {await ...}

OnAfterRender
Os métodos OnAfterRender e OnAfterRenderAsync são chamados após a conclusão da renderização de um componente. As
referências de elementos e componentes são preenchidas neste ponto (mais sobre esses conceitos abaixo). A interatividade com o
navegador está habilitada neste momento. As interações com a execução do DOM e do JavaScript podem ocorrer com
segurança.

34 CAPÍTULO 6 | Crie componentes de UI reutilizáveis com Blazor


Machine Translated by Google

substituição protegida void OnAfterRender(bool firstRender) {

if (primeira renderização)
{
...
}

} substituição protegida tarefa assíncrona OnAfterRenderAsync(bool firstRender) {

if (primeira renderização)
{
aguardam ...
}
}

OnAfterRender e OnAfterRenderAsync não são chamados durante a pré-renderização no servidor.

O parâmetro firstRender é verdadeiro na primeira vez que o componente é renderizado; caso contrário, seu valor é
falso.

IDisponível
Os componentes do Razor podem implementar IDisposable para descartar recursos quando o componente é
removido da UI. Um componente Razor pode implementar IDispose usando a diretiva @implements :

@usando Sistema
@implementa IDisposable

...

@código
{ public void Dispose() {

...
}
}

Capturar referências de componentes


Em ASP.NET Web Forms, é comum manipular uma instância de controle diretamente no código, referindo-se ao
seu ID. No Blazor também é possível capturar e manipular uma referência a um componente, embora seja muito
menos comum.

Para capturar uma referência de componente no Blazor, use o atributo da diretiva @ref . O valor do atributo
deve corresponder ao nome de um campo configurável com o mesmo tipo do componente referenciado.

<MyLoginDialog @ref="loginDialog" ... />

@code
{ MyLoginDialog loginDialog = padrão!;

void EmAlguma coisa()


{
loginDialog.Show();

35 CAPÍTULO 6 | Crie componentes de UI reutilizáveis com Blazor


Machine Translated by Google

}
}

Quando o componente pai é renderizado, o campo é preenchido com a instância do componente filho.
Você pode então chamar métodos ou manipular a instância do componente.

Não é recomendado manipular o estado do componente diretamente usando referências de componentes. Isso evita que o componente
seja renderizado automaticamente nos momentos corretos.

Capturar referências de elementos


Os componentes do Razor podem capturar referências a um elemento. Ao contrário dos controles de servidor HTML em ASP.NET
Web Forms, você não pode manipular o DOM diretamente usando uma referência de elemento no Blazor. O Blazor lida com a
maioria das interações DOM para você usando seu algoritmo de comparação de DOM. As referências de elementos capturados no Blazor
são opacas. No entanto, eles são usados para passar uma referência de elemento específico em uma chamada de
interoperabilidade JavaScript. Para obter mais informações sobre interoperabilidade JavaScript, consulte Interoperabilidade
JavaScript do ASP.NET Core Blazor .

Componentes modelados
No ASP.NET Web Forms, você pode criar controles de modelo. Os controles modelados permitem que o desenvolvedor especifique uma
parte do HTML usado para renderizar um controle de contêiner. A mecânica de construção de controles de servidor modelo é
complexa, mas permite cenários poderosos para renderizar dados de maneira personalizável pelo usuário. Exemplos de controles de
modelo incluem Repeater e DataList.

Os componentes do Razor também podem ser modelados definindo parâmetros de componente do tipo
RenderFragment ou RenderFragment<T>. Um RenderFragment representa um pedaço da marcação Razor que pode então ser renderizado
pelo componente. Um RenderFragment<T> é um pedaço da marcação Razor que usa um parâmetro que pode ser especificado quando o
fragmento de renderização é renderizado.

Conteúdo infantil
Os componentes do Razor podem capturar seu conteúdo filho como RenderFragment e renderizar esse conteúdo como parte da
renderização do componente. Para capturar conteúdo filho, defina um parâmetro de componente do tipo RenderFragment e nomeie-o
como ChildContent.

ChildContentComponent.razor

<h1>Componente com conteúdo filho</h1>

<div>@ChildContent</div>

@código {
[Parâmetro]
public RenderFragment ChildContent {obter; definir; }
}

Um componente pai pode então fornecer conteúdo filho usando a sintaxe normal do Razor.

36 CAPÍTULO 6 | Crie componentes de UI reutilizáveis com Blazor


Machine Translated by Google

<ChildContentComponent>
<Conteúdo Infantil>
<p>A hora é @DateTime.Now</p>
</ChildContent>
</ChildContentComponent>

Parâmetros do modelo
Um componente Razor modelado também pode definir vários parâmetros de componente do tipo
RenderFragment ou RenderFragment<T>. O parâmetro para RenderFragment<T> pode ser especificado
quando é invocado. Para especificar um parâmetro de tipo genérico para um componente, use a diretiva
@typeparam Razor.

SimpleListView.razor

@typeparam TItem

@Cabeçalho

<ul>
@foreach (var item em Itens)
{
<li>@ItemTemplate(item)</li>
}
</ul>

@código {
[Parâmetro]
cabeçalho RenderFragment público {obter; definir; }

[Parâmetro]
public RenderFragment<TItem> ItemTemplate { get; definir; }

[Parâmetro]
public IEnumerable<TItem> Itens { get; definir; }
}

Ao usar um componente de modelo, os parâmetros do modelo podem ser especificados usando elementos filhos
que correspondam aos nomes dos parâmetros. Argumentos de componente do tipo RenderFragment<T> passados
como elementos possuem um parâmetro implícito denominado contexto. Você pode alterar o nome desse
parâmetro de implementação usando o atributo Context no elemento filho. Quaisquer parâmetros de tipo
genérico podem ser especificados usando um atributo que corresponda ao nome do parâmetro de tipo. O
parâmetro type será inferido se possível:

<SimpleListView Items="messages" TItem="string">


<Título>
<h1>Minha lista</h1>
</Título>
<ItemTemplate Context="mensagem">
<p>A mensagem é: @message</p>
</ItemTemplate>
</SimpleListView>

A saída deste componente é semelhante a esta:

37 CAPÍTULO 6 | Crie componentes de UI reutilizáveis com Blazor


Machine Translated by Google

<h1>Minha lista</h1>
<ul>
<li><p>A mensagem é: mensagem1</p></li>
<li><p>A mensagem é: mensagem2</p></li>
<ul>

Código por trás


Um componente Razor normalmente é criado em um único arquivo .razor . No entanto, também é possível separar o código e a
marcação usando um arquivo code-behind. Para usar um arquivo de componente, adicione um arquivo C# que corresponda ao
nome do arquivo de componente, mas com uma extensão .cs adicionada (Counter.razor.cs). Use o arquivo C# para definir uma
classe base para o componente. Você pode nomear a classe base como quiser, mas é comum nomear a classe da mesma forma
que a classe do componente, mas com uma extensão Base adicionada (CounterBase). A classe baseada em componentes
também deve derivar de ComponentBase. Em seguida, no arquivo do componente Razor, adicione a diretiva @inherits para
especificar a classe base do componente (@inherits CounterBase).

Contador.navalha

@herda CounterBase

<h1>Contador</h1>

<p>Contagem atual: @currentCount</p>

<button @onclick="IncrementCount">Clique em mim</button>

Contador.razor.cs

classe pública CounterBase: ComponentBase


{
protegido int contagem atual = 0;

protegido nulo IncrementCount()


{
ContagemAtual++;
}
}

A visibilidade dos membros do componente na classe base deve ser protegida ou pública para ser visível para a classe do
componente.

Recursos adicionais
O texto anterior não é um tratamento exaustivo de todos os aspectos dos componentes do Razor. Para obter mais informações sobre
como criar e usar componentes do ASP.NET Core Razor, consulte a documentação do Blazor.

38 CAPÍTULO 6 | Crie componentes de UI reutilizáveis com Blazor


Machine Translated by Google

CAPÍTULO 7

Páginas, roteamento
e layouts
Os aplicativos ASP.NET Web Forms são compostos de páginas definidas em arquivos .aspx . O endereço de cada
página é baseado no caminho físico do arquivo no projeto. Quando um navegador faz uma solicitação à página, o
conteúdo da página é renderizado dinamicamente no servidor. A renderização leva em conta a marcação HTML
da página e seus controles de servidor.

No Blazor, cada página do aplicativo é um componente, normalmente definido em um arquivo .razor , com uma ou
mais rotas especificadas. O roteamento ocorre principalmente no lado do cliente, sem envolver uma solicitação
específica do servidor. O navegador primeiro faz uma solicitação ao endereço raiz do aplicativo. Um componente roteador
raiz no aplicativo Blazor manipula a interceptação de solicitações de navegação e as encaminha para o componente correto.

Blazor também oferece suporte a links diretos. O deep linking ocorre quando o navegador faz uma solicitação para uma
rota específica diferente da raiz do aplicativo. As solicitações de links diretos enviadas ao servidor são roteadas
para o aplicativo Blazor, que então roteia a solicitação do lado do cliente para o componente correto.

Uma página simples em ASP.NET Web Forms pode conter a seguinte marcação:

Nome.aspx

<%@ Page Title="Nome" Language="C#" MasterPageFile="~/Site.Master" AutoEventWireup="true"


CodeBehind="Nome.aspx.cs" Inherits="WebApplication1.Name" %>

<asp:Content ID="BodyContent" ContentPlaceHolderID="MainContent" runat="server">


<div>
Qual é o seu nome?<br />
<asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
<asp:Button ID="Button1" runat="server" Text="Submit" OnClick="Button1_Click" />
</div>
<div>
<asp:Literal ID="Literal1" runat="servidor" />
</div>
</asp:Conteúdo>

Nome.aspx.cs

Nome da classe parcial pública : System.Web.UI.Page


{
protegido void Button1_Click1 (objeto remetente, EventArgs e)
{
Literal1.Text = "Olá" + TextBox1.Text;
}
}

39 CAPÍTULO 7 | Páginas, roteamento e layouts


Machine Translated by Google

A página equivalente em um aplicativo Blazor ficaria assim:

Nome.razor

@page "/Nome"
@layout MainLayout

<div>
Qual é o seu nome?<br /> <input
@bind="text" /> <button
@onclick="OnClick">Enviar</button> </div> <div>

@if (nome! = nulo) {

@:Olá @nome

} </div>

@código
{string texto;
nome da sequência;

void OnClick() { nome


= texto;
}
}

Criar páginas
Para criar uma página no Blazor, crie um componente e adicione a diretiva @page Razor para especificar a rota para o
componente. A diretiva @page usa um único parâmetro, que é o modelo de rota a ser adicionado a esse componente.

@página "/ contador"

O parâmetro do modelo de rota é obrigatório. Ao contrário dos Web Forms do ASP.NET, a rota para um componente
Blazor não é inferida a partir do local do arquivo (embora esse possa ser um recurso adicionado no futuro).

A sintaxe do modelo de rota é a mesma sintaxe básica usada para roteamento em ASP.NET Web Forms. Os parâmetros
de rota são especificados no modelo usando chaves. O Blazor vinculará valores de rota a parâmetros de componente com
o mesmo nome (sem distinção entre maiúsculas e minúsculas).

@página "/produto/{id}"

<h1>@ID do produto</h1>

@código {
[Parâmetro] ID
de string pública {get; definir; }
}

Você também pode especificar restrições no valor do parâmetro de rota. Por exemplo, para restringir o ID do produto a um
int:

40 CAPÍTULO 7 | Páginas, roteamento e layouts


Machine Translated by Google

@página "/produto/{id:int}"

<h1>@ID do produto</h1>

@código {
[Parâmetro]
público int ID {obter; definir; }
}

Para obter uma lista completa das restrições de rota suportadas pelo Blazor, consulte Restrições de rota.

Componente roteador
O roteamento no Blazor é controlado pelo componente Router . O componente Router normalmente é usado no componente raiz
do aplicativo (App.razor).

<Router AppAssembly="@typeof(Program).Assembly">
<Found Context="routeData">
<RouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)" />
</Encontrado>
<Não encontrado>

<LayoutView Layout="@typeof(MainLayout)">
<p>Desculpe, não há nada neste endereço.</p>
</LayoutView>
</NotFound>
</Roteador>

O componente Router descobre os componentes roteáveis no AppAssembly especificado e nos AdicionaisAssemblies


opcionalmente especificados. Quando o navegador navega, o roteador intercepta a navegação e renderiza o conteúdo de seu
parâmetro Found com o RouteData extraído se uma rota corresponder ao endereço, caso contrário, o roteador renderiza seu
parâmetro NotFound .

O componente RouteView lida com a renderização do componente correspondente especificado pelo RouteData
com seu layout, se houver. Se o componente correspondente não tiver um layout, o DefaultLayout especificado
opcionalmente será usado.

O componente LayoutView renderiza seu conteúdo filho dentro do layout especificado. Veremos os layouts com mais detalhes
posteriormente neste capítulo.

Navegação
No ASP.NET Web Forms, você aciona a navegação para uma página diferente retornando uma resposta de redirecionamento
ao navegador. Por exemplo:

void protegido NavigateButton_Click ( remetente do objeto, EventArgs e)


{
Response.Redirect("Contador");
}

Normalmente, retornar uma resposta de redirecionamento não é possível no Blazor. Blazor não usa um modelo de
solicitação-resposta. Você pode, no entanto, acionar navegações do navegador diretamente, como faz com JavaScript.

41 CAPÍTULO 7 | Páginas, roteamento e layouts


Machine Translated by Google

Blazor fornece um serviço NavigationManager que pode ser usado para:

• Obtenha o endereço atual do navegador


• Obtenha o endereço base

Acionar navegações

Seja notificado quando o endereço mudar

Para navegar para um endereço diferente, use o método NavigateTo :

@página "/"
@inject NavigationManager NavigationManager

<button @onclick="Navigate">Navegar</button>

@código {
void Navegar() {
NavigationManager.NavigateTo("contador");
}
}

Para obter uma descrição de todos os membros do NavigationManager , consulte URI e auxiliares de estado de navegação.

URLs básicos

Se seu aplicativo Blazor for implantado em um caminho base, você precisará especificar a URL base nos metadados da página usando
a tag <base> para roteamento para a propriedade work. Se a página host do aplicativo for renderizada pelo servidor usando o Razor,
você poderá usar a sintaxe ~/ para especificar o endereço base do aplicativo. Se a página host for HTML estático, você precisará
especificar explicitamente o URL base.

<base href="~/" />

Layout da página

O layout da página em ASP.NET Web Forms é gerenciado por páginas mestras. As páginas mestras definem um modelo com um ou
mais marcadores de conteúdo que podem ser fornecidos por páginas individuais. As páginas mestras são definidas em arquivos .master
e começam com a diretiva <%@ Master %> . O conteúdo dos arquivos .master é codificado como se fosse uma página .aspx , mas com

a adição de controles <asp:ContentPlaceHolder> para marcar onde as páginas podem fornecer conteúdo.

Site.master

<%@ Master Language="C#" AutoEventWireup="true" CodeBehind="Site.master.cs"


Herda = "WebApplication1.SiteMaster" %>

<!DOCTYPEhtml>
<html lang="pt">
<head runat="servidor">
<meta charset="utf-8" />
<meta name="viewport" content="largura=largura do dispositivo, escala inicial=1,0" />
<title><%: Page.Title %> - Meu aplicativo ASP.NET</title>
<link href="~/favicon.ico" rel="ícone de atalho" type="image/x-icon" />
</head>

42 CAPÍTULO 7 | Páginas, roteamento e layouts


Machine Translated by Google

<body>
<form runat="servidor">
<div class="container body-content">
<asp:ContentPlaceHolder ID="MainContent" runat="server"> </
asp:ContentPlaceHolder> <hr />
<footer>
<p>&copy;
<%: DateTime.Now.Year %> - Meu aplicativo ASP.NET</p> </footer> </div> </form> </
body> </
html>

No Blazor, você gerencia o layout da página usando componentes de layout. Os componentes de layout herdam de
LayoutComponentBase, que define uma única propriedade Body do tipo RenderFragment, que pode ser usada para renderizar o
conteúdo da página.

MainLayout.razor

@inherits LayoutComponentBase
<h1>Layout principal</h1>
<div>
@Body
</div>

Quando a página com um layout é renderizada, a página é renderizada dentro do conteúdo do layout especificado no local onde
o layout renderiza sua propriedade Body .

Para aplicar um layout a uma página, use a diretiva @layout :

@layoutMainLayout

Você pode especificar o layout para todos os componentes em uma pasta e subpastas usando um arquivo *_Imports.razor*.
Você também pode especificar um layout padrão para todas as suas páginas usando o componente Roteador.

As páginas mestras podem definir vários espaços reservados de conteúdo, mas os layouts no Blazor possuem apenas uma única
propriedade Body . Esperançosamente, esta limitação dos componentes de layout do Blazor será abordada em uma versão futura.

As páginas mestras em formulários da Web ASP.NET podem ser aninhadas. Ou seja, uma Master Page também pode usar
uma Master Page. Os componentes de layout no Blazor também podem ser aninhados. Você pode aplicar um componente de layout
a um componente de layout. O conteúdo do layout interno será renderizado dentro do layout externo.

ChildLayout.razor

@layout MainLayout
<h2>Layout filho</h2> <div>

@Body
</div>

Índice.razor

@page "/"
@layout ChildLayout
<p>Estou em um layout aninhado!</p>

A saída renderizada para a página seria então:

43 CAPÍTULO 7 | Páginas, roteamento e layouts


Machine Translated by Google

<h1>Layout principal</h1>
<div>
<h2>Layout filho</h2>
<div>
<p>Estou em um layout aninhado!</p>
</div>
</div>

Os layouts no Blazor normalmente não definem os elementos HTML raiz de uma página (<html>, <body>, <head> e assim
por diante). Em vez disso, os elementos HTML raiz são definidos na página host de um aplicativo Blazor, que é usada para
renderizar o conteúdo HTML inicial do aplicativo (consulte Bootstrap Blazor). A página host pode renderizar vários componentes
raiz para o aplicativo com marcação circundante.

Os componentes do Blazor, incluindo páginas, não podem renderizar tags <script> . Essa restrição de renderização existe
porque as tags <script> são carregadas uma vez e não podem ser alteradas. Poderá ocorrer um comportamento inesperado se
você tentar renderizar as tags dinamicamente usando a sintaxe do Razor. Em vez disso, todas as tags <script> devem ser
adicionadas à página host do aplicativo.

44 CAPÍTULO 7 | Páginas, roteamento e layouts


Machine Translated by Google

CAPÍTULO 8

Gestão estadual
O gerenciamento de estado é um conceito-chave dos aplicativos Web Forms, facilitado pelos recursos ViewState, Session State,
Application State e Postback. Esses recursos com estado da estrutura ajudaram a ocultar o gerenciamento de estado necessário
para um aplicativo e permitiram que os desenvolvedores de aplicativos se concentrassem no fornecimento de sua funcionalidade.
Com o ASP.NET Core e o Blazor, alguns desses recursos foram realocados e outros foram completamente removidos. Este
capítulo analisa como manter o estado e fornecer a mesma funcionalidade com os novos recursos do Blazor.

Solicite gerenciamento de estado com ViewState


Ao discutir o gerenciamento de estado em aplicativos Web Forms, muitos desenvolvedores pensarão imediatamente em
ViewState. Em Web Forms, o ViewState gerencia o estado do conteúdo entre as solicitações HTTP, enviando um grande bloco de texto
codificado para o navegador. O campo ViewState pode ficar sobrecarregado com conteúdo de uma página contendo muitos
elementos, expandindo potencialmente para vários megabytes de tamanho.

Com o Blazor Server, o aplicativo mantém uma conexão contínua com o servidor. O estado do aplicativo, chamado circuito, é mantido
na memória do servidor enquanto a conexão é considerada ativa. O estado só será descartado quando o usuário sair do aplicativo
ou de uma página específica do aplicativo. Todos os membros dos componentes ativos estão disponíveis entre as interações com o
servidor.

Existem várias vantagens deste recurso:

• O estado do componente está prontamente disponível e não é reconstruído entre interações.


• O estado não é transmitido ao navegador.

No entanto, existem algumas desvantagens na persistência do estado do componente na memória que você deve conhecer:


Se o servidor for reiniciado entre as solicitações, o estado será perdido.

A solução de balanceamento de carga do servidor web do seu aplicativo deve incluir sessões fixas para garantir que todas as
solicitações do mesmo navegador retornem ao mesmo servidor. Se uma solicitação for para um servidor diferente, o
estado será perdido.

A persistência do estado do componente no servidor pode causar pressão de memória no servidor web.

Pelas razões anteriores, não confie apenas no estado do componente para residir na memória do servidor. Seu aplicativo também
deve incluir algum armazenamento de dados de apoio para dados entre solicitações. Alguns exemplos simples desta estratégia:


Em um aplicativo de carrinho de compras, persista o conteúdo dos novos itens adicionados ao carrinho em um registro do
banco de dados. Se o estado no servidor for perdido, você poderá reconstituí-lo a partir dos registros do banco de dados.

45 CAPÍTULO 8 | Gestão estadual


Machine Translated by Google


Em um formulário web multiparte, seus usuários esperam que seu aplicativo lembre valores entre cada solicitação.
Grave os dados entre cada uma das postagens do usuário em um armazenamento de dados para que possam ser
buscados e montados na estrutura final de resposta do formulário quando o formulário de várias partes for concluído.

Para obter detalhes adicionais sobre como gerenciar o estado em aplicativos Blazor, consulte Gerenciamento de estado do ASP.NET Core Blazor.

Manter o estado com Session


Os desenvolvedores de Web Forms podem manter informações sobre o usuário em ação no momento com o
Microsoft.AspNetCore.Http.ISession objeto de dicionário. É bastante fácil adicionar um objeto com uma chave de string à
Sessão, e esse objeto estará disponível posteriormente durante as interações do usuário com o aplicativo. Na tentativa de
eliminar o gerenciamento da interação com HTTP, o objeto Session facilitou a manutenção do estado.

A assinatura do objeto Sessão do .NET Framework não é a mesma da Sessão do ASP.NET Core
objeto. Considere a documentação da nova sessão ASP.NET Core antes de decidir migrar e usar o novo recurso de estado
de sessão.

A sessão está disponível no ASP.NET Core e no Blazor Server, mas seu uso é desencorajado em favor do armazenamento
adequado de dados em um repositório de dados. O estado da sessão também não funciona se os visitantes recusarem o uso
de cookies HTTP em seu aplicativo devido a questões de privacidade.

A configuração do ASP.NET Core e do estado da sessão está disponível no artigo Gerenciamento de sessão e estado no
ASP.NET Core.

Estado do aplicativo
O objeto Application na estrutura Web Forms fornece um repositório massivo de solicitações cruzadas para interagir com a
configuração e o estado do escopo do aplicativo. O estado do aplicativo era um local ideal para armazenar diversas
propriedades de configuração do aplicativo que seriam referenciadas por todas as solicitações, independentemente do usuário
que fez a solicitação. O problema com o objeto Aplicativo era que os dados não persistiam em vários servidores. O estado do
objeto do aplicativo foi perdido entre as reinicializações.

Tal como acontece com a Sessão, é recomendado que os dados sejam movidos para um armazenamento de apoio
persistente que possa ser acessado por várias instâncias de servidor. Se houver dados voláteis que você gostaria de acessar
entre solicitações e usuários, você poderá armazená-los facilmente em um serviço singleton que pode ser injetado em
componentes que exigem essas informações ou interação.

A construção de um objeto para manter o estado da aplicação e seu consumo poderia ser semelhante à seguinte implementação:

classe pública MyApplicationState


{
public int VisitorCounter { obter; conjunto privado; } = 0;

public void IncrementCounter() => VisitorCounter += 1;


}

46 CAPÍTULO 8 | Gestão estadual


Machine Translated by Google

app.AddSingleton<MyApplicationState>();

@inject MyApplicationState AppState

<label>Total de visitantes: @AppState.VisitorCounter</label>

O objeto MyApplicationState é criado apenas uma vez no servidor, e o valor VisitorCounter é obtido e gerado no rótulo do componente. O
valor VisitorCounter deve ser persistido e recuperado de um armazenamento de dados de apoio para durabilidade e escalabilidade.

No navegador
Os dados do aplicativo também podem ser armazenados do lado do cliente no dispositivo do usuário para que fiquem disponíveis

posteriormente. Existem dois recursos do navegador que permitem a persistência de dados em diferentes escopos do navegador do usuário:

• localStorage - com escopo para todo o navegador do usuário. Se a página for recarregada, o
navegador será fechado e reaberto ou outra guia será aberta com o mesmo URL e o mesmo localStorage
é fornecido pelo navegador

sessionStorage - com escopo definido para a guia atual do navegador do usuário. Se a guia for recarregada, o estado
persiste. No entanto, se o usuário abrir outra aba do seu aplicativo ou fechar e reabrir o navegador, o estado será perdido.

Você pode escrever algum código JavaScript personalizado para interagir com esses recursos ou há vários pacotes NuGet
que podem ser usados para fornecer essa funcionalidade. Um desses pacotes é
Microsoft.AspNetCore.ProtectedBrowserStorage.

Para obter instruções sobre como utilizar este pacote para interagir com localStorage e sessionStorage, consulte Blazor State Management

artigo.

47 CAPÍTULO 8 | Gestão estadual


Machine Translated by Google

CAPÍTULO 9

Formulários e validação
A estrutura ASP.NET Web Forms inclui um conjunto de controles de servidor de validação que tratam da validação da entrada do usuário inserida em um

formulário (RequiredFieldValidator, CompareValidator, RangeValidator e assim por diante). A estrutura ASP.NET Web Forms também oferece suporte à

associação de modelo e à validação do modelo com base em anotações de dados ([Obrigatório], [StringLength], [Range] e assim por diante). A lógica de

validação pode ser aplicada tanto no servidor quanto no cliente usando validação discreta baseada em JavaScript.

O controle de servidor ValidationSummary é usado para exibir um resumo dos erros de validação para o
do utilizador.

Blazor oferece suporte ao compartilhamento de lógica de validação entre o cliente e o servidor. ASP.NET fornece
implementações JavaScript pré-construídas de muitas validações de servidor comuns. Em muitos casos, o desenvolvedor ainda
precisa escrever JavaScript para implementar totalmente a lógica de validação específica do aplicativo. Os mesmos tipos de
modelo, anotações de dados e lógica de validação podem ser usados no servidor e no cliente.

Blazor fornece um conjunto de componentes de entrada. Os componentes de entrada tratam da vinculação de dados de
campo a um modelo e da validação da entrada do usuário quando o formulário é enviado.

Componente de entrada Elemento HTML renderizado

Caixa de verificação de entrada <input type="caixa de seleção">

Data de entrada <input type="data">

Número de entrada <tipo de entrada = "número">

Seleção de entrada <selecionar>

Entrada de texto <entrada>

EntradaTextArea <área de texto>

O componente EditForm agrupa esses componentes de entrada e orquestra o processo de validação por meio de um
EditContext. Ao criar um EditForm, você especifica a qual instância de modelo vincular usando o parâmetro Model . A validação
normalmente é feita usando anotações de dados e é extensível. Para habilitar a validação baseada em anotação de dados, adicione
o componente DataAnnotationsValidator como filho do EditForm. O componente EditForm fornece um evento conveniente para lidar
com envios válidos (OnValidSubmit) e inválidos (OnInvalidSubmit) . Há também um OnSubmit mais genérico

evento que permite acionar e manipular a validação por conta própria.

Para exibir um resumo do erro de validação, use o componente ValidationSummary . Para exibir mensagens de validação para um
campo de entrada específico, use o componente ValidationMessage , especificando uma expressão lambda para o parâmetro
For que aponta para o membro do modelo apropriado.

O seguinte tipo de modelo define diversas regras de validação usando anotações de dados:

48 CAPÍTULO 9 | Formulários e validação


Machine Translated by Google

usando o
sistema; usando System.ComponentModel.DataAnnotations;

classe pública nave estelar


{
[Obrigatório]
[StringLength(16,
ErrorMessage = "Identificador muito longo (limite de 16 caracteres).")] public
string Identifier { get; definir; }

string pública Descrição { get; definir; }

[Obrigatório]
public string Classificação { get; definir; }

[Range(1, 100000,
ErrorMessage = "Acomodação inválida (1-100000).")]
public int Máxima acomodação { get; definir; }

[Obrigatório]
[Range(typeof(bool), "true", "true",
ErrorMessage = "Este formulário não permite navios não aprovados.")]
public bool IsValidatedDesign { get; definir; }

[Obrigatório]
public DateTime ProductionDate { get; definir; }
}

O componente a seguir demonstra a construção de um formulário no Blazor com base no tipo de modelo Starship :

<h1>Formulário de inscrição de novo navio</h1>

<EditForm Model="@starship" OnValidSubmit="@HandleValidSubmit">


<DataAnnotationsValidator />
<Resumo de validação />

<p>
<label for="identifier">Identificador: </label> <InputText
id="identifier" @bind-Value="starship.Identifier" /> <ValidationMessage For="() =>
starship.Identifier" /> </ p> <p>

<label for="description">Descrição (opcional): </label> <InputTextArea


id="description" @bind-Value="starship.Description" /> </p> <p>

<label for="classification">Classificação primária: </label> <InputSelect


id="classification" @bind-Value="starship.Classification"> <option value="">Selecionar
classificação ...</option> < option value="Exploration">Exploração</
option> <option value="Diplomacy">Diplomacia</option>
<option value="Defense">Defesa</option> </InputSelect>
<ValidationMessage For="() = > nave
estelar.Classificação" /
> </p> <p>

<label for="accommodation">Acomodação máxima: </label> <InputNumber


id="accommodation" @bind-Value="starship.MaximumAccommodation" /> <ValidationMessage For="()
=> starship.MaximumAccommodation" /> < /p>

49 CAPÍTULO 9 | Formulários e validação


Machine Translated by Google

<p>
<label for="valid">Aprovação de engenharia: </label>
<InputCheckbox id="valid" @bind-Value="starship.IsValidatedDesign" /> <ValidationMessage
For="() => starship.IsValidatedDesign" /> < /p> <p>

<label for="productionDate">Data de produção: </label> <InputDate


id="productionDate" @bind-Value="starship.ProductionDate" /> <ValidationMessage For="() =>
starship.ProductionDate" /> < /p>

<button type="submit">Enviar</button>
</EditForm>

@code
{ nave estelar privada nave = new nave estelar();

private void HandleValidSubmit() {

//Salva os dados
}
}

Após o envio do formulário, os dados vinculados ao modelo não foram salvos em nenhum armazenamento de dados,
como um banco de dados. Em um aplicativo Blazor WebAssembly, os dados devem ser enviados ao servidor. Por exemplo,
usando uma solicitação HTTP POST. Em um aplicativo Blazor Server, os dados já estão no servidor, mas devem ser persistidos.
O tratamento do acesso a dados em aplicativos Blazor é o assunto da seção Lidando com dados .

Recursos adicionais
Para mais informações sobre formulários e validação em aplicativos Blazor, consulte a documentação do Blazor.

50 CAPÍTULO 9 | Formulários e validação


Machine Translated by Google

CAPÍTULO 10

Trabalhar com dados

O acesso a dados é a espinha dorsal de um aplicativo ASP.NET Web Forms. Se você estiver criando formulários para a web, o que
acontece com esses dados? Com Web Forms, havia diversas técnicas de acesso a dados que você poderia usar para interagir
com um banco de dados:

• Fontes de dados

• ADO.NET

Estrutura de entidade

Fontes de dados eram controles que você poderia colocar em uma página de Web Forms e configurar como outros
controles. O Visual Studio forneceu um conjunto amigável de caixas de diálogo para configurar e vincular os controles às suas
páginas de Web Forms. Os desenvolvedores que gostam de uma abordagem de “baixo código” ou “sem código”
preferiram essa técnica quando o Web Forms foi lançado pela primeira vez.

ADO.NET é a abordagem de baixo nível para interagir com um banco de dados. Seus aplicativos podem criar
uma conexão com o banco de dados com comandos, tabelas de dados e conjuntos de dados para interação. Os
resultados poderiam então ser vinculados a campos na tela sem muito código. A desvantagem dessa abordagem era
que cada conjunto de objetos ADO.NET (Connection, Command e DataTable) estava vinculado a bibliotecas fornecidas
por um fornecedor de banco de dados. O uso desses componentes tornou o código rígido e difícil de migrar para
um banco de dados diferente.

Estrutura de entidade
Entity Framework (EF) é a estrutura de mapeamento objeto-relacional de código aberto mantida pela .NET
Foundation. Lançado inicialmente com .NET Framework, o EF permite gerar código para conexões de
banco de dados, esquemas de armazenamento e interações. Com esta abstração, você pode se concentrar em seu

51 CAPÍTULO 10 | Trabalhar com dados


Machine Translated by Google

regras de negócios do aplicativo e permitir que o banco de dados seja gerenciado por um administrador de banco de dados
confiável. No .NET, você pode usar uma versão atualizada do EF chamada EF Core. O EF Core ajuda a gerar e manter as interações
entre seu código e o banco de dados com uma série de comandos que estão disponíveis para você usando a ferramenta de linha de
comando dotnet ef . Vamos dar uma olhada em alguns exemplos para você trabalhar com um banco de dados.

Código EF primeiro

Uma maneira rápida de começar a construir suas interações com o banco de dados é começar com os objetos de classe com os
quais você deseja trabalhar. A EF fornece uma ferramenta para ajudar a gerar o código de banco de dados apropriado para suas classes.
Essa abordagem é chamada de desenvolvimento “Code First”. Considere a seguinte classe Product para um exemplo de aplicativo
de loja que queremos armazenar em um banco de dados relacional como o Microsoft SQL Server.

classe pública Produto


{
público int ID { obter; definir; }

[Obrigatório]
string pública Nome { obter; definir; }

[Comprimento Máx(4000)]
string pública Descrição { get; definir; }

[Intervalo(0, 99999,99)]
[DataType(DataType.Moeda)]
Preço decimal público { obter; definir; }
}

O produto possui uma chave primária e três campos adicionais que seriam criados em nosso banco de dados:


A EF identificará a propriedade Id como chave primária por convenção.

O nome será armazenado em uma coluna configurada para armazenamento de texto. O atributo [Required] que decora esta
propriedade adicionará uma restrição não nula para ajudar a impor este comportamento declarado da propriedade.

• A descrição será armazenada em uma coluna configurada para armazenamento de texto e terá comprimento
máximo configurado de 4.000 caracteres conforme ditado pelo atributo [MaxLength] . O esquema do banco
de dados será configurado com uma coluna chamada MaxLength usando o tipo de dados varchar(4000).

• A propriedade Price será armazenada como moeda. O atributo [Range] gerará restrições apropriadas para evitar o armazenamento
de dados fora dos valores mínimo e máximo declarados.

Precisamos adicionar esta classe Product a uma classe de contexto de banco de dados que defina a conexão e

operações de tradução com nosso banco de dados.

classe pública MyDbContext: DbContext


{
public DbSet<Produto> Produtos { get; definir; }
}

A classe MyDbContext fornece a única propriedade que define o acesso e a tradução para a classe Product . Seu aplicativo
configura essa classe para interação com o banco de dados usando as seguintes entradas no método ConfigureServices da
classe Startup (ou local apropriado em Program.cs usando a propriedade builder.Services em vez de serviços):

52 CAPÍTULO 10 | Trabalhar com dados


Machine Translated by Google

serviços.AddDbContext<MyDbContext>(opções =>
options.UseSqlServer("MINHA CADEIA DE CONEXÃO DE BANCO DE DADOS"));

O código anterior se conectará a um banco de dados SQL Server com a cadeia de conexão especificada. Você pode
colocar a cadeia de conexão em seu arquivo appsettings.json , variáveis de ambiente ou outros locais de
armazenamento de configuração e substituir essa cadeia incorporada adequadamente.

Você pode então gerar a tabela de banco de dados apropriada para esta classe usando os seguintes comandos:

dotnet ef migrações adicionam 'Criar tabela de produtos'


atualização do banco de dados dotnet ef

O primeiro comando define as alterações que você está fazendo no esquema do banco de dados como uma nova migração
EF chamada Criar tabela de produto. Uma migração define como aplicar e remover as novas alterações do banco de
dados.

Depois de aplicado, você terá uma tabela Produto simples em seu banco de dados e algumas novas classes adicionadas
ao projeto que ajudam a gerenciar o esquema do banco de dados. Você pode encontrar essas classes geradas, por padrão,
em uma nova pasta chamada Migrations. Ao fazer alterações na classe Produto ou adicionar mais classes relacionadas
com as quais gostaria de interagir com seu banco de dados, você precisará executar os comandos de linha de comando
novamente com um novo nome de migração. Este comando irá gerar outro conjunto de classes de migração para atualizar o
esquema do seu banco de dados.

Banco de dados EF primeiro

Para bancos de dados existentes, você pode gerar as classes para o EF Core usando as ferramentas de linha de
comando do .NET. Para criar o scaffold das classes, use uma variação do seguinte comando:

dotnet ef dbcontext scaffold "STRING DE CONEXÃO" Microsoft.EntityFrameworkCore.SqlServer -c MyDbContext -t Produto -t Cliente

O comando anterior se conecta ao banco de dados usando a cadeia de conexão especificada e o provedor
Microsoft.EntityFrameworkCore.SqlServer . Uma vez conectado, uma classe de contexto de banco de dados chamada
MyDbContext é criada. Além disso, são criadas classes de suporte para as tabelas Produto e Cliente que foram
especificadas com as opções -t . Existem muitas opções de configuração para este comando gerar a hierarquia de classes
apropriada para seu banco de dados. Para uma referência completa, consulte a documentação do comando.

Mais informações sobre o EF Core pode ser encontrado no site do Microsoft Docs.

Interaja com serviços da web


Quando o ASP.NET foi lançado pela primeira vez, os serviços SOAP eram a forma preferida de servidores e clientes da Web
trocarem dados. Muita coisa mudou desde então, e as interações preferenciais com os serviços mudaram para interações
diretas do cliente HTTP. Com ASP.NET Core e Blazor, você pode registrar a configuração do seu HttpClient em
Program.cs ou no método ConfigureServices da classe Startup .
Use essa configuração quando precisar interagir com o terminal HTTP. Considere o seguinte código de configuração:

53 CAPÍTULO 10 | Trabalhar com dados


Machine Translated by Google

// em Programa.cs
construtor.Services.AddHttpClient("github", cliente =>
{
cliente.BaseAddress = novo Uri("http://api.github.com/");
// Versionamento da API do Github
client.DefaultRequestHeaders.Add("Aceitar", "application/vnd.github.v3+json");
// Github requer um agente de usuário
client.DefaultRequestHeaders.Add("User-Agent", "BlazorWebForms-Sample");
});

Sempre que você precisar acessar dados do GitHub, crie um cliente com o nome github. O cliente é configurado
com o endereço base e os cabeçalhos da solicitação são definidos adequadamente. Injete o
IHttpClientFactory em seus componentes Blazor com a diretiva @inject ou um [Inject]
atributo em uma propriedade. Crie seu cliente nomeado e interaja com os serviços usando a seguinte sintaxe:

@inject fábrica IHttpClientFactory

...

@código {
substituição protegida tarefa assíncrona OnInitializedAsync()
{
var cliente = factory.CreateClient("github");
var resposta = aguardar client.GetAsync("repos/dotnet/docs/issues");
resposta.EnsureStatusCode();
var content = aguarda resposta.Content.ReadAsStringAsync();
}
}

Este método retorna a string que descreve a coleção de problemas no repositório GitHub dotnet/ docs .
Ele retorna conteúdo no formato JSON e é desserializado em objetos de problema apropriados do GitHub. Há
muitas maneiras de configurar o HttpClientFactory para entregar HttpClient pré-configurado
objetos. Tente configurar várias instâncias de HttpClient com nomes e endpoints diferentes para os vários
serviços da Web com os quais você trabalha. Essa abordagem tornará suas interações com esses serviços
mais fáceis de trabalhar em cada página. Para obter mais informações, consulte Fazer solicitações
HTTP usando IHttpClientFactory.

54 CAPÍTULO 10 | Trabalhar com dados


Machine Translated by Google

CAPÍTULO 11

Módulos, manipuladores
e middleware
Um aplicativo ASP.NET Core é baseado em uma série de middleware. Middleware são manipuladores organizados em
um pipeline para lidar com solicitações e respostas. Em um aplicativo Web Forms, os manipuladores e módulos HTTP
resolvem problemas semelhantes. No ASP.NET Core, módulos, manipuladores, Global.asax.cs e o ciclo de vida do
aplicativo são substituídos por middleware. Neste capítulo, você aprenderá sobre middleware no contexto de um Blazor
aplicativo.

Visão geral
O pipeline de solicitação do ASP.NET Core consiste em uma sequência de delegados de solicitação,
chamados um após o outro. O diagrama a seguir demonstra o conceito. O fio da execução segue o preto
Setas; flechas.

55 CAPÍTULO 11 | Módulos, manipuladores e middleware


Machine Translated by Google

O diagrama anterior carece de um conceito de eventos do ciclo de vida. Esse conceito é fundamental para como as
solicitações de Web Forms do ASP.NET são tratadas. Este sistema facilita o raciocínio sobre qual processo está ocorrendo e
permite que o middleware seja inserido a qualquer momento. O middleware é executado na ordem em que é adicionado ao
pipeline de solicitação. Eles também são adicionados no código em vez de arquivos de configuração, geralmente em
Startup.cs.

Katana
Os leitores familiarizados com Katana se sentirão confortáveis com o ASP.NET Core. Na verdade, Katana é uma estrutura da qual
deriva o ASP.NET Core. Ele introduziu padrões semelhantes de middleware e pipeline para ASP.NET 4.x.
O middleware projetado para Katana pode ser adaptado para funcionar com o pipeline do ASP.NET Core.

Middleware comum
ASP.NET 4.x inclui muitos módulos. De maneira semelhante, o ASP.NET Core também possui muitos componentes de
middleware disponíveis. Os módulos IIS podem ser usados em alguns casos com ASP.NET Core. Em outros casos, o
middleware ASP.NET Core nativo pode estar disponível.

A tabela a seguir lista middleware e componentes de substituição no ASP.NET Core.

Módulo Módulo ASP.NET 4.x Opção ASP.NET Core

Erros HTTP Módulo de erro personalizado Middleware de páginas de código de status

Documento padrão MóduloDocumentoPadrão Middleware de arquivos padrão

56 CAPÍTULO 11 | Módulos, manipuladores e middleware


Machine Translated by Google

Módulo Módulo ASP.NET 4.x Opção ASP.NET Core

Navegação no diretório Módulo de Listagem de Diretórios Middleware de navegação em diretório

Compressão dinâmica Módulo de Compressão Dinâmica Middleware de compactação de resposta

Rastreamento de solicitações com falha FailedRequestsTracingModule Log do ASP.NET Core

Cache de arquivos Módulo FileCache


Middleware de cache de resposta

Cache HTTP Módulo HttpCache Middleware de cache de resposta

Registro HTTP Módulo HttpLogging Log do ASP.NET Core

Redirecionamento HTTP Módulo HttpRedirection Middleware de reescrita de URL

Filtros ISAPI Módulo IsapiFilter Middleware

ISAPI Módulo Isapi Middleware

Solicitar filtragem Módulo de Filtragem de Solicitação URL Reescrevendo Middleware IRule

Reescrita de URL† Reescrever Módulo Middleware de reescrita de URL

Compressão estática Módulo de compressão estática Middleware de compactação de resposta

Conteúdo estático Módulo de arquivo estático Middleware de arquivo estático

Autorização de URL UrlAuthorizationModule Identidade principal do ASP.NET

Esta lista não é exaustiva, mas deve dar uma ideia do mapeamento existente entre as duas estruturas.
Para obter uma lista mais detalhada, consulte Módulos IIS com ASP.NET Core.

Middleware personalizado

O middleware integrado pode não lidar com todos os cenários necessários para um aplicativo. Nesses casos, faz sentido criar seu
próprio middleware. Existem várias maneiras de definir middleware, sendo a mais simples um simples delegado. Considere o seguinte
middleware, que aceita uma solicitação de cultura de uma string de consulta:

inicialização de classe pública


{
Configuração pública void (aplicativo IApplicationBuilder)
{
app.Use(async (contexto, próximo) =>
{
var culturaQuery = context.Request.Query["cultura"];

if (!string.IsNullOrWhiteSpace(cultureQuery))
{
var cultura = new CultureInfo(culturaQuery);

CultureInfo.CurrentCulture = cultura;
CultureInfo.CurrentUICulture = cultura;
}

// Chama o próximo delegado/middleware no pipeline


aguarde o próximo();
});

57 CAPÍTULO 11 | Módulos, manipuladores e middleware


Machine Translated by Google

app.Run(async (contexto) =>


aguarde contexto.Response.WriteAsync(
$"Olá {CultureInfo.CurrentCulture.DisplayName}"));
}
}

Middleware também pode ser definido como classe, seja pela implementação da interface IMiddleware ou seguindo
a convenção de middleware. Para obter mais informações, consulte Escrever middleware ASP.NET Core personalizado.

58 CAPÍTULO 11 | Módulos, manipuladores e middleware


Machine Translated by Google

CAPÍTULO 12

Configuração do aplicativo

A principal maneira de carregar a configuração do aplicativo em Web Forms é com entradas no arquivo web.config — no
servidor ou em um arquivo de configuração relacionado referenciado por web.config. Você pode usar o objeto
ConfigurationManager estático para interagir com configurações do aplicativo, cadeias de conexão do repositório de
dados e outros provedores de configuração estendidos que são adicionados ao aplicativo. É comum ver interações
com a configuração do aplicativo, conforme visto no código a seguir:

var configurationValue = ConfigurationManager.AppSettings["ConfigurationSettingName"];


var connectionString =
ConfigurationManager.ConnectionStrings["MyDatabaseConnectionName"].ConnectionString;

Com o ASP.NET Core e o Blazor do lado do servidor, o arquivo web.config PODE estar presente se seu aplicativo estiver
hospedado em um servidor Windows IIS. No entanto, não há interação do ConfigurationManager com esta configuração e você
pode receber configurações de aplicativo mais estruturadas de outras fontes. Vamos dar uma olhada em como a configuração
é coletada e como você ainda pode acessar as informações de configuração de um web.config
arquivo.

Fontes de configuração
O ASP.NET Core reconhece que há muitas fontes de configuração que você pode querer usar para seu aplicativo. A estrutura tenta
oferecer o melhor desses recursos por padrão. A configuração é lida e agregada dessas diversas fontes pelo ASP.NET
Core. Os valores carregados posteriormente para a mesma chave de configuração têm precedência sobre os
valores anteriores.

O ASP.NET Core foi projetado para ter reconhecimento de nuvem e facilitar a configuração de aplicativos para operadores e
desenvolvedores. O ASP.NET Core reconhece o ambiente e sabe se está sendo executado em seu ambiente de produção
ou desenvolvimento . O indicador de ambiente é configurado na variável de ambiente do sistema
ASPNETCORE_ENVIRONMENT . Se nenhum valor for configurado, o aplicativo será executado no ambiente de produção por
padrão .

Seu aplicativo pode acionar e adicionar configurações de diversas fontes com base no nome do ambiente.
Por padrão, a configuração é carregada dos seguintes recursos na ordem listada:

1. Arquivo appsettings.json , se presente

2. arquivo appsettings.{ENVIRONMENT_NAME}.json , se presente

3. Arquivo de segredos do usuário no disco, se presente

4. Variáveis ambientais

5. Argumentos de linha de comando

59 CAPÍTULO 12 | Configuração do aplicativo


Machine Translated by Google

Formato e acesso appsettings.json


O arquivo appsettings.json pode ser hierárquico com valores estruturados como o seguinte JSON:

{
"seção0": {
"chave0": "valor",
"chave1": "valor"
},
"seção1": {
"key0": "valor",
"chave1": "valor"
}
}

Quando apresentado com o JSON anterior, o sistema de configuração nivela os valores filhos e faz referência aos seus
caminhos hierárquicos totalmente qualificados. Um caractere de dois pontos (:) separa cada propriedade na hierarquia. Por exemplo,
a chave de configuração section1:key0 acessa o valor key0 do literal do objeto section1 .

Segredos do usuário
Os segredos do usuário são:


Valores de configuração armazenados em um arquivo JSON na estação de trabalho do desenvolvedor, fora da pasta de
desenvolvimento do aplicativo.

Carregado apenas ao executar no ambiente de desenvolvimento .

Associado a um aplicativo específico.

• Gerenciado com o comando user-secrets da CLI do .NET .

Configure seu aplicativo para armazenamento de segredos executando o comando user-secrets :

inicialização de segredos do usuário dotnet

O comando anterior adiciona um elemento UserSecretsId ao arquivo de projeto. O elemento contém um GUID, que é usado para
associar segredos ao aplicativo. Você pode então definir um segredo com o conjunto
comando. Por exemplo:

dotnet user-secrets set "Parent:ApiKey" "12345"

O comando anterior disponibiliza a chave de configuração Parent:ApiKey na estação de trabalho de um desenvolvedor com o
valor 12345.

Para obter mais informações sobre como criar, armazenar e gerenciar segredos de usuário, consulte Armazenamento seguro de
segredos de aplicativo em desenvolvimento no ASP.NET Core documento.

Variáveis ambientais
O próximo conjunto de valores carregados na configuração do seu aplicativo são as variáveis de ambiente do sistema. Todas as
configurações de variáveis de ambiente do seu sistema agora estão acessíveis por meio da API de configuração.

60 CAPÍTULO 12 | Configuração do aplicativo


Machine Translated by Google

Os valores hierárquicos são nivelados e separados por dois pontos quando lidos dentro do seu aplicativo.
No entanto, alguns sistemas operacionais não permitem nomes de variáveis de ambiente com caracteres de dois pontos.
O ASP.NET Core aborda essa limitação convertendo valores que possuem sublinhados duplos (__) em dois pontos quando são
acessados. O valor Parent:ApiKey da seção de segredos do usuário acima pode ser substituído pela variável de ambiente
Parent__ApiKey.

Argumentos de linha de comando


A configuração também pode ser fornecida como argumentos de linha de comando quando seu aplicativo é iniciado. Use a
notação de traço duplo (--) ou barra (/) para indicar o nome do valor de configuração a ser definido e o valor a ser configurado.
A sintaxe é semelhante aos seguintes comandos:

dotnet execute CommandLineKey1 = valor1 --CommandLineKey2 = valor2 /CommandLineKey3 = valor3


dotnet run --CommandLineKey1 valor1 /CommandLineKey2 valor2
dotnet run Pai:ApiKey=67890

O retorno do web.config
Se você implantou seu aplicativo no Windows no IIS, o arquivo web.config ainda configurará o IIS para gerenciar seu aplicativo.
Por padrão, o IIS adiciona uma referência ao ASP.NET Core Module (ANCM). ANCM é um módulo IIS nativo que
hospeda seu aplicativo no lugar do servidor web Kestrel. Esta seção web.config é semelhante à seguinte marcação XML:

<?xml version="1.0" encoding="utf-8"?>


<configuração>
< caminho de localização="." herdarInChildApplications="falso">
<sistema.webServer>
<manipuladores>
<add name="aspNetCore" path="*" verbo="*" módulos="AspNetCoreModuleV2"
resourceType="Não especificado" />
</handlers>
<aspNetCore processPath=".\MyApp.exe"
stdoutLogEnabled="falso"
stdoutLogFile=".\logs\stdout"
hospedagemModel="em processo" />
</system.webServer>
</local>
</configuração>

A configuração específica do aplicativo pode ser definida aninhando um elemento environmentVariables no elemento
aspNetCore . Os valores definidos nesta seção são apresentados ao aplicativo ASP.NET Core como variáveis de ambiente.
As variáveis de ambiente são carregadas adequadamente durante esse segmento de inicialização do aplicativo.

<aspNetCore processPath="dotnet"
argumentos = ".\MyApp.dll"
stdoutLogEnabled="falso"
stdoutLogFile=".\logs\stdout"
hospedagemModel="em processo">
<variáveisde ambiente>
<environmentVariable name="ASPNETCORE_ENVIRONMENT" value="Desenvolvimento" />

61 CAPÍTULO 12 | Configuração do aplicativo


Machine Translated by Google

<environmentVariable name="Parent:ApiKey" value="67890" />


</environmentVariables>
</aspNetCore>

Leia a configuração no aplicativo


ASP.NET Core fornece configuração de aplicativo por meio do IConfiguration interface. Essa interface de configuração deve
ser solicitada pelos componentes do Blazor, pelas páginas do Blazor e por qualquer outra classe gerenciada pelo ASP.NET Core
que precise de acesso à configuração. A estrutura do ASP.NET Core preencherá automaticamente essa interface com a
configuração resolvida configurada anteriormente. Em uma página Blazor ou na marcação Razor de um componente,
você pode injetar o objeto IConfiguration com uma diretiva @inject na parte superior do arquivo .razor assim:

@inject Configuração de configuração

Esta instrução anterior disponibiliza o objeto IConfiguration como a variável Configuration em todo o restante do modelo Razor.

As definições de configuração individuais podem ser lidas especificando a hierarquia de definições de configuração procurada
como um parâmetro do indexador:

var minhaConfiguração = Configuração["seção1:chave0"];

Você pode buscar seções inteiras de configuração usando GetSection para recuperar uma coleção de chaves em um local
específico com uma sintaxe semelhante a GetSection("section1") para recuperar a configuração da seção1 do
exemplo anterior.

Configuração fortemente digitada


Com Web Forms, foi possível criar um tipo de configuração fortemente tipado que herdou do ConfigurationSection tipo e tipos
associados. Uma ConfigurationSection permitiu configurar algumas regras de negócios e processamento para esses valores de
configuração.

No ASP.NET Core, você pode especificar uma hierarquia de classes que receberá os valores de configuração. Estas aulas:


Não precisa herdar de uma classe pai.

Deve incluir propriedades públicas que correspondam às propriedades e referências de tipo da estrutura de
configuração que você deseja capturar.

Para o exemplo appsettings.json anterior , você poderia definir as seguintes classes para capturar os valores:

classe pública MyConfig


{
seção pública MyConfigSection0 { get; definir;}

public MyConfigSection seção1 { obter; definir;}


}

classe pública MyConfigSection


{

62 CAPÍTULO 12 | Configuração do aplicativo


Machine Translated by Google

chave de string pública0 { obter; definir; }

string pública chave1 { obter; definir; }


}

Essa hierarquia de classes pode ser preenchida adicionando a seguinte linha ao


método Startup.ConfigureServices (ou local apropriado em Program.cs usando a propriedade
builder.Services em vez de serviços):

services.Configure<MyConfig>(Configuração);

No restante do aplicativo, você pode adicionar um parâmetro de entrada às classes ou uma diretiva @inject
nos modelos Razor do tipo IOptions<MyConfig> para receber as definições de configuração com rigidez de
digitação. A propriedade IOptions<MyConfig>.Value produzirá o valor MyConfig preenchido a partir das definições
de configuração.

@inject IOptions<MyConfig> opções


@código {
var MinhaConfiguração = opções.Valor;
var theSetting = MyConfiguration.section1.key0;
}

Mais informações sobre o recurso Opções podem ser encontradas no padrão Opções no ASP.NET Core
documento.

63 CAPÍTULO 12 | Configuração do aplicativo


Machine Translated by Google

CAPÍTULO 13

Segurança: Autenticação
e Autorização em
Formulários Web ASP.NET
e Blazor
A migração de um aplicativo ASP.NET Web Forms para o Blazor quase certamente exigirá a atualização
de como a autenticação e a autorização são executadas, presumindo que o aplicativo tenha a autenticação
configurada. Este capítulo abordará como migrar do modelo de provedor universal ASP.NET Web Forms
(para associação, funções e perfis de usuário) e como trabalhar com ASP.NET Core Identity de aplicativos
Blazor. Embora este capítulo cubra as etapas e considerações de alto nível, as etapas e os scripts
detalhados podem ser encontrados na documentação referenciada.

Provedores universais ASP.NET


Desde o ASP.NET 2.0, a plataforma ASP.NET Web Forms oferece suporte a um modelo de provedor para
diversos recursos, incluindo associação. O provedor de associação universal, junto com o provedor de
função opcional, é comumente implantado com aplicativos ASP.NET Web Forms. Ele oferece uma maneira
robusta e segura de gerenciar autenticação e autorização que continua funcionando bem até hoje. A oferta
mais recente desses provedores universais está disponível como um pacote NuGet, Microsoft.AspNet.Providers.

Os provedores universais funcionam com um esquema de banco de dados SQL que inclui
tabelas como aspnet_Applications, aspnet_Membership, aspnet_Roles e aspnet_Users. Quando configurado
executando o comando aspnet_regsql.exe, os provedores instalam tabelas e procedimentos armazenados que
fornecem todas as consultas e comandos necessários para trabalhar com os dados subjacentes. O esquema do
banco de dados e esses procedimentos armazenados não são compatíveis com os sistemas ASP.NET Identity e
ASP.NET Core Identity mais recentes, portanto, os dados existentes devem ser migrados para o novo sistema. A
Figura 1 mostra um exemplo de esquema de tabela configurado para provedores universais.

64 CAPÍTULO 13 | Segurança: Autenticação e Autorização em ASP.NET Web Forms e Blazor


Machine Translated by Google

O provedor universal lida com usuários, associações, funções e perfis. Os usuários recebem identificadores
exclusivos globalmente e informações básicas como userId, userName etc. são armazenadas em aspnet_Users
mesa. Informações de autenticação, como senha, formato de senha, senha salt, contadores e detalhes de bloqueio, etc.
são armazenadas na tabela aspnet_Membership . As funções consistem simplesmente em nomes e identificadores
exclusivos, que são atribuídos aos usuários por meio da tabela de associação aspnet_UsersInRoles , fornecendo
um relacionamento muitos para muitos.

Se o seu sistema existente estiver usando funções além da associação, você precisará migrar as contas de
usuário, as senhas associadas, as funções e a associação de funções para o ASP.NET Core Identity.
Você provavelmente também precisará atualizar seu código onde está executando verificações de função usando
instruções if para aproveitar filtros declarativos, atributos e/ou auxiliares de tags. Analisaremos as considerações sobre
migração com mais detalhes no final deste capítulo.

Configuração de autorização em Web Forms


Para configurar o acesso autorizado a determinadas páginas em um aplicativo ASP.NET Web Forms, normalmente
você especifica que determinadas páginas ou pastas são inacessíveis para usuários anônimos. Esta configuração é feita
no arquivo web.config:

<?xml versão="1.0"?>
<configuração>
<sistema.web>
< modo de autenticação="Formulários">
<formulários defaultUrl="~/home.aspx" loginUrl="~/login.aspx"
deslizamentoExpiration="true" timeout="2880"></forms>
</autenticação>

<autorização>
<negar usuários="?" />
</autorização>
</system.web>
</configuração>

A seção de configuração de autenticação configura a autenticação de formulários para o aplicativo. A seção de


autorização é usada para proibir usuários anônimos em todo o aplicativo. No entanto, você pode fornecer regras de
autorização mais granulares por local, bem como aplicar verificações de autorização baseadas em função.

< caminho de localização="login.aspx">


<sistema.web>

65 CAPÍTULO 13 | Segurança: Autenticação e Autorização em ASP.NET Web Forms e Blazor


Machine Translated by Google

<autorização>
<allow users="*" /> </
autorização> </
system.web> </
location>

A configuração acima, quando combinada com a primeira, permitiria que usuários anônimos acessassem a página de
login, substituindo a restrição de todo o site para usuários não autenticados.

< caminho de localização="/


admin">
<system.web> <autorização>
<allow role="Administradores" /> <deny
users="*" /> </
authorization> </
system.web> </
location>

A configuração acima, quando combinada com as outras, restringe o acesso à pasta /admin e a todos os recursos dentro
dela aos membros da função “Administradores”. Essa restrição também pode ser aplicada colocando um arquivo
web.config separado na raiz da pasta /admin .

Código de autorização em Web Forms

Além de configurar o acesso usando web.config, você também pode configurar programaticamente o acesso e o
comportamento em seu aplicativo Web Forms. Por exemplo, você pode restringir a capacidade de realizar
determinadas operações ou visualizar determinados dados com base na função do usuário.

Este código pode ser usado tanto na lógica code-behind quanto na própria página:

<% if (HttpContext.Current.User.IsInRole("Administradores")) { %>


<a href="/admin"> Vá para Administrador</
a> <% } %>

Além de verificar a associação à função do usuário, você também pode determinar se eles estão autenticados
(embora muitas vezes seja melhor fazer isso usando a configuração baseada em localização abordada acima). Abaixo
está um exemplo dessa abordagem.

protegido void Page_Load(objeto remetente, EventArgs e) {

if (!User.Identity.IsAuthenticated) {

FormsAuthentication.RedirectToLoginPage();

} if (!Roles.IsUserInRole(User.Identity.Name, "Administradores")) {

MessageLabel.Text = "Apenas administradores podem visualizar isto.";


SecretPanel.Visible = falso;
}
}

No código acima, o controle de acesso baseado em função (RBAC) é usado para determinar se determinados elementos
da página, como SecretPanel , são visíveis com base na função do usuário atual.

66 CAPÍTULO 13 | Segurança: Autenticação e Autorização em ASP.NET Web Forms e Blazor


Machine Translated by Google

Normalmente, os aplicativos ASP.NET Web Forms configuram a segurança no arquivo web.config e, em seguida, adicionam
verificações adicionais quando necessário nas páginas .aspx e em seus arquivos code-behind .aspx.cs relacionados . A maioria
dos aplicativos aproveita o provedor de associação universal, frequentemente com o provedor de função adicional.

Identidade principal do ASP.NET


Embora ainda tenha a tarefa de autenticação e autorização, o ASP.NET Core Identity usa um conjunto diferente de abstrações e
suposições quando comparado aos provedores universais. Por exemplo, o novo modelo de identidade oferece suporte à
autenticação de terceiros, permitindo que os usuários se autentiquem usando uma conta de mídia social ou outro provedor de
autenticação confiável. O ASP.NET Core Identity oferece suporte à UI para páginas comumente necessárias, como login, logout
e registro. Ele aproveita o EF Core para acesso a dados e usa migrações do EF Core para gerar o esquema necessário para dar
suporte ao seu modelo de dados. Esta introdução ao Identity no ASP.NET Core fornece uma boa visão geral do que está incluído no
ASP.NET Core Identity e como começar a trabalhar com ele. Se você ainda não configurou o ASP.NET Core Identity em seu
aplicativo e em seu banco de dados, isso o ajudará a começar.

Funções, reivindicações e políticas

Tanto os provedores universais quanto o ASP.NET Core Identity suportam o conceito de funções. Você pode criar funções para
usuários e atribuir funções a usuários. Os usuários podem pertencer a qualquer número de funções e você pode verificar a
associação à função como parte de sua implementação de autorização.

Além das funções, a identidade do ASP.NET Core dá suporte aos conceitos de declarações e políticas. Embora uma função deva
corresponder especificamente a um conjunto de recursos que um usuário nessa função deva ser capaz de acessar, uma
declaração é simplesmente parte da identidade de um usuário. Uma afirmação é um par nome-valor que representa o que o sujeito
é, não o que o sujeito pode fazer.

É possível inspecionar diretamente as declarações de um usuário e determinar com base nesses valores se um usuário deve
receber acesso a um recurso. No entanto, essas verificações são muitas vezes repetitivas e dispersas por todo o sistema.
Uma abordagem melhor é definir uma política.

Uma política de autorização consiste em um ou mais requisitos. As políticas são registradas como parte da configuração do
serviço de autorização no método ConfigureServices de Startup.cs. Por exemplo, o trecho de código a seguir configura uma política
chamada “CanadiansOnly”, que exige que o usuário tenha a declaração Country com o valor “Canadá”.

serviços.AddAuthorization(opções =>
{
options.AddPolicy("CanadiansOnly", política => política.RequireClaim(ClaimTypes.Country, "Canadá"));

});

Você pode aprender mais sobre como criar políticas personalizadas na documentação.

Esteja você usando políticas ou funções, você pode especificar que uma página específica em seu aplicativo Blazor
requer essa função ou política com o atributo [Authorize] , aplicado com o @attribute
diretiva.

Exigindo uma função:

67 CAPÍTULO 13 | Segurança: Autenticação e Autorização em ASP.NET Web Forms e Blazor


Machine Translated by Google

@attribute [Autorizar(Roles = "administradores")]

Exigir que uma política seja satisfeita:

@attribute [Autorizar(Policy = "CanadiansOnly")]

Se você precisar de acesso ao estado de autenticação, às funções ou às declarações de um usuário em seu código, há duas maneiras
principais de obter essa funcionalidade. A primeira é receber o estado de autenticação como parâmetro em cascata. A segunda
é acessar o estado usando um AuthenticationStateProvider injetado. Os detalhes de cada uma dessas abordagens estão descritos na
documentação do Blazor Security.

O código a seguir mostra como receber AuthenticationState como parâmetro em cascata:

[CascadingParameter]
private Task<AuthenticationState> authenticationStateTask { get; definir; }

Com esse parâmetro em vigor, você pode fazer com que o usuário use este código:

var authState = aguarda autenticaçãoStateTask;


var usuário = authState.User;

O código a seguir mostra como injetar o AuthenticationStateProvider:

@usando Microsoft.AspNetCore.Components.Authorization
@inject AuthenticationStateProvider AuthenticationStateProvider

Com o provedor instalado, você pode obter acesso ao usuário com o seguinte código:

AuthenticationState authState = aguarda


AuthenticationStateProvider.GetAuthenticationStateAsync();
Usuário ClaimsPrincipal = authState.User;

if (usuário.Identity.IsAuthenticated)
{
// trabalha com user.Claims e/ou user.Roles
}

Nota: O componente AuthorizeView , abordado posteriormente neste capítulo, fornece uma forma declarativa de controlar o que um
usuário vê em uma página ou componente.

Para trabalhar com usuários e declarações (em aplicativos Blazor Server), talvez você também precise injetar um
UserManager<T> (use IdentityUser por padrão) que pode ser usado para enumerar e modificar declarações para um usuário. Primeiro
injete o tipo e atribua-o a uma propriedade:

@inject UserManager<IdentityUser> MeuUserManager

Em seguida, use-o para trabalhar com as reivindicações do usuário. O exemplo a seguir mostra como adicionar e persistir uma declaração
em um usuário:

tarefa assíncrona privada AddCountryClaim()


{
var authState = aguarda AuthenticationStateProvider.GetAuthenticationStateAsync();
var usuário = authState.User;
var identidadeUser = aguarda MyUserManager.FindByNameAsync(user.Identity.Name);

if (!user.HasClaim(c => c.Type == ClaimTypes.Country))


{

68 CAPÍTULO 13 | Segurança: Autenticação e Autorização em ASP.NET Web Forms e Blazor


Machine Translated by Google

// armazena a declaração no cookie


ID de reivindicação de identidade = new ClaimsIdentity();
id.AddClaim(new Claim(ClaimTypes.Country, "Canadá"));
usuário.AddIdentity(id);

//salva a reclamação no banco de dados


aguarde MyUserManager.AddClaimAsync(identityUser, new Claim(ClaimTypes.Country, "Canadá"));

}
}

Se você precisar trabalhar com funções, siga a mesma abordagem. Pode ser necessário injetar um RoleManager<T>
(use IdentityRole como tipo padrão) para listar e gerenciar as próprias funções.

Nota: Em projetos Blazor WebAssembly, você precisará fornecer APIs de servidor para executar essas operações
(em vez de usar UserManager<T> ou RoleManager<T> diretamente). Um aplicativo cliente Blazor WebAssembly
gerenciaria declarações e/ou funções chamando com segurança os pontos de extremidade da API expostos para essa
finalidade.

Guia de migração
A migração de ASP.NET Web Forms e provedores universais para ASP.NET Core Identity requer várias etapas:

1. Crie o esquema do banco de dados ASP.NET Core Identity no banco de dados de destino

2. Migrar dados do esquema de provedor universal para o esquema de identidade principal do ASP.NET

3. Migre a configuração do web.config para middleware e serviços, normalmente em Program.cs


(ou uma aula de inicialização )

4. Atualize páginas individuais usando controles e condicionais para usar auxiliares de tags e nova identidade
APIs.

Cada uma dessas etapas é descrita em detalhes nas seções a seguir.

Criando o esquema de identidade principal do ASP.NET


Existem várias maneiras de criar a estrutura de tabela necessária usada para o ASP.NET Core Identity. O mais simples
é criar um novo aplicativo Web ASP.NET Core. Escolha Aplicativo Web e altere o tipo de autenticação para usar contas
individuais.

69 CAPÍTULO 13 | Segurança: Autenticação e Autorização em ASP.NET Web Forms e Blazor


Machine Translated by Google

Na linha de comando, você pode fazer a mesma coisa executando dotnet new webapp -au Individual.
Depois de criado o aplicativo, execute-o e cadastre-se no site. Você deve acionar uma página como a
mostrada abaixo:

70 CAPÍTULO 13 | Segurança: Autenticação e Autorização em ASP.NET Web Forms e Blazor


Machine Translated by Google

Clique no botão “Aplicar Migrações” e as tabelas de banco de dados necessárias deverão ser criadas para você.
Além disso, os arquivos de migração deverão aparecer no seu projeto, conforme mostrado:

71 CAPÍTULO 13 | Segurança: Autenticação e Autorização em ASP.NET Web Forms e Blazor


Machine Translated by Google

Você mesmo pode executar a migração, sem executar o aplicativo Web, usando esta ferramenta de linha de
comando:

atualização do banco de dados dotnet ef

Se preferir executar um script para aplicar o novo esquema a um banco de dados existente, você poderá criar scripts
para essas migrações na linha de comando. Execute este comando para gerar o script:

script de migração dotnet ef -o auth.sql

O comando acima produzirá um script SQL no arquivo de saída auth.sql, que pode então ser executado em
qualquer banco de dados de sua preferência. Se você tiver problemas para executar comandos dotnet ef , certifique-
se de ter as ferramentas EF Core instaladas em seu sistema.

Caso você tenha colunas adicionais em suas tabelas de origem, será necessário identificar o melhor local para
essas colunas no novo esquema. Geralmente, as colunas encontradas no aspnet_Membership
tabela deve ser mapeada para a tabela AspNetUsers . As colunas em aspnet_Roles devem ser mapeadas para
AspNetRoles. Quaisquer colunas adicionais na tabela aspnet_UsersInRoles seriam adicionadas à tabela
AspNetUserRoles .

Também vale a pena considerar colocar colunas adicionais em tabelas separadas. Para que as futuras
migrações não precisem de ter em conta tais personalizações do esquema de identidade padrão.

Migrando dados de provedores universais para ASP.NET Core Identity


Depois de definir o esquema da tabela de destino, a próxima etapa é migrar seus registros de usuário e função
para o novo esquema. Uma lista completa das diferenças de esquema, incluindo quais colunas são mapeadas para
quais novas colunas, pode ser encontrada aqui.

72 CAPÍTULO 13 | Segurança: Autenticação e Autorização em ASP.NET Web Forms e Blazor


Machine Translated by Google

Para migrar seus usuários da associação para as novas tabelas de identidade, siga as etapas descritas na
documentação. Depois de seguir essas etapas e o script fornecido, seus usuários precisarão alterar a senha na
próxima vez que fizerem login.

É possível migrar senhas de usuários, mas o processo é muito mais complicado. Exigir que os usuários atualizem
suas senhas como parte do processo de migração e incentivá-los a usar senhas novas e exclusivas provavelmente
aumentará a segurança geral do aplicativo.

Migrando configurações de segurança do web.config para a inicialização do aplicativo

Conforme observado acima, a associação e os provedores de funções do ASP.NET são configurados no


arquivo web.config do aplicativo . Como os aplicativos ASP.NET Core não estão vinculados ao IIS e usam
um sistema separado para configuração, essas configurações devem ser definidas em outro lugar. Na maior parte, a
identidade do ASP.NET Core é configurada no arquivo Program.cs . Abra o projeto web criado anteriormente (para
gerar o esquema da tabela de identidade) e revise seu arquivo Program.cs (ou Startup.cs) .

Este código adiciona suporte para EF Core e Identity:

//Adiciona serviços ao contêiner.


var connectionString = construtor.Configuration.GetConnectionString("DefaultConnection");
construtor.Services.AddDbContext<ApplicationDbContext>(opções =>
opções.UseSqlServer(connectionString));
construtor.Services.AddDatabaseDeveloperPageExceptionFilter();
construtor.Services.AddDefaultIdentity<IdentityUser>(opções =>
opções.SignIn.RequireConfirmedAccount = verdadeiro)
.AddEntityFrameworkStores<ApplicationDbContext>();

O método de extensão AddDefaultIdentity é usado para configurar o Identity para usar o ApplicationDbContext
padrão e o tipo IdentityUser da estrutura . Se você estiver usando um IdentityUser personalizado,
especifique seu tipo aqui. Se esses métodos de extensão não estiverem funcionando em seu aplicativo, verifique
se você possui as instruções using apropriadas e se possui as referências de pacote NuGet necessárias. Por exemplo,
seu projeto deve ter alguma versão do Microsoft.AspNetCore.Identity.EntityFrameworkCore e
Microsoft.AspNetCore.Identity.UI
pacotes referenciados.

Também em Program.cs você deverá ver o middleware necessário configurado para o site. Especificamente,
UseAuthentication e UseAuthorization devem ser configurados e no local apropriado.

// Configure o pipeline de solicitação HTTP.


if (app.Environment.IsDevelopment())
{
app.UseMigrationsEndPoint();
}
outro
{
app.UseExceptionHandler("/Erro");
// O valor padrão do HSTS é 30 dias. Talvez você queira alterar isso para cenários de produção, consulte https://
aka.ms/aspnetcore-hsts.
app.UseHsts();
}

app.UseHttpsRedirection();

app.UseStaticFiles();

73 CAPÍTULO 13 | Segurança: Autenticação e Autorização em ASP.NET Web Forms e Blazor


Machine Translated by Google

app.UseRouting();

app.UseAuthentication();
app.UseAuthorization();

//app.MapControllers();
app.MapBlazorHub();
app.MapFallbackToPage("/_Host");

ASP.NET Identity não configura acesso anônimo ou baseado em função a locais de Program.cs.
Você precisará migrar quaisquer dados de configuração de autorização específicos do local para filtros no ASP.NET
Core. Anote quais pastas e páginas exigirão essas atualizações. Você fará essas alterações na próxima seção.

Atualizando páginas individuais para usar abstrações de identidade principal do ASP.NET


Em seu aplicativo ASP.NET Web Forms, se você tivesse configurações do web.config para negar acesso a
determinadas páginas ou pastas para usuários anônimos, você migraria essas alterações adicionando o [Autorizar]
atribua a essas páginas:

@attribute [Autorizar]

Se você ainda tivesse negado o acesso, exceto aos usuários pertencentes a uma determinada função, você também
migraria esse comportamento adicionando um atributo especificando uma função:

@attribute [Autorizar(Roles = "administradores")]

O atributo [Authorize] funciona apenas em componentes @page que são acessados por meio do Blazor Router.
O atributo não funciona com componentes filhos, que deveriam usar AuthorizeView.

Se você tiver lógica na marcação da página para determinar se algum código deve ser exibido para um determinado usuário,
você poderá substituí-la pelo componente AuthorizeView . O componente AuthorizeView exibe seletivamente a interface
do usuário, dependendo se o usuário está autorizado a vê-la. Também expõe uma variável de contexto que pode ser
usada para acessar informações do usuário.

<AutorizarVisualização>
<Autorizado>
<h1>Olá, @context.User.Identity.Name!</h1>
<p>Você só poderá ver este conteúdo se estiver autenticado.</p>
</Autorizado>
<Não autorizado>
<h1>Falha na autenticação!</h1>
<p>Você não está conectado.</p>
</NotAuthorized>
</AutorizeView>

Você pode acessar o estado de autenticação dentro da lógica processual acessando o usuário de um
Task<AuthenticationState configurado com o atributo [CascadingParameter] . Essa configuração lhe dará acesso ao usuário,
o que permitirá determinar se ele está autenticado e se pertence a uma função específica. Se precisar avaliar uma
política de maneira processual, você poderá injetar uma instância do IAuthorizationService e chamar o método
AuthorizeAsync nela. O código de exemplo a seguir demonstra como obter informações do usuário e permitir que um
usuário autorizado execute uma tarefa restrita pela política do editor de conteúdo .

74 CAPÍTULO 13 | Segurança: Autenticação e Autorização em ASP.NET Web Forms e Blazor


Machine Translated by Google

@usando Microsoft.AspNetCore.Authorization @inject


IAuthorizationService AuthorizationService

<button @onclick="@DoSomething">Faça algo importante</button>

@código {
[CascadingParameter]
private Task<AuthenticationState> authenticationStateTask { get; definir; }

tarefa assíncrona privada DoSomething() {

var usuário = (aguarda autenticaçãoStateTask).User;

if (usuário.Identity.IsAuthenticated) {

// Executa uma ação disponível apenas para usuários autenticados (conectados).


}

if (user.IsInRole("admin")) {

// Execute uma ação disponível apenas para usuários na função 'admin'.


}

if ((aguarde AuthorizationService.AuthorizeAsync(usuário, "editor de conteúdo"))


.Sucesso)
{
// Execute uma ação disponível apenas para usuários que satisfaçam a // política do
'editor de conteúdo'.
}
}
}

O AuthenticationState primeiro precisa ser configurado como um valor em cascata antes de poder ser vinculado
a um parâmetro em cascata como este. Isso normalmente é feito usando o componente
CascadingAuthenticationState . Essa configuração normalmente é feita em App.razor:

<CascadingAuthenticationState> <Router
AppAssembly="@typeof(Program).Assembly"> <Found
Context="routeData">
<AuthorizeRouteView RouteData="@routeData"
DefaultLayout="@typeof(MainLayout)" />
</Encontrado>
<Não encontrado>

<LayoutView Layout="@typeof(MainLayout)">
<p>Desculpe, não há nada neste endereço.</p> </LayoutView>
</NotFound> </
Router> </

CascadingAuthenticationState>

Resumo
Blazor usa o mesmo modelo de segurança do ASP.NET Core, que é ASP.NET Core Identity. A migração de
provedores universais para o ASP.NET Core Identity é relativamente simples, desde que não tenha sido
aplicada muita personalização ao esquema de dados original. Depois que os dados forem migrados, o trabalho

75 CAPÍTULO 13 | Segurança: Autenticação e Autorização em ASP.NET Web Forms e Blazor


Machine Translated by Google

com autenticação e autorização em aplicativos Blazor está bem documentado, com suporte configurável e programático para a
maioria dos requisitos de segurança.

Referências

Introdução à identidade no ASP.NET Core

Migrar da autenticação de associação do ASP.NET para a identidade do ASP.NET Core 2.0

Migrar autenticação e identidade para ASP.NET Core
• Autenticação e autorização do ASP.NET Core Blazor

76 CAPÍTULO 13 | Segurança: Autenticação e Autorização em ASP.NET Web Forms e Blazor


Machine Translated by Google

CAPÍTULO 14

Migrar de formulários da
Web ASP.NET para o Blazor

Migrar uma base de código do ASP.NET Web Forms para o Blazor é uma tarefa demorada que requer planejamento.
Este capítulo descreve o processo. Algo que pode facilitar a transição é garantir que o aplicativo siga uma arquitetura de
N camadas , em que o modelo do aplicativo (neste caso, Web Forms) seja separado da lógica de negócios. Essa
separação lógica de camadas deixa claro o que precisa ser migrado para o .NET Core e o Blazor.

Para este exemplo, o aplicativo eShop disponível no GitHub é usado. eShop é um serviço de catálogo que fornece recursos
CRUD por meio de entrada e validação de formulário.

Por que um aplicativo funcional deve ser migrado para o Blazor? Muitas vezes, não há necessidade. Os Web Forms do
ASP.NET continuarão a ter suporte por muitos anos. No entanto, muitos dos recursos fornecidos pelo Blazor só têm suporte
em um aplicativo migrado. Esses recursos incluem:

Melhorias de desempenho na estrutura, como Span<T>

Capacidade de executar como WebAssembly

Suporte multiplataforma para Linux e macOS

Implantação local de aplicativo ou implantação de estrutura compartilhada sem afetar outros aplicativos

Se esses ou outros novos recursos forem atraentes o suficiente, pode haver valor na migração do aplicativo. A migração
pode assumir diferentes formas; pode ser o aplicativo inteiro ou apenas alguns endpoints que exigem alterações. A decisão
de migrar baseia-se, em última análise, nos problemas de negócios a serem resolvidos pelo desenvolvedor.

Hospedagem do lado do servidor versus hospedagem do lado do cliente

Conforme descrito no capítulo modelos de hospedagem , um aplicativo Blazor pode ser hospedado de duas maneiras
diferentes: no lado do servidor e no lado do cliente. O modelo do lado do servidor usa conexões ASP.NET Core SignalR
para gerenciar as atualizações do DOM enquanto executa qualquer código real no servidor. O modelo do
lado do cliente é executado como WebAssembly em um navegador e não requer conexões de servidor. Existem várias
diferenças que podem afetar qual é o melhor para um aplicativo específico:


A execução como WebAssembly não oferece suporte a todos os recursos (como threading) no momento

A comunicação tagarela entre o cliente e o servidor pode causar problemas de latência no modo do lado do
servidor

77 CAPÍTULO 14 | Migrar de formulários da Web ASP.NET para o Blazor


Machine Translated by Google


O acesso a bancos de dados e serviços internos ou protegidos requerem um serviço separado com hospedagem do lado do cliente

No momento em que este artigo foi escrito, o modelo do lado do servidor se assemelhava mais aos Web Forms. A maior parte deste capítulo

concentra-se no modelo de hospedagem no lado do servidor, já que ele está pronto para produção.

Crie um novo projeto


Esta etapa inicial de migração consiste em criar um novo projeto. Esse tipo de projeto é baseado nos projetos de estilo SDK do .NET e

simplifica grande parte do padrão usado em formatos de projeto anteriores. Para mais detalhes, consulte o capítulo sobre Estrutura do Projeto.

Depois de criado o projeto, instale as bibliotecas que foram utilizadas no projeto anterior. Em projetos Web Forms mais antigos, você pode ter

usado o arquivo packages.config para listar os pacotes NuGet necessários.

No novo projeto estilo SDK, packages.config foi substituído por elementos <PackageReference> no arquivo do projeto. Um benefício dessa

abordagem é que todas as dependências são instaladas transitivamente. Você lista apenas as dependências de nível superior de seu interesse.

Muitas das dependências que você está usando estão disponíveis para .NET, incluindo Entity Framework 6 e log4net. Se não houver

uma versão .NET ou .NET Standard disponível, a versão .NET Framework poderá ser usada com frequência. Sua milhagem pode variar.

Qualquer API usada que não esteja disponível no .NET causa um erro de tempo de execução. O Visual Studio notifica você sobre esses pacotes.

Um ícone amarelo aparece no nó Referências do projeto no Solution Explorer.

No projeto eShop baseado em Blazor, você pode ver os pacotes que estão instalados. Anteriormente, o arquivo packages.config

listava todos os pacotes usados no projeto, resultando em um arquivo com quase 50 linhas. Um trecho de packages.config é:

<?xml version="1.0" encoding="utf-8"?>


<pacotes>
...
<package id="Microsoft.ApplicationInsights.Agent.Intercept" versão="2.4.0"
targetFramework="net472" />
<package id="Microsoft.ApplicationInsights.DependencyCollector" versão="2.9.1"
targetFramework="net472" />
<package id="Microsoft.ApplicationInsights.PerfCounterCollector" versão="2.9.1"
targetFramework="net472" />
<package id="Microsoft.ApplicationInsights.Web" versão="2.9.1" targetFramework="net472"
/>
< id do pacote="Microsoft.ApplicationInsights.WindowsServer" versão="2.9.1"
targetFramework="net472" />
< id do pacote="Microsoft.ApplicationInsights.WindowsServer.TelemetryChannel"
versão="2.9.1" targetFramework="net472" />
<package id="Microsoft.AspNet.FriendlyUrls" version="1.0.2" targetFramework="net472" />
<package id="Microsoft.AspNet.FriendlyUrls.Core" versão="1.0.2" targetFramework="net472"
/>
< id do pacote="Microsoft.AspNet.ScriptManager.MSAjax" versão="5.0.0"
targetFramework="net472" />
<package id="Microsoft.AspNet.ScriptManager.WebForms" versão="5.0.0"
targetFramework="net472" />
...
<package id="System.Memory" version="4.5.1" targetFramework="net472" />
<package id="System.Numerics.Vectors" version="4.4.0" targetFramework="net472" />
<package id="System.Runtime.CompilerServices.Unsafe" versão="4.5.0"

78 CAPÍTULO 14 | Migrar de formulários da Web ASP.NET para o Blazor


Machine Translated by Google

targetFramework="net472" />
<package id="System.Threading.Channels" version="4.5.0" targetFramework="net472" />
<package id="System.Threading.Tasks.Extensions" versão="4.5.1" targetFramework="net472"
/>
<package id="WebGrease" version="1.6.0" targetFramework="net472" />
</pacotes>

O elemento <packages> inclui todas as dependências necessárias. É difícil identificar quais desses pacotes estão incluídos
porque você precisa deles. Alguns elementos <package> são listados simplesmente para satisfazer as necessidades de
dependências necessárias.

O projeto Blazor lista as dependências necessárias em um elemento <ItemGroup> no arquivo do projeto:

<Grupo de Itens>
<PackageReference Include="Autofac" Version="4.9.3" />
<PackageReference Include="EntityFramework" Versão="6.4.4" />
<PackageReference Include="log4net" Versão="2.0.12" />
<PackageReference Inclui = "Microsoft.Extensions.Logging.Log4Net.AspNetCore"
Versão="2.2.12" />
</ItemGroup>

Um pacote NuGet que simplifica a vida dos desenvolvedores de Web Forms é o Windows Compatibility Pack. Embora o .NET
seja multiplataforma, alguns recursos estão disponíveis apenas no Windows. Recursos específicos do Windows são
disponibilizados com a instalação do pacote de compatibilidade. Exemplos de tais recursos incluem Registro, WMI e Serviços
de Diretório. O pacote adiciona cerca de 20.000 APIs e ativa muitos serviços com os quais você já deve estar familiarizado. O projeto
eShop não requer pacote de compatibilidade; mas se seus projetos usarem recursos específicos do Windows, o pacote
facilita os esforços de migração.

Habilitar processo de inicialização


O processo de inicialização do Blazor mudou de Web Forms e segue uma configuração semelhante para outros serviços
ASP.NET Core. Quando hospedados no lado do servidor, os componentes do Razor são executados como parte de um
aplicativo ASP.NET Core normal. Quando hospedados no navegador com WebAssembly, os componentes do Razor usam um
modelo de hospedagem semelhante. A diferença é que os componentes são executados como um serviço separado de
qualquer processo de back-end. De qualquer forma, a inicialização é semelhante.

O arquivo Global.asax.cs é a página de inicialização padrão para projetos Web Forms. No projeto eShop, esse arquivo configura o
contêiner de Inversão de Controle (IoC) e manipula os diversos eventos do ciclo de vida do aplicativo ou solicitação. Alguns desses
eventos são tratados com middleware (como Application_BeginRequest).
Outros eventos exigem a substituição de serviços específicos por meio de injeção de dependência (DI).

A título de exemplo, o arquivo Global.asax.cs para eShop contém o seguinte código:

classe pública Global: HttpApplication, IContainerProviderAccessor


{
private static readonly ILog _log =
LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);

estático IContainerProvider _containerProvider;


Contêiner IContainer;

79 CAPÍTULO 14 | Migrar de formulários da Web ASP.NET para o Blazor


Machine Translated by Google

public IContainerProvider ContainerProvider {

obter { retornar _containerProvider; }


}

protegido void Application_Start(objeto remetente, EventArgs e) {

// Código que é executado na inicialização


do aplicativo RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
ConfigureContainer();
ConfigDataBase();
}

/// <resumo>
/// Acompanhe o nome da máquina e a hora de início da sessão dentro da sessão atual /// </summary>
protected
void
Session_Start(Object sender, EventArgs e) {

HttpContext.Current.Session["Nome da Máquina"] = Ambiente.Nome da Máquina;


HttpContext.Current.Session["SessionStartTime"] = DateTime.Now;
}

/// <summary> ///


https://autofaccn.readthedocs.io/en/latest/integration/webforms.html /// </summary> private
void
ConfigureContainer() {

var construtor = novo ContainerBuilder(); var


mockData = bool.Parse(ConfigurationManager.AppSettings["UseMockData"]);
construtor.RegisterModule(novo ApplicationModule(mockData));
contêiner = construtor.Build();
_containerProvider = novo ContainerProvider(contêiner);
}

private void ConfigDataBase() {

var mockData = bool.Parse(ConfigurationManager.AppSettings["UseMockData"]);

if (!mockData) {

Database.SetInitializer<CatalogDBContext>(container.Resolve<CatalogDBInitializer>());
}
}

protegido void Application_BeginRequest(objeto remetente, EventArgs e) {

//define a propriedade para nosso novo objeto


LogicalThreadContext.Properties["activityid"] = new ActivityIdHelper();

LogicalThreadContext.Properties["requestinfo"] = new WebRequestInfo();

_log.Debug("Application_BeginRequest");
}
}

O arquivo anterior se torna o arquivo Program.cs no Blazor do lado do servidor:

80 CAPÍTULO 14 | Migrar de formulários da Web ASP.NET para o Blazor


Machine Translated by Google

usando eShopOnBlazor.Models;
usando eShopOnBlazor.Models.Infraestrutura; usando
eShopOnBlazor.Services; usando log4net;
usando
System.Data.Entity; usando
eShopOnBlazor;

var construtor = WebApplication.CreateBuilder(args);

//adiciona serviços

construtor.Services.AddRazorPages();
construtor.Services.AddServerSideBlazor();

if (builder.Configuration.GetValue<bool>("UseMockData")) {

construtor.Services.AddSingleton<ICatalogService, CatalogServiceMock>();
}
senão
{
construtor.Services.AddScoped<ICatalogService, CatalogService>();
construtor.Services.AddScoped<IDatabaseInitializer<CatalogDBContext>,
CatalogDBInitializer>();
construtor.Services.AddSingleton<CatalogItemHiLoGenerator>();
construtor.Services.AddScoped(_ => new
CatalogDBContext(builder.Configuration.GetConnectionString("CatalogDBContext"))); }

var app= builder.Build();

novo LoggerFactory().AddLog4Net("log4Net.xml");

if (app.Environment.IsDevelopment()) {

app.UseDeveloperExceptionPage();
}
senão
{
app.UseExceptionHandler("/Home/Erro");
}

// Middleware para Application_BeginRequest app.Use((ctx,


next) => {

LogicalThreadContext.Properties["activityid"] = new ActivityIdHelper(ctx);


LogicalThreadContext.Properties["requestinfo"] = new WebRequestInfo(ctx); retornar próximo();

});

app.UseStaticFiles();

app.UseRouting();

app.UseEndpoints(pontos finais => {

endpoints.MapBlazorHub();
endpoints.MapFallbackToPage("/_Host");
});

ConfigDataBase(aplicativo);

81 CAPÍTULO 14 | Migrar de formulários da Web ASP.NET para o Blazor


Machine Translated by Google

void ConfigDataBase (aplicativo IApplicationBuilder)


{
usando (var escopo = app.ApplicationServices.CreateScope())
{
var inicializador =
escopo.ServiceProvider.GetService<IDatabaseInitializer<CatalogDBContext>>();

if (inicializador! = nulo)
{
Database.SetInitializer(inicializador);
}
}
}

app.Run();

Uma mudança significativa que você pode notar nos Web Forms é a proeminência da injeção de dependência (DI). DI tem
sido um princípio orientador no design do ASP.NET Core. Ele oferece suporte à personalização de quase todos os aspectos
da estrutura ASP.NET Core. Existe até um provedor de serviços integrado que pode ser usado em vários cenários. Se for
necessária mais personalização, ela poderá ser apoiada por muitos projetos comunitários. Por exemplo, você pode
transferir seu investimento em biblioteca DI de terceiros.

No aplicativo eShop original, há algumas configurações para gerenciamento de sessões. Como o Blazor do lado do
servidor usa ASP.NET Core SignalR para comunicação, o estado da sessão não tem suporte, pois as conexões
podem ocorrer independentemente de um contexto HTTP. Um aplicativo que usa o estado de sessão requer uma
rearquitetura antes de ser executado como um aplicativo Blazor.

Para obter mais informações sobre a inicialização do aplicativo, consulte Inicialização do aplicativo.

Migrar módulos e manipuladores HTTP para middleware


Módulos e manipuladores HTTP são padrões comuns em Web Forms para controlar o pipeline de solicitação HTTP.
Classes que implementam IHttpModule ou IHttpHandler podem ser registradas e processar solicitações recebidas. Os
Web Forms configuram módulos e manipuladores no arquivo web.config . Web Forms também é fortemente baseado no
tratamento de eventos do ciclo de vida do aplicativo. Em vez disso, o ASP.NET Core usa middleware. O
middleware é registrado no método Configure da classe Startup . A ordem de execução do middleware é determinada pela
ordem de registro.

Na seção Habilitar processo de inicialização , um evento de ciclo de vida foi gerado pelo Web Forms como
o método Application_BeginRequest . Este evento não está disponível no ASP.NET Core. Uma maneira de obter esse
comportamento é implementar middleware conforme visto no exemplo do arquivo Startup.cs . Esse middleware faz a mesma
lógica e depois transfere o controle para o próximo manipulador no pipeline do middleware.

Para obter mais informações sobre a migração de módulos e manipuladores, consulte Migrar manipuladores e módulos HTTP
para o middleware ASP.NET Core.

82 CAPÍTULO 14 | Migrar de formulários da Web ASP.NET para o Blazor


Machine Translated by Google

Migrar arquivos estáticos


Para servir arquivos estáticos (por exemplo, HTML, CSS, imagens e JavaScript), os arquivos devem ser expostos por middleware.
Chamar o método UseStaticFiles permite o fornecimento de arquivos estáticos do caminho raiz da web. O diretório raiz da web padrão
é wwwroot, mas pode ser personalizado. Conforme incluído no arquivo Program.cs :

...

app.UseStaticFiles();

...

O projeto eShop permite acesso básico a arquivos estáticos. Existem muitas personalizações disponíveis para acesso a arquivos estáticos.

Para obter informações sobre como habilitar arquivos padrão ou um navegador de arquivos, consulte Arquivos estáticos no ASP.NET Core.

Migrar o pacote de tempo de execução e a configuração de minificação


Agrupamento e minificação são técnicas de otimização de desempenho para reduzir o número e o tamanho das solicitações do
servidor para recuperar determinados tipos de arquivos. JavaScript e CSS geralmente passam por alguma forma de
agrupamento ou minificação antes de serem enviados ao cliente. No ASP.NET Web Forms, essas otimizações são tratadas em
tempo de execução. As convenções de otimização são definidas em um arquivo App_Start/ BundleConfig.cs .
No ASP.NET Core, é adotada uma abordagem mais declarativa. Um arquivo lista os arquivos a serem minificados, juntamente
com configurações específicas de minificação.

Para obter mais informações sobre agrupamento e minificação, consulte Agrupar e minificar ativos estáticos no ASP.NET Core.

Migrar páginas ASPX


Uma página em um aplicativo Web Forms é um arquivo com extensão .aspx . Muitas vezes, uma página de Web Forms pode ser
mapeada para um componente no Blazor. Um componente Razor é criado em um arquivo com a extensão .razor . Para o projeto
eShop, cinco páginas são convertidas em uma página Razor.

Por exemplo, a visualização de detalhes compreende três arquivos no projeto Web Forms: Details.aspx, Details.aspx.cs
e Details.aspx.designer.cs. Ao converter para Blazor, o code-behind e a marcação são combinados em Details.razor. A compilação
do Razor (equivalente ao que está nos arquivos .designer.cs ) é armazenada no diretório obj e não pode, por padrão, ser visualizada
no Solution Explorer. A página Web Forms consiste na seguinte marcação:

<%@ Page Title="Detalhes" Language="C#" MasterPageFile="~/Site.Master"


AutoEventWireup = "true" CodeBehind = "Details.aspx.cs"
Inherits="eShopLegacyWebForms.Catalog.Details" %>

<asp:Content ID="Detalhes" ContentPlaceHolderID="MainContent" runat="servidor">


<h2 class="esh-body-title">Detalhes</h2>

<div class="contêiner">
<div class="linha">

83 CAPÍTULO 14 | Migrar de formulários da Web ASP.NET para o Blazor


Machine Translated by Google

<asp:Image runat="server" CssClass="col-md-6 esh-picture" ImageUrl='<%#"/Pics/" + product.PictureFileName%>' /


>
<dl class="col-md-6 dl-horizontal">
<dt>Nome
</dt>

<dd>
<asp:Label runat="servidor" Text='<%#product.Name%>' /> </dd>

<dt>Descrição</dt>

<dd>
<asp:Label runat="server" Text='<%#product.Description%>' /> </dd>

<dt>Marca</
dt>

<dd>
<asp:Label runat="server" Text='<%#product.CatalogBrand.Brand%>' /> </dd>

<dt>Tipo</
dt>

<dd>
<asp:Label runat="server" Text='<%#product.CatalogType.Type%>' /> </dd> <dt>Preço </dt>

<dd>
<asp:Label CssClass="esh-price" runat="servidor"
Text='<%#product.Price%>' /> </dd>

<dt>Nome da imagem
</dt>

<dd>
<asp:Label runat="server" Text='<%#product.PictureFileName%>' /> </dd>

<dt>Estoque</
dt>

<dd>
<asp:Label runat="server" Text='<%#product.AvailableStock%>' /> </dd>

<dt>Reabastecer
</dt>

<dd>
<asp:Label runat="server" Text='<%#product.RestockThreshold%>' /> </dd>

<dt>Estoque
máximo </dt>

84 CAPÍTULO 14 | Migrar de formulários da Web ASP.NET para o Blazor


Machine Translated by Google

<dd>
<asp:Label runat="server" Text='<%#product.MaxStockThreshold%>' /> </dd>

</dl>
</div>

<div class="form-actions no-color esh-link-list">


<a runat="server" href='<%# GetRouteUrl("EditProductRoute", new {id =product.Id}) %>'
class="esh-link-item">Editar
</a>

| <a runat="server" href="~" class="esh-link-item">Voltar à lista </a> </div>

</div>
</asp:Conteúdo>

O code-behind da marcação anterior inclui o seguinte código:

usando eShopLegacyWebForms.Models;
usando eShopLegacyWebForms.Services;
usando log4net;
usando o
sistema; usando System.Web.UI;

namespace eShopLegacyWebForms.Catalog {

Detalhes da classe parcial pública : System.Web.UI.Page {

private static readonly ILog _log =


LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);

produto CatalogItem protegido ;

public ICatalogService CatalogService { obter; definir; }

protegido void Page_Load(objeto remetente, EventArgs e) {

var productId = Convert.ToInt32(Page.RouteData.Values["id"]); _log.Info($"Agora


carregando... /Catalog/Details.aspx?id={productId}"); produto =
CatalogService.FindCatalogItem(produtoId);

this.DataBind();
}
}
}

Quando convertida para Blazor, a página Web Forms é convertida no seguinte código:

@page "/Catalog/Details/{id:int}" @inject


ICatalogService CatalogService @inject
ILogger<Detalhes> Registrador

<h2 class="esh-body-title">Detalhes</h2>

<div class="contêiner">
<div class="linha">

85 CAPÍTULO 14 | Migrar de formulários da Web ASP.NET para o Blazor


Machine Translated by Google

<img class="col-md-6 esh-picture" src="@($"/Pics/{_item.PictureFileName}")">

<dl class="col-md-6 dl-horizontal">


<dt>
Nome
</dt>

<dd>
@_item.Nome
</dd>

<dt>
Descrição

<dd>
@_item.Descrição </dd>

<dt>
Marca
</dt>

<dd>
@_item.CatalogBrand.Brand </dd>

<dt>
Digite
</dt>

<dd>
@_item.CatalogType.Type </
dd>
<dt>
Preço
</dt>

<dd>
@_item.Price </
dd>

<dt>
Nome da imagem
</dt>

<dd>
@_item.PictureFileName </dd>

<dt>
Estoque
</dt>

<dd>
@_item.AvailableStock </dd>

<dt>
Reabastecer
</dt>

86 CAPÍTULO 14 | Migrar de formulários da Web ASP.NET para o Blazor


Machine Translated by Google

<dd>
@_item.RestockThreshold
</dd>

<dt>
Estoque máximo
</dt>

<dd>
@_item.MaxStockThreshold
</dd>

</dl>
</div>

<div class="form-actions no-color esh-link-list">


<a href="@($"/Catalog/Edit/{_item.Id}")" class="esh-link-item">
Editar
</a>
|
<a href="/" class="esh-link-item">
De volta à lista
</a>
</div>

</div>

@código {
private CatalogItem _item;

[Parâmetro]
público int ID {obter; definir; }

substituição protegida void OnInitialized()


{
Logger.LogInformation("Agora carregando... /Catalog/Details/{Id}", Id);

_item = CatalogService.FindCatalogItem(Id);
}
}

Observe que o código e a marcação estão no mesmo arquivo. Quaisquer serviços necessários são disponibilizados com o
atributo @inject . De acordo com a diretiva @page , esta página pode ser acessada na rota
Catalog/Details/{id} . O valor do espaço reservado {id} da rota foi restrito a um número inteiro. Conforme descrito na seção
de roteamento , diferentemente dos Web Forms, um componente Razor declara explicitamente sua rota e quaisquer
parâmetros incluídos. Muitos controles de Web Forms podem não ter equivalentes exatos no Blazor. Muitas
vezes há um trecho de HTML equivalente que serve ao mesmo propósito. Por exemplo, o controle <asp:Label /> pode ser
substituído por um elemento HTML <label> .

Validação de modelo no Blazor


Se o seu código de Web Forms incluir validação, você poderá transferir muito do que possui com pouca ou nenhuma
alteração. Um benefício de executar no Blazor é que a mesma lógica de validação pode ser executada sem a necessidade
de JavaScript personalizado. As anotações de dados permitem fácil validação do modelo.

87 CAPÍTULO 14 | Migrar de formulários da Web ASP.NET para o Blazor


Machine Translated by Google

Por exemplo, a página Create.aspx possui um formulário de entrada de dados com validação. Um trecho de exemplo ficaria
assim:

<div class="form-group">
<label class="control-label col-md-2">Nome</label>
<div class="col-md-3">
<asp:TextBox ID="Nome" runat="servidor" CssClass="form-control"></asp:TextBox>
<asp:RequiredFieldValidator runat="servidor" ControlToValidate="Nome"
Exibir = "Dinâmico"
CssClass="field-validation-valid text-danger" ErrorMessage="O campo Nome é obrigatório." />

</div>
</div>

No Blazor, a marcação equivalente é fornecida em um arquivo Create.razor :

<EditForm Model="_item" OnValidSubmit="@...">


<DataAnnotationsValidator />

<div class="form-group">
<label class="control-label col-md-2">Nome</label>
<div class="col-md-3">
<InputText class="form-control" @bind-Value="_item.Name" />
<ValidationMessage For="(() => _item.Nome)" />
</div>
</div>

...
</EditForm>

O contexto EditForm inclui suporte de validação e pode ser agrupado em torno de uma entrada. As anotações de
dados são uma forma comum de adicionar validação. Esse suporte de validação pode ser adicionado por meio do
componente DataAnnotationsValidator . Para obter mais informações sobre esse mecanismo, consulte Formulários e validação
do ASP.NET Core Blazor.

Migrar configuração
Em um projeto Web Forms, os dados de configuração são mais comumente armazenados no arquivo web.config . Os
dados de configuração são acessados com ConfigurationManager. Freqüentemente, os serviços eram necessários para
analisar objetos. Com o .NET Framework 4.7.2, a capacidade de composição foi adicionada à configuração
por meio de ConfigurationBuilders. Esses construtores permitiram que os desenvolvedores adicionassem várias
fontes para a configuração que era então composta em tempo de execução para recuperar os valores necessários.

O ASP.NET Core introduziu um sistema de configuração flexível que permite definir a fonte ou fontes de configuração usadas
pelo seu aplicativo e implantação. A infraestrutura do ConfigurationBuilder que você pode estar usando em seu aplicativo Web
Forms foi modelada com base nos conceitos usados no sistema de configuração do ASP.NET Core.

O snippet a seguir demonstra como o projeto Web Forms eShop usa web.config para armazenar valores de configuração:

<configuração>
<seções de configuração>
< nome da seção="entityFramework"

88 CAPÍTULO 14 | Migrar de formulários da Web ASP.NET para o Blazor


Machine Translated by Google

type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Versão=6.0.0.0,


Culture=neutro, PublicKeyToken=b77a5c561934e089"
requirePermission = "falso" />
</configSections>
<connectionStrings>
<add name="CatalogDBContext" connectionString=" Fonte de dados=(localdb)\MSSQLLocalDB; Catálogo
Inicial=Microsoft.eShopOnContainers.Services.CatalogDb; Segurança Integrada=True; MultipleActiveResultSets=True;"
provedorName="System.Data.SqlClient" />
</connectionStrings>
<configurações do aplicativo>

<add key="UseMockData" value="true" />


<add key="UseCustomizationData" value="false" />
</appSettings>
</configuração>

É comum que segredos, como cadeias de conexão de banco de dados, sejam armazenados no web.config. Os
segredos persistem inevitavelmente em locais inseguros, como o controle de origem. Com o Blazor no ASP.NET Core,
a configuração anterior baseada em XML é substituída pelo seguinte JSON:

{
"ConnectionStrings": {
"CatalogDBContext": "Fonte de dados=(localdb)\\MSSQLLocalDB; Catálogo
Inicial=Microsoft.eShopOnContainers.Services.CatalogDb; Segurança Integrada=True;
MultipleActiveResultSets=True;"
},
"UseMockData": verdadeiro,
"UseCustomizationData": falso
}

JSON é o formato de configuração padrão; entretanto, o ASP.NET Core oferece suporte a muitos outros
formatos, incluindo XML. Existem também vários formatos suportados pela comunidade.

Você pode acessar os valores de configuração do construtor em Program.cs:

if (builder.Configuration.GetValue<bool>("UseMockData"))
{
construtor.Services.AddSingleton<ICatalogService, CatalogServiceMock>();
}
outro
{
construtor.Services.AddScoped<ICatalogService, CatalogService>();
construtor.Services.AddScoped<IDatabaseInitializer<CatalogDBContext>,
CatalogDBInitializer>();
construtor.Services.AddSingleton<CatalogItemHiLoGenerator>();
construtor.Services.AddScoped(_ => novo
CatalogDBContext(builder.Configuration.GetConnectionString("CatalogDBContext")));
}

Por padrão, variáveis de ambiente, arquivos JSON (appsettings.json e appsettings.{Environment}.json) e opções de


linha de comando são registrados como fontes de configuração válidas no objeto de configuração. As fontes de
configuração podem ser acessadas via Configuration[key]. Uma técnica mais avançada é vincular os dados de
configuração a objetos usando o padrão de opções. Para obter mais informações sobre configuração e
padrão de opções, consulte Configuração no ASP.NET Core e padrão de opções no ASP.NET Core,
respectivamente.

89 CAPÍTULO 14 | Migrar de formulários da Web ASP.NET para o Blazor


Machine Translated by Google

Migrar o acesso aos dados

O acesso aos dados é um aspecto importante de qualquer aplicativo. O projeto eShop armazena informações do catálogo em
um banco de dados e recupera os dados com o Entity Framework (EF) 6. Como o EF 6 é compatível com o .NET 5, o projeto
pode continuar a usá-lo.

As seguintes alterações relacionadas ao EF foram necessárias no eShop:


No .NET Framework, o objeto DbContext aceita uma string no formato name=ConnectionString
e usa a string de conexão de ConfigurationManager.AppSettings[ConnectionString]
conectar. No .NET Core, isso não é compatível. A cadeia de conexão deve ser fornecida.

• O banco de dados foi acessado de forma síncrona. Embora isso funcione, a escalabilidade pode ser prejudicada. Esse
a lógica deve ser movida para um padrão assíncrono.

Embora não haja o mesmo suporte nativo para vinculação de conjunto de dados, o Blazor fornece flexibilidade e potência com seu
suporte C# em uma página Razor. Por exemplo, você pode realizar cálculos e exibir o resultado.
Para obter mais informações sobre padrões de dados no Blazor, consulte o capítulo Acesso a dados .

Mudanças arquitetônicas

Finalmente, há algumas diferenças arquitetônicas importantes a serem consideradas ao migrar para o Blazor. Muitas dessas alterações
são aplicáveis a qualquer coisa baseada em .NET Core ou ASP.NET Core.

Como o Blazor é criado no .NET Core, há considerações para garantir o suporte no .NET Core. Algumas das principais mudanças
incluem a remoção dos seguintes recursos:


Vários AppDomains

Remoção

• Segurança de acesso ao código (CAS)



Transparência de segurança
Para obter mais informações sobre técnicas para identificar as alterações necessárias para dar suporte à execução no .NET
Core, consulte Portar seu código do .NET Framework para o .NET Core.

O ASP.NET Core é uma versão reinventada do ASP.NET e tem algumas alterações que podem não parecer óbvias à primeira
vista. As principais mudanças são:

• Nenhum contexto de sincronização, o que significa que não há HttpContext.Current,


Thread.CurrentPrincipal ou outros acessadores estáticos

• Sem cópia de sombra

• Sem fila de solicitações

Muitas operações no ASP.NET Core são assíncronas, o que permite um descarregamento mais fácil de tarefas vinculadas a E/
S. É importante nunca bloquear usando Task.Wait() ou Task.GetResult(), que pode esgotar rapidamente os recursos do pool de
threads.

90 CAPÍTULO 14 | Migrar de formulários da Web ASP.NET para o Blazor


Machine Translated by Google

Conclusão da migração
Neste ponto, você viu muitos exemplos do que é necessário para mover um projeto Web Forms para o Blazor. Para um
exemplo completo, consulte o eShopOnBlazor projeto.

91 CAPÍTULO 14 | Migrar de formulários da Web ASP.NET para o Blazor

Você também pode gostar