Dê a sua opinião sobre a experiência de download do PDF.
Documentação do ASP.NET
Aprenda a usar o ASP.NET Core para criar aplicativos Web e serviços rápidos, seguros,
multiplataforma e baseados em nuvem. Procure tutoriais, código de exemplo, conceitos básicos,
referência de API e muito mais.
COMEÇAR AGORA VISÃO GERAL
Crie um aplicativo ASP.NET Core Visão geral do ASP.NET Core
em qualquer plataforma em 5
minutos
BAIXAR NOVIDADES
Baixar o .NET Novidades nos documentos do
ASP.NET Core
COMEÇAR AGORA COMEÇAR AGORA
Crie sua primeira interface do Crie sua primeira API Web
usuário da Web
COMEÇAR AGORA VISÃO GERAL
Crie seu primeiro aplicativo Web Documentação do ASP.NET 4.x
em tempo real
Desenvolver aplicativos ASP.NET Core
Escolha aplicativos Web interativos, APIs Web, aplicativos padronizados por MVC, aplicativos em tempo
real e muito mais
Aplicativos Blazor Aplicativos de API Interface do usuário da
interativos no lado do HTTP Web focada em
cliente Desenvolver serviços HTTP páginas com o Razor…
Desenvolva com componentes com ASP.NET Core Desenvolver aplicativos Web
de interface do usuário b Criar uma API Web mínima focados em páginas com uma
reutilizáveis que podem com ASP.NET Core separação clara de interesses
aproveitar o WebAssembly…
d Criar uma API Web com os b Crie seu primeiro aplicativo
e Visão geral controladores do ASP.NET Web do Razor Pages
Core
b Como criar seu primeiro g Crie uma Interface do
aplicativo Blazor g Gerar páginas de ajuda da usuário da Web focada em
API Web com o páginas que consome uma
b Crie seu primeiro aplicativo Swagger/OpenAPI
Blazor com componentes API Web
reutilizáveis p Tipos de retorno de ação p Sintaxe Razor
do controlador
p Modelos de hospedagem p Filtros
do Blazor p Formatar dados de
resposta p Roteamento
p Tratar erros p Aplicativos Web ASP.NET
Core acessíveis
g Chamar uma API Web do
ASP.NET Core com o
JavaScript
Interface do usuário da Aplicativos Web em Aplicativos de RPC
Web focada em tempo real com o (Chamada de
páginas com MVC SignalR Procedimento Remot…
Desenvolva aplicativos Web Adicione funcionalidade em Desenvolva serviços de alto
usando o padrão de design do tempo real ao seu aplicativo desempenho e contract-first
Model-View-Controller Web e habilite o código do com o gRPC no ASP.NET Core
lado do servidor para enviar…
e Visão geral e Visão geral
e Visão geral
b Crie seu primeiro aplicativo b Criar um cliente e servidor
ASP.NET Core MVC b Crie seu primeiro aplicativo gRPC
SignalR
p Exibições p Conceitos dos serviços
g SignalR com Blazor gRPC em C#
p Exibições parciais
WebAssembly
s Exemplos
p Controladores
g SignalR com TypeScript
p Ações de roteamento para p Comparar serviços gRPC
o controlador
s Exemplos com APIs HTTP
p Hubs g Adicionar um serviço gRPC
p Teste de unidade
a um aplicativo ASP.NET
p Recursos de cliente SignalR
Core
p Hospedar e dimensionar
g Chamar os serviços gRPC
com o cliente .NET
g Usar o gRPC em aplicativos
de navegador
Aplicativos Web Versões anteriores do Tutoriais em vídeo do
controlados por dados ASP.NET Framework ASP.NET Core
Criar aplicativos Web Explore as visões gerais,
q Série de vídeos básicos do
controlados por dados no tutoriais, conceitos
ASP.NET Core
ASP.NET Core fundamentais, arquitetura e
q
g SQL com o ASP.NET Core referência de API para versõe…
q Série de vídeos básicos do
Entity Framework Core
p Associação de dados no p ASP.NET 4.x com .NET Core e ASP.NET
ASP.NET Core Blazor
Core
g SQL Server Express e Razor
Pages
q Arquitetura de
microsserviço com o
g Entity Framework Core ASP.NET Core
com o Razor Pages
q Concentre-se na série de
g Entity Framework Core vídeos Blazor
com o ASP.NET Core MVC
q .NET Channel
g Armazenamento do Azure
g Armazenamento de Blobs
p Armazenamento de
Tabelas do Azure
p Cenários do Microsoft
Graph para ASP.NET Core
Conceitos e funcionalidades
Referência de API para ASP.NET Core Hospedar e implantar
Navegador da API .NET Visão geral
Implantar no Serviço de Aplicativo do Azure
DevOps para desenvolvedores ASP.NET principais
Linux com o Apache
Linux com o Nginx
Kestrel
IIS
Docker
Segurança e identidade Globalização e localização
Visão geral Visão geral
Autenticação Localização de objeto portátil
Autorização Extensibilidade de localização
Curso: Proteger um aplicativo Web ASP.NET Core Solução de problemas
com a estrutura de Identidade
Proteção de dados
Gerenciamento de segredos
Impor o HTTPS
Hospedar o Docker com HTTPS
Testar, depurar e solucionar problemas Azure e ASP.NET Core
Testes de unidades de páginas Razor Implantar um aplicativo Web do ASP.NET Core
Depuração remota ASP.NET Core e Docker
Depuração de instantâneo Hospedar um aplicativo Web com o Serviço de
Aplicativo do Azure
Testes de integração
Serviço de Aplicativo e Banco de Dados SQL do
Testes de estresse e carga
Azure
Solucionar problemas e depurar
Identidade gerenciada com o ASP.NET Core e o
Registrando em log Banco de Dados SQL do Azure
Teste de carga de aplicativos Web do Azure usando API Web com CORS no Serviço de Aplicativo do
o Azure DevOps Azure
Capturar logs de aplicativos Web com o log de
diagnóstico do Serviço de Aplicativo
Desempenho Recursos avançados
Visão geral Model binding
Memória e coleta de lixo Validação de modelo
Cache de resposta Gravar middleware
Compactação de resposta Operações de solicitação e de resposta
Ferramentas de diagnóstico Reescrita de URL
Testes de estresse e carga
Migração Arquitetura
ASP.NET Core 5.0 a 6.0 Escolher entre aplicativos Web tradicionais e SPAs
(aplicativos de página única)
ASP.NET Principais exemplos de código 5.0 para o
modelo de hospedagem mínimo 6.0 Princípios de arquitetura
ASP.NET Core 3.1 a 5.0 Arquiteturas comuns de aplicativo Web
ASP.NET Core 3.0 a 3.1 Tecnologias da Web comuns do lado do cliente
ASP.NET Core 2.2 a 3.0 Processo de desenvolvimento para o Azure
ASP.NET Core 2.1 a 2.2
ASP.NET Core 2.0 para 2.1
ASP.NET Core 1.x para 2.0
ASP.NET para ASP.NET Core
Contribua para a documentação do ASP.NET Core. Leia nosso guia do colaborador .
Documentação do ASP.NET Core – Quais
são as novidades?
Bem-vindo às novidades nos documentos do ASP.NET Core. Use esta página para
localizar rapidamente as alterações mais recentes.
Localizar atualizações de documentos do ASP.NET Core
h NOVIDADES
Junho de 2022
Março de 2022
Fevereiro de 2022
Janeiro de 2022
Dezembro de 2021
Novembro de 2021
Participe – contribua para a documentação do ASP.NET Core
e VISÃO GERAL
Repositório de documentos do ASP.NET Core
Estrutura e rótulos do projeto para problemas e solicitações de pull
p CONCEITO
Guia do colaborador do Microsoft Docs
Guia do colaborador do ASP.NET Core
Guia do colaborador de documentos de referência da API do ASP.NET Core
Comunidade
h NOVIDADES
Comunidade
Comunidade
Páginas de novidades relacionadas
h NOVIDADES
Atualizações de documentos do Xamarin
Notas sobre a versão do .NET Core
Notas sobre a versão do ASP.NET Core
Notas sobre a versão do compilador C# (Roslyn)
Notas sobre a versão do Visual Studio
Notas sobre a versão do Visual Studio para Mac
Notas sobre a versão do Visual Studio Code
Visão geral do ASP.NET Core
Artigo • 28/11/2022 • 11 minutos para o fim da leitura
Por Daniel Roth , Rick Anderson e Shaun Luttin
ASP.NET Core é uma estrutura de software livre multiplataforma, de alto desempenho e
de software livre para a criação de aplicativos modernos habilitados para nuvem e
conectados à Internet.
Com o ASP.NET Core, você pode:
Crie aplicativos e serviços Web, aplicativos de Internet das Coisas (IoT) e back-
ends móveis.
Usar suas ferramentas de desenvolvimento favoritas no Windows, macOS e Linux.
Implantar na nuvem ou local.
Execute no .NET Core.
Por que escolher o ASP.NET Core?
Milhões de desenvolvedores usam ou usaram ASP.NET 4.x para criar aplicativos Web.
ASP.NET Core é uma reformulação do ASP.NET 4.x, incluindo alterações arquitetônicas
que resultam em uma estrutura mais enxuta e modular.
O ASP.NET Core oferece os seguintes benefícios:
Uma história unificada para a criação da interface do usuário da Web e das APIs
Web.
Projetado para capacidade de teste.
Razor As páginas tornam os cenários focados em página de codificação mais fáceis
e produtivos.
Blazor permite que você use C# no navegador ao lado de JavaScript. Compartilhe
a lógica de aplicativo do lado do cliente e do servidor toda escrita com o .NET.
Capacidade de desenvolver e executar no Windows, macOS e Linux.
De software livre e voltado para a comunidade .
Integração de estruturas modernas do lado do cliente e fluxos de trabalho de
desenvolvimento.
Suporte para hospedagem de serviços RPC (chamada de procedimento remoto)
usando gRPC.
Um sistema de configuração pronto para a nuvem, baseado no ambiente.
Injeção de dependência interna.
Um pipeline de solicitação HTTP leve, modular e de alto desempenho .
Capacidade de hospedar no seguinte:
Kestrel
IIS
HTTP.sys
Nginx
Apache
Docker
Controle de versão lado a lado.
Ferramentas que simplificam o moderno desenvolvimento para a Web.
Compilar APIs Web e uma interface do usuário
da Web usando o ASP.NET Core MVC
O ASP.NET Core MVC fornece recursos que ajudam você a compilar APIs Web e
aplicativos Web:
O padrão MVC (Model-View-Controller) ajuda a tornar as APIs Web e os
aplicativos Web testáveis.
Razor Pages é um modelo de programação baseado em página que torna a
criação da interface do usuário da Web mais fácil e produtiva.
Razor A marcação fornece uma sintaxe produtiva para Razor exibições de Páginas
e MVC.
Os Auxiliares de Marcação permitem que o código do servidor participe da criação
e renderização de elementos HTML em arquivos do Razor.
O suporte interno para vários formatos de dados e negociação de conteúdo
permite que as APIs Web alcancem uma ampla gama de clientes, incluindo
navegadores e dispositivos móveis.
O model binding mapeia automaticamente os dados de solicitações HTTP para os
parâmetros de método de ação.
A Validação de Modelos executa automaticamente a validação no lado do cliente e
do servidor.
Desenvolvimento do lado do cliente
ASP.NET Core se integra perfeitamente a estruturas e bibliotecas populares do lado do
cliente, incluindo Blazor, Angular, React e Bootstrap . Para obter mais informações,
consulte ASP.NET Core Blazor e tópicos relacionados em Desenvolvimento do lado do
cliente.
estruturas de destino ASP.NET Core
ASP.NET Core 3.x ou posterior só pode ser direcionado ao .NET Core. Geralmente,
ASP.NET Core é composto por bibliotecas .NET Standard. As bibliotecas gravadas com
.NET Standard 2.0 podem ser executadas em qualquer plataforma .NET que implemente
o .NET Standard 2.0.
Há várias vantagens em direcionar para o .NET Core, e essas vantagens aumentam com
cada versão. Algumas vantagens do .NET Core em relação ao .NET Framework incluem:
Multiplataforma. É executado no Windows, macOS e Linux.
desempenho aprimorado
Controle de versão lado a lado
Novas APIs
Software livre
Caminho de aprendizado recomendado
Recomendamos a seguinte sequência de tutoriais para uma introdução ao
desenvolvimento de aplicativos ASP.NET Core:
1. Siga um tutorial para o tipo de aplicativo que você deseja desenvolver ou manter.
Tipo de aplicativo Cenário Tutorial
Aplicativo Web Novo desenvolvimento de interface do Introdução ao
usuário da Web do lado do servidor Razor Pages
Aplicativo Web Mantendo um aplicativo MVC Introdução ao
MVC
Aplicativo Web Desenvolvimento da interface do usuário Introdução ao
da Web do lado do cliente Blazor
API Web RESTserviços HTTP ful Criar uma API
Web†
Aplicativo de Chamada de Serviços de primeiro contrato usando Introdução a
Procedimento Remoto buffers de protocolo um serviço
gRPC
Aplicativo em tempo real Comunicação bidirecional entre servidores Introdução ao
e clientes conectados SignalR
2. Siga um tutorial que mostra como fazer o acesso básico a dados.
Cenário Tutorial
Novo desenvolvimento Razor Páginas com o Entity Framework Core
Mantendo um aplicativo MVC MVC com o Entity Framework Core
3. Leia uma visão geral dos conceitos básicos ASP.NET Core que se aplicam a todos
os tipos de aplicativo.
4. Procure no sumário outros tópicos de interesse.
†Tere também é um tutorial interativo da API Web. Nenhuma instalação local de
ferramentas de desenvolvimento é necessária. O código é executado em um Cloud Shell
do Azure no navegador e o curl é usado para teste.
Migrar do .NET Framework
Para obter um guia de referência para migrar aplicativos ASP.NET 4.x para ASP.NET
Core, consulte Migrar de ASP.NET para ASP.NET Core.
Como baixar uma amostra
Muitos dos artigos e tutoriais incluem links para exemplos de código.
1. Baixe o arquivo zip do repositório ASP.NET .
2. Descompacte o arquivo AspNetCore.Docs-main.zip .
3. Para acessar o aplicativo de exemplo de um artigo no repositório descompactado,
use a URL no link de exemplo do artigo para ajudá-lo a navegar até a pasta do
exemplo. Normalmente, o link de exemplo de um artigo aparece na parte superior
do artigo com o texto do link Exibir ou baixar o código de exemplo.
Diretivas do pré-processador no código de exemplo
Para demonstrar vários cenários, os aplicativos de exemplo usam as #define diretivas de
pré-processador e #if-#else/#elif-#endif para compilar e executar seletivamente
diferentes seções de código de exemplo. Para os exemplos que usam essa abordagem,
defina a #define diretiva na parte superior dos arquivos C# para definir o símbolo
associado ao cenário que você deseja executar. Alguns exemplos exigem a definição do
símbolo na parte superior de vários arquivos para executar um cenário.
Por exemplo, a seguinte lista de símbolo #define indica que quatro cenários estão
disponíveis (um cenário por símbolo). A configuração da amostra atual executa o
cenário TemplateCode :
C#
#define TemplateCode // or LogFromMain or ExpandDefault or FilterInCode
Para alterar a amostra que executará o cenário ExpandDefault , defina o símbolo
ExpandDefault e deixe os símbolos restantes comentados de fora:
C#
#define ExpandDefault // TemplateCode or LogFromMain or FilterInCode
Para obter mais informações sobre como usar diretivas de pré-processador C# para
compilar seletivamente as seções de código, consulte #define (Referência C#) e #if
(Referência C#) .
Regiões no código de exemplo
Alguns aplicativos de exemplo contêm seções de código cercadas por diretivas #region
e #endregion C#. O sistema de build de documentação injeta essas regiões nos tópicos
renderizados da documentação.
Os nomes de região geralmente contêm a palavra "snippet". O exemplo a seguir mostra
uma região chamada snippet_WebHostDefaults :
C#
#region snippet_WebHostDefaults
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
#endregion
O snippet de código C# precedente é referenciado no arquivo de markdown do tópico
com a seguinte linha:
Markdown
[!code-csharp[](sample/SampleApp/Program.cs?name=snippet_WebHostDefaults)]
Você pode ignorar com segurança (ou remover) as #region diretivas e #endregion que
cercam o código. Não altere o código dentro dessas diretivas se você planeja executar
os cenários de exemplo descritos no tópico. Fique à vontade para alterar o código ao
experimentar com outros cenários.
Para obter mais informações, veja Contribuir para a documentação do ASP.NET: snippets
de código .
Alterações interruptivas e avisos de segurança
Alterações interruptivas e avisos de segurança são relatados no repositório
Comunicados . Os anúncios podem ser limitados a uma versão específica selecionando
um filtro rótulo .
Próximas etapas
Para saber mais, consulte os recursos a seguir:
Introdução ao ASP.NET Core
Publicar um aplicativo ASP.NET Core no Azure com o Visual Studio
conceitos básicos ASP.NET Core
O Community Standup semanal do ASP.NET aborda o progresso e os planos da
equipe. Ele apresenta o novo software de terceiros e blogs.
Escolher entre o ASP.NET 4.x e o
ASP.NET Core
Artigo • 10/01/2023 • 2 minutos para o fim da leitura
O ASP.NET Core é uma reformulação do ASP.NET 4. x. Este artigo lista as diferenças
entre eles.
ASP.NET Core
O ASP.NET Core é uma estrutura de software livre, multiplataforma, para a criação de
aplicativos Web modernos e baseados em nuvem, no Windows, no macOS ou no Linux.
O ASP.NET Core oferece os seguintes benefícios:
Uma história unificada para a criação da interface do usuário da Web e das APIs
Web.
Projetado para capacidade de teste.
Razor As páginas tornam os cenários focados em página de codificação mais fáceis
e produtivos.
Blazor permite que você use C# no navegador ao lado de JavaScript. Compartilhe
a lógica de aplicativo do lado do cliente e do servidor toda escrita com o .NET.
Capacidade de desenvolver e executar no Windows, macOS e Linux.
De software livre e voltado para a comunidade .
Integração de estruturas modernas do lado do cliente e fluxos de trabalho de
desenvolvimento.
Suporte para hospedagem de serviços RPC (chamada de procedimento remoto)
usando gRPC.
Um sistema de configuração pronto para a nuvem, baseado no ambiente.
Injeção de dependência interna.
Um pipeline de solicitação HTTP leve, modular e de alto desempenho .
Capacidade de hospedar no seguinte:
Kestrel
IIS
HTTP.sys
Nginx
Apache
Docker
Controle de versão lado a lado.
Ferramentas que simplificam o moderno desenvolvimento para a Web.
ASP.NET 4.x
O ASP.NET 4.x é uma estrutura consolidada que fornece os serviços necessários para
criar aplicativos Web baseados em servidor, de nível empresarial, no Windows.
Seleção de estrutura
A tabela a seguir compara o ASP.NET Core com o ASP.NET 4. x.
ASP.NET Core ASP.NET 4.x
Build para Windows, macOS ou Linux Build para Windows
Razor Pages é a abordagem recomendada para criar uma Usar Web Forms, SignalR,
interface do usuário da Web a partir do ASP.NET Core 2.x. MVC, API Web, WebHooks
Consulte também MVC, API Web e SignalR. ou Páginas da Web
Várias versões por computador Uma versão por computador
Desenvolva com o Visual Studio , Visual Studio para Mac ou Desenvolver com o Visual
Visual Studio Code usando C# ou F# Studio usando C#, VB ou F
#
Desempenho superior ao do ASP.NET 4.x Bom desempenho
Usar o runtime do .NET Core Use o runtime do .NET
Framework
Confira ASP.NET Core targeting .NET Framework (ASP.NET Core direcionado para o .NET
Framework) para obter informações sobre o suporte do ASP.NET Core 2.x no .NET
Framework.
Cenários do ASP.NET Core
Sites
APIs
Em tempo real
Implantar um aplicativo do ASP.NET Core no Azure
Cenários do ASP.NET 4.x
Sites
APIs
Em tempo real
Criar um aplicativo Web ASP.NET 4.x no Azure
Recursos adicionais
Introdução ao ASP.NET
Introdução ao ASP.NET Core
Implantar aplicativos ASP.NET Core no Serviço de Aplicativo do Azure
.NET 5 vs. .NET Framework para
aplicativos de servidor
Artigo • 28/11/2022 • 6 minutos para o fim da leitura
Há duas implementações do .NET com suporte para a criação de aplicativos do lado do
servidor.
Implementação Versões incluídas
.NET .NET Core 1.0 – 3.1, .NET 5 e versões posteriores do .NET.
.NET Framework .NET Framework 1.0 - 4.8
Ambas compartilham muitos dos mesmos componentes, e você pode compartilhar
código entre as duas. No entanto, há diferenças fundamentais entre os dois e sua
escolha depende do que você deseja realizar. Este artigo diretrizes sobre quando usar
cada um.
Use o .NET Core no seu aplicativo de servidor se:
Você tiver necessidades de plataforma cruzada.
Você estiver direcionando microsserviços.
Você estiver usando contêineres do Docker.
Você precisar de alto desempenho e sistemas escalonáveis.
Você precisar de versões do .NET correspondentes a cada aplicativo.
Use o .NET Framework para o aplicativo para servidores se:
Seu aplicativo usar o .NET Framework atualmente (a recomendação é estender em
vez de migrar).
Seu aplicativo usar bibliotecas de terceiros ou pacotes NuGet não disponíveis para
o .NET.
Seu aplicativo usar tecnologias .NET Framework que não estão disponíveis para o
.NET.
Seu aplicativo usar uma plataforma que não oferece suporte ao .NET.
Quando escolher o .NET
As seguintes seções oferecem uma explicação mais detalhada sobre os motivos
mencionados anteriormente para escolher o .NET em vez do .NET Framework.
Necessidades de plataforma cruzada
Se o aplicativo Web ou aplicativo de serviço precisar ser executado em várias
plataformas, por exemplo, Windows, Linux e macOS, use o .NET.
O .NET dá suporte aos sistemas operacionais mencionados anteriormente como sua
estação de trabalho de desenvolvimento. O Visual Studio fornece um IDE (ambiente de
desenvolvimento integrado) para Windows e macOS. Você também pode usar o Visual
Studio Code, que é executado no Windows, Linux e macOS. O Visual Studio Code dá
suporte ao .NET, incluindo IntelliSense e depuração. A maioria dos editores de terceiros,
como Sublime, Emacs e VI, trabalham com o .NET. Esses editores de terceiros obtém o
IntelliSense do editor usando o Omnisharp . Você também pode evitar qualquer editor
de código e usar diretamente a CLI do .NET, que está disponível para todas as
plataformas com suporte.
Arquitetura de microsserviços
Uma arquitetura de microsserviços possibilita uma combinação de tecnologias em um
limite de serviço. Essa combinação de tecnologias permite uma adoção gradual do .NET
para novos microsserviços que funcionam com outros serviços ou microsserviços. Por
exemplo, você pode combinar microsserviços ou serviços desenvolvidos com .NET
Framework, Java, Ruby ou outras tecnologias monolíticas.
Há muitas plataformas de infraestrutura disponíveis. O Azure Service Fabric é criado
para sistemas de microsserviço grandes e complexos. O Serviço de Aplicativo do
Azure é uma boa escolha para microsserviços sem monitoração de estado.
Alternativas de microsserviços com base no Docker se encaixam em qualquer
abordagem de microsserviços, conforme explicado na seção Contêineres . Todas essas
plataformas oferecem suporte ao .NET, e são ideais para hospedar microsserviços.
Para mais informações sobre arquitetura de microsserviços, consulte Microsserviços
.NET. Arquitetura para aplicativos .NET em contêineres.
Contêineres
Os contêineres são comumente usados com uma arquitetura de microsserviços. Os
contêineres também podem ser usados para colocar em contêiner os aplicativos ou
serviços Web que seguem qualquer padrão de arquitetura. .NET Framework podem ser
usados em contêineres do Windows. Ainda assim, a modularidade e a natureza leve do
.NET o tornam uma opção melhor para contêineres. Quando você está criando e
implantando um contêiner, o tamanho de sua imagem é muito menor com o .NET do
que com .NET Framework. Como ele é multiplataforma, você pode implantar aplicativos
de servidor em contêineres do Docker do Linux.
Os contêineres do Docker podem ser hospedados em sua própria infraestrutura do
Linux ou do Windows ou em um serviço de nuvem, como Serviço de Kubernetes do
Azure . O Serviço de Kubernetes do Azure pode gerenciar, orquestrar e dimensionar
aplicativos baseados em contêiner na nuvem.
Alto desempenho e sistemas escalonáveis
Quando o seu sistema precisa do melhor desempenho e escalabilidade possíveis, o .NET
e o ASP.NET Core são as melhores opções. O runtime do servidor de alto desempenho
para Windows Server e Linux torna ASP.NET Core uma estrutura Web de melhor
desempenho em benchmarks do TechEmpower .
O desempenho e a escalabilidade são especialmente relevantes para arquiteturas de
microsserviços, em que centenas de microsserviços podem estar em execução. Com o
ASP.NET Core, os sistemas são executados com um número bem menor de
servidores/VMs (Máquinas Virtuais). Os servidores/VMs reduzidos economizam custos
em infraestrutura e hospedagem.
Versões do .NET lado a lado por nível de aplicativo
Para instalar aplicativos com dependências em diferentes versões do .NET, é
recomendável o .NET. Essa implementação dá suporte à instalação lado a lado de
diferentes versões do runtime do .NET no mesmo computador. A instalação lado a lado
permite vários serviços no mesmo servidor, cada um em sua própria versão do .NET. Ela
também reduz os riscos e gera economia financeira nas operações de TI e atualizações
de aplicativo.
A instalação lado a lado não é possível com o .NET Framework. Ele é um componente
do Windows, e apenas uma versão pode existir em um computador por vez. Cada
versão do .NET Framework substitui a versão anterior. Se você instalar um novo
aplicativo direcionado a uma versão posterior do .NET Framework, poderá interromper
os aplicativos existentes executados no computador porque a versão anterior foi
substituída.
Quando escolher o .NET Framework
O .NET oferece benefícios significativos para novos aplicativos e padrões de aplicativo.
No entanto, o .NET Framework continua sendo a escolha natural para muitos cenários
existentes e, portanto, não é substituído pelo .NET em todos os aplicativos para
servidores.
Aplicativos .NET Framework atuais
Na maioria dos casos, não é necessário migrar aplicativos existentes para o .NET. Em vez
disso, recomendamos usar o .NET à medida que você estende um aplicativo existente,
como escrever um novo serviço Web em ASP.NET Core.
Bibliotecas de terceiros ou pacotes NuGet não disponíveis
para o .NET
O .NET Standard permite o compartilhamento de código entre todas as implementações
do .NET, incluindo o .NET Core/5+. Com o .NET Standard 2.0, um modo de
compatibilidade permite que os projetos do .NET Standard e do .NET referenciem
bibliotecas do .NET Framework. Para obter mais informações, consulte Suporte para
bibliotecas do .NET Framework.
Portanto, apenas nos casos em que as bibliotecas ou pacotes NuGet usarem tecnologias
que não estão disponíveis no .NET Standard ou .NET você precisará usar o .NET
Framework.
Tecnologias do .NET Framework não disponíveis para o
.NET
Algumas tecnologias do .NET Framework não estão disponíveis no .NET. A lista a seguir
mostra as tecnologias mais comuns não encontradas no .NET:
ASP.NET Web Forms aplicativos: ASP.NET Web Forms só estão disponíveis no .NET
Framework. ASP.NET Core não pode ser usado para ASP.NET Web Forms.
Páginas da Web do ASP.NET aplicativos: Páginas da Web do ASP.NET não estão
incluídos no ASP.NET Core.
Serviços relacionados ao fluxo de trabalho: Windows Workflow Foundation (WF),
Workflow Services (WCF + WF em um único serviço) e WCF Data Services
(anteriormente conhecido como "ADO.NET Data Services") só estão disponíveis em
.NET Framework.
Suporte à linguagem: No momento, há suporte para Visual Basic e F# no .NET,
mas não para todos os tipos de projeto. Para obter uma lista de modelos de
projeto com suporte, consulte Opções de modelo para o dotnet new.
Para obter mais informações, confira Tecnologias do .NET Framework não disponíveis no
.NET.
A plataforma não dá suporte ao .NET
Algumas plataformas de terceiros ou da Microsoft não oferecem suporte ao .NET.
Alguns serviços do Azure fornecem um SDK que ainda não está disponível para ser
consumido no .NET. Nesses casos, você pode usar a API REST equivalente em vez do
SDK do cliente.
Confira também
Escolher entre o ASP.NET e o ASP.NET Core
ASP.NET Core direcionado para o .NET Framework
Estruturas de destino
Introdução ao .NET
Portabilidade do .NET Framework para .NET 5
Introdução ao .NET e ao Docker
Implementações do .NET
Microsserviços do .NET. Arquitetura de aplicativos .NET em contêineres
Tutorial: introdução ao ASP.NET Core
Artigo • 28/11/2022 • 2 minutos para o fim da leitura
Este tutorial mostra como criar e executar um aplicativo Web ASP.NET Core usando a
CLI do .NET Core.
Você aprenderá a:
" Criar um projeto de aplicativo Web.
" Confiar no certificado de desenvolvimento.
" Execute o aplicativo.
" Editar uma página do Razor.
No final, você terá um aplicativo Web de trabalho em execução no seu computador
local.
Pré-requisitos
SDK do .NET 6.0
Criar um projeto do aplicativo Web
Abra um shell de comando e insira o seguinte comando:
CLI do .NET
dotnet new webapp -o aspnetcoreapp
O comando anterior:
Cria um novo aplicativo Web.
O parâmetro -o aspnetcoreapp cria um diretório chamado aspnetcoreapp com os
arquivos de origem do aplicativo.
Confiar no certificado de desenvolvimento
Confie no certificado de desenvolvimento HTTPS:
Windows
CLI do .NET
dotnet dev-certs https --trust
O comando anterior exibe a caixa de diálogo a seguir:
Selecione Sim se você concordar com confiar no certificado de desenvolvimento.
Para obter mais informações, confira Confiar no certificado de desenvolvimento HTTPS
do ASP.NET Core
Executar o aplicativo
Execute os seguintes comandos:
CLI do .NET
cd aspnetcoreapp
dotnet watch run
Depois que o shell de comando indicar que o aplicativo foi iniciado, navegue até
https://localhost:{port} , onde {port} está a porta aleatória usada.
Editar uma página do Razor
Abra Pages/Index.cshtml e modifique e salve a página com a seguinte marcação
realçada:
CSHTML
@page
@model IndexModel
@{
ViewData["Title"] = "Home page";
}
<div class="text-center">
<h1 class="display-4">Welcome</h1>
<p>Hello, world! The time on the server is @DateTime.Now</p>
</div>
Navegue até https://localhost:{port} , atualize a página e verifique se as alterações
são exibidas.
Próximas etapas
Neste tutorial, você aprendeu a:
" Criar um projeto de aplicativo Web.
" Confiar no certificado de desenvolvimento.
" Execute o projeto.
" Faça uma alteração.
Para saber mais sobre o ASP.NET Core, confira o seguinte:
Visão geral do ASP.NET Core
Novidades no ASP.NET Core 7.0
Artigo • 14/12/2022 • 29 minutos para o fim da leitura
Este artigo destaca as alterações mais significativas no ASP.NET Core 7.0 com links para
a documentação relevante.
Middleware de limitação de taxa no ASP.NET
Core
O Microsoft.AspNetCore.RateLimiting middleware fornece middleware de limitação de
taxa. Os aplicativos configuram políticas de limitação de taxa e anexam as políticas aos
pontos de extremidade. Para obter mais informações, consulte Middleware de limitação
de taxa em ASP.NET Core.
A autenticação usa um único esquema como
DefaultScheme
Como parte do trabalho para simplificar a autenticação, quando há apenas um único
esquema de autenticação registrado, ele é usado automaticamente como e
DefaultScheme não precisa ser especificado. Para obter mais informações, consulte
DefaultScheme.
MVC e Razor páginas
Suporte para modelos anuláveis em exibições e Razor
páginas do MVC
Há suporte para modelos de exibição ou página anuláveis para melhorar a experiência
ao usar a verificação de estado nulo com aplicativos ASP.NET Core:
C#
@model Product?
Associar com IParsable<T>.TryParse em controladores de
API e MVC
A IParsable<TSelf>.TryParse API dá suporte a valores de parâmetro de ação do
controlador de associação. Para obter mais informações, consulte Associar com
IParsable<T>.TryParse.
Personalizar o valor de cookie consentimento
Em ASP.NET Core versões anteriores a 7, a cookie validação de consentimento usa o
valor yes para indicar o cookie consentimento. Agora você pode especificar o valor que
representa o consentimento. Por exemplo, você pode usar true em vez de yes :
C#
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages();
builder.Services.Configure<CookiePolicyOptions>(options =>
{
options.CheckConsentNeeded = context => true;
options.MinimumSameSitePolicy = SameSiteMode.None;
options.ConsentCookieValue = "true";
});
var app = builder.Build();
Para obter mais informações, consulte Personalizar o valor de cookie consentimento.
Controladores de API
Associação de parâmetros com DI em controladores de
API
A associação de parâmetros para ações do controlador de API associa parâmetros por
meio de injeção de dependência quando o tipo é configurado como um serviço. Isso
significa que não é mais necessário aplicar explicitamente o [FromServices] atributo a
um parâmetro. No código a seguir, ambas as ações retornam a hora:
C#
[Route("[controller]")]
[ApiController]
public class MyController : ControllerBase
{
public ActionResult GetWithAttribute([FromServices] IDateTime dateTime)
=> Ok(dateTime.Now);
[Route("noAttribute")]
public ActionResult Get(IDateTime dateTime) => Ok(dateTime.Now);
}
Em casos raros, a DI automática pode interromper aplicativos que têm um tipo na DI
que também é aceito em um método de ação de controladores de API. Não é comum
ter um tipo na DI e como argumento em uma ação do controlador da API. Para
desabilitar a associação automática de parâmetros, defina
DisableImplicitFromServicesParameters
C#
using Microsoft.AspNetCore.Mvc;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers();
builder.Services.AddSingleton<IDateTime, SystemDateTime>();
builder.Services.Configure<ApiBehaviorOptions>(options =>
{
options.DisableImplicitFromServicesParameters = true;
});
var app = builder.Build();
app.MapControllers();
app.Run();
No ASP.NET Core 7.0, os tipos na DI são verificados na inicialização do aplicativo com
IServiceProviderIsService para determinar se um argumento em uma ação do
controlador de API vem da DI ou de outras fontes.
O novo mecanismo para inferir a origem da associação dos parâmetros de ação do
Controlador de API usa as seguintes regras:
1. Um BindingInfo.BindingSource especificado anteriormente nunca é substituído.
2. Um parâmetro de tipo complexo, registrado no contêiner DI, é atribuído
BindingSource.Services.
3. Um parâmetro de tipo complexo, não é registrado no contêiner DI, é atribuído
BindingSource.Body.
4. Um parâmetro com um nome que aparece como um valor de rota em qualquer
modelo de rota é atribuído BindingSource.Path.
5. Todos os outros parâmetros são BindingSource.Query.
JSNomes de propriedade ON em erros de validação
Por padrão, quando ocorre um erro de validação, a validação do modelo produz um
ModelStateDictionary com o nome da propriedade como a chave de erro. Alguns
aplicativos, como aplicativos de página única, se beneficiam do uso JSde nomes de
propriedade ON para erros de validação gerados a partir de APIs Web. O código a
seguir configura a validação para usar o SystemTextJsonValidationMetadataProvider
para usar JSnomes de propriedade ON:
C#
using Microsoft.AspNetCore.Mvc.ModelBinding.Metadata;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers(options =>
{
options.ModelMetadataDetailsProviders.Add(new
SystemTextJsonValidationMetadataProvider());
});
var app = builder.Build();
app.UseHttpsRedirection();
app.UseAuthorization();
app.MapControllers();
app.Run();
O código a seguir configura a validação para usar o para usar JSo
NewtonsoftJsonValidationMetadataProvider nome da propriedade ON ao usar
Json.NET :
C#
using Microsoft.AspNetCore.Mvc.NewtonsoftJson;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers(options =>
{
options.ModelMetadataDetailsProviders.Add(new
NewtonsoftJsonValidationMetadataProvider());
}).AddNewtonsoftJson();
var app = builder.Build();
app.UseHttpsRedirection();
app.UseAuthorization();
app.MapControllers();
app.Run();
Para obter mais informações, consulte Usar JSnomes de propriedade ON em erros de
validação
APIs mínimas
Filtros em aplicativos de API mínima
Filtros mínimos de API permitem que os desenvolvedores implementem a lógica de
negócios que dá suporte a:
Executando o código antes e depois do manipulador de rotas.
Inspecionar e modificar parâmetros fornecidos durante uma invocação do
manipulador de rotas.
Interceptando o comportamento de resposta de um manipulador de rotas.
Os filtros podem ser úteis nos seguintes cenários:
Validando os parâmetros de solicitação e o corpo que são enviados para um ponto
de extremidade.
Registrar em log informações sobre a solicitação e a resposta.
Validar se uma solicitação tem como destino uma versão de API com suporte.
Para obter mais informações, consulte Filtros em aplicativos de API mínimos
Associar matrizes e valores de cadeia de caracteres de
cabeçalhos e cadeias de caracteres de consulta
No ASP.NET 7, há suporte para associar cadeias de caracteres de consulta a uma matriz
de tipos primitivos, matrizes de cadeia de caracteres e StringValues :
C#
// Bind query string values to a primitive type array.
// GET /tags?q=1&q=2&q=3
app.MapGet("/tags", (int[] q) =>
$"tag1: {q[0]} , tag2: {q[1]}, tag3: {q[2]}");
// Bind to a string array.
// GET /tags2?names=john&names=jack&names=jane
app.MapGet("/tags2", (string[] names) =>
$"tag1: {names[0]} , tag2: {names[1]}, tag3: {names[2]}");
// Bind to StringValues.
// GET /tags3?names=john&names=jack&names=jane
app.MapGet("/tags3", (StringValues names) =>
$"tag1: {names[0]} , tag2: {names[1]}, tag3: {names[2]}");
Há suporte para associar cadeias de caracteres de consulta ou valores de cabeçalho a
uma matriz de tipos complexos quando o tipo é TryParse implementado. Para obter
mais informações, consulte Associar matrizes e valores de cadeia de caracteres de
cabeçalhos e cadeias de caracteres de consulta.
Para obter mais informações, consulte Adicionar resumo ou descrição do ponto de
extremidade.
Associar o corpo da solicitação como um Stream ou
PipeReader
O corpo da solicitação pode ser associado como um Stream ou PipeReader para dar
suporte eficiente a cenários em que o usuário precisa processar dados e:
Armazene os dados no armazenamento de blobs ou enfileira os dados para um
provedor de filas.
Processe os dados armazenados com um processo de trabalho ou uma função de
nuvem.
Por exemplo, os dados podem ser enfileirados no Armazenamento de Filas do Azure ou
armazenados no Armazenamento de Blobs do Azure.
Para obter mais informações, consulte Associar o corpo da solicitação como um Stream
ou PipeReader
Novas sobrecargas de Results.Stream
Introduzimos novas Results.Stream sobrecargas para acomodar cenários que precisam
de acesso ao fluxo de resposta HTTP subjacente sem buffer. Essas sobrecargas também
melhoram os casos em que uma API transmite dados para o fluxo de resposta HTTP,
como de Armazenamento de Blobs do Azure. O exemplo a seguir usa ImageSharp
para retornar um tamanho reduzido da imagem especificada:
C#
using SixLabors.ImageSharp;
using SixLabors.ImageSharp.Formats.Jpeg;
using SixLabors.ImageSharp.Processing;
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.MapGet("/process-image/{strImage}", (string strImage, HttpContext http,
CancellationToken token) =>
{
http.Response.Headers.CacheControl = $"public,max-age=
{TimeSpan.FromHours(24).TotalSeconds}";
return Results.Stream(stream => ResizeImageAsync(strImage, stream,
token), "image/jpeg");
});
async Task ResizeImageAsync(string strImage, Stream stream,
CancellationToken token)
{
var strPath = $"wwwroot/img/{strImage}";
using var image = await Image.LoadAsync(strPath, token);
int width = image.Width / 2;
int height = image.Height / 2;
image.Mutate(x =>x.Resize(width, height));
await image.SaveAsync(stream, JpegFormat.Instance, cancellationToken:
token);
}
Para obter mais informações, consulte Exemplos de fluxo
Resultados tipado para APIs mínimas
No .NET 6, a IResult interface foi introduzida para representar valores retornados de
APIs mínimas que não utilizam o suporte implícito para JSON serializando o objeto
retornado para a resposta HTTP. A classe Resultados estáticos é usada para criar objetos
variados IResult que representam diferentes tipos de respostas. Por exemplo, definir o
código de status de resposta ou redirecionar para outra URL. No IResult entanto, os
tipos de estrutura de implementação retornados desses métodos eram internos,
dificultando a verificação do tipo específico IResult que está sendo retornado de
métodos em um teste de unidade.
No .NET 7, os tipos que implementam IResult são públicos, permitindo declarações de
tipo ao testar. Por exemplo:
C#
[TestClass()]
public class WeatherApiTests
{
[TestMethod()]
public void MapWeatherApiTest()
{
var result = WeatherApi.GetAllWeathers();
Assert.IsInstanceOfType(result, typeof(Ok<WeatherForecast[]>));
}
}
Melhor capacidade de teste de unidade para
manipuladores de rota mínimos
IResult Os tipos de implementação agora estão disponíveis publicamente no
Microsoft.AspNetCore.Http.HttpResults namespace . Os IResult tipos de
implementação podem ser usados para testar a unidade de manipuladores de rotas
mínimas ao usar métodos nomeados em vez de lambdas.
O código a seguir usa a Ok<TValue> classe :
C#
[Fact]
public async Task GetTodoReturnsTodoFromDatabase()
{
// Arrange
await using var context = new MockDb().CreateDbContext();
context.Todos.Add(new Todo
{
Id = 1,
Title = "Test title",
Description = "Test description",
IsDone = false
});
await context.SaveChangesAsync();
// Act
var okResult = (Ok<Todo>)await TodoEndpointsV1.GetTodo(1, context);
//Assert
Assert.Equal(200, okResult.StatusCode);
var foundTodo = Assert.IsAssignableFrom<Todo>(okResult.Value);
Assert.Equal(1, foundTodo.Id);
}
Para obter mais informações, consulte IResult tipos de implementação.
Novas interfaces HttpResult
As interfaces a seguir no Microsoft.AspNetCore.Http namespace fornecem uma maneira
de detectar o IResult tipo em runtime, que é um padrão comum em implementações
de filtro:
IContentTypeHttpResult
IFileHttpResult
INestedHttpResult
IStatusCodeHttpResult
IValueHttpResult
IValueHttpResult<TValue>
Para obter mais informações, consulte Interfaces IHttpResult.
Melhorias de OpenAPI para APIs mínimas
Pacote NuGet Microsoft.AspNetCore.OpenApi
O Microsoft.AspNetCore.OpenApi pacote permite interações com especificações de
OpenAPI para pontos de extremidade. O pacote atua como um link entre os modelos
OpenAPI definidos no Microsoft.AspNetCore.OpenApi pacote e os pontos de
extremidade definidos em APIs mínimas. O pacote fornece uma API que examina
parâmetros, respostas e metadados de um ponto de extremidade para construir um tipo
de anotação OpenAPI usado para descrever um ponto de extremidade.
C#
app.MapPost("/todoitems/{id}", async (int id, Todo todo, TodoDb db) =>
{
todo.Id = id;
db.Todos.Add(todo);
await db.SaveChangesAsync();
return Results.Created($"/todoitems/{todo.Id}", todo);
})
.WithOpenApi();
Chamar WithOpenApi com parâmetros
O WithOpenApi método aceita uma função que pode ser usada para modificar a
anotação OpenAPI. Por exemplo, no código a seguir, uma descrição é adicionada ao
primeiro parâmetro do ponto de extremidade:
C#
app.MapPost("/todo2/{id}", async (int id, Todo todo, TodoDb db) =>
{
todo.Id = id;
db.Todos.Add(todo);
await db.SaveChangesAsync();
return Results.Created($"/todoitems/{todo.Id}", todo);
})
.WithOpenApi(generatedOperation =>
{
var parameter = generatedOperation.Parameters[0];
parameter.Description = "The ID associated with the created Todo";
return generatedOperation;
});
Fornecer resumos e descrições de ponto de extremidade
ApIs mínimas agora dão suporte à anotação de operações com descrições e resumos
para a geração de especificações do OpenAPI. Você pode chamar métodos
WithDescription de extensão e WithSummary ou usar atributos [EndpointDescription] e
[EndpointSummary]).
Para obter mais informações, consulte OpenAPI em aplicativos de API mínimos
Uploads de arquivo usando IFormFile e
IFormFileCollection
ApIs mínimas agora dão suporte ao upload de arquivo com IFormFile e
IFormFileCollection . O código a seguir usa IFormFile e IFormFileCollection para
carregar o arquivo:
C#
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.MapGet("/", () => "Hello World!");
app.MapPost("/upload", async (IFormFile file) =>
{
var tempFile = Path.GetTempFileName();
app.Logger.LogInformation(tempFile);
using var stream = File.OpenWrite(tempFile);
await file.CopyToAsync(stream);
});
app.MapPost("/upload_many", async (IFormFileCollection myFiles) =>
{
foreach (var file in myFiles)
{
var tempFile = Path.GetTempFileName();
app.Logger.LogInformation(tempFile);
using var stream = File.OpenWrite(tempFile);
await file.CopyToAsync(stream);
}
});
app.Run();
Há suporte para solicitações de upload de arquivo autenticadas usando um cabeçalho
de autorização , um certificado de cliente ou um cookie cabeçalho.
Não há suporte interno para antiforgeria. No entanto, ele pode ser implementado
usando o IAntiforgery serviço .
[AsParameters] o atributo habilita a associação de
parâmetros para listas de argumentos
O [AsParameters] atributo habilita a associação de parâmetros para listas de
argumentos. Para obter mais informações, consulte Associação de parâmetros para
listas de argumentos com [AsParameters].
APIs mínimas e controladores de API
Novo serviço de detalhes do problema
O serviço de detalhes do problema implementa a IProblemDetailsService interface , que
dá suporte à criação de Detalhes do Problema para APIs HTTP .
Para obter mais informações, consulte Serviço de detalhes do problema.
Grupos de rotas
O MapGroup método de extensão ajuda a organizar grupos de pontos de extremidade
com um prefixo comum. Ele reduz o código repetitivo e permite personalizar grupos
inteiros de pontos de extremidade com uma única chamada a métodos como
RequireAuthorization e WithMetadata que adicionam metadados de ponto de
extremidade.
Por exemplo, o código a seguir cria dois grupos semelhantes de pontos de extremidade:
C#
app.MapGroup("/public/todos")
.MapTodosApi()
.WithTags("Public");
app.MapGroup("/private/todos")
.MapTodosApi()
.WithTags("Private")
.AddEndpointFilterFactory(QueryPrivateTodos)
.RequireAuthorization();
EndpointFilterDelegate QueryPrivateTodos(EndpointFilterFactoryContext
factoryContext, EndpointFilterDelegate next)
{
var dbContextIndex = -1;
foreach (var argument in factoryContext.MethodInfo.GetParameters())
{
if (argument.ParameterType == typeof(TodoDb))
{
dbContextIndex = argument.Position;
break;
}
}
// Skip filter if the method doesn't have a TodoDb parameter.
if (dbContextIndex < 0)
{
return next;
}
return async invocationContext =>
{
var dbContext = invocationContext.GetArgument<TodoDb>
(dbContextIndex);
dbContext.IsPrivate = true;
try
{
return await next(invocationContext);
}
finally
{
// This should only be relevant if you're pooling or otherwise
reusing the DbContext instance.
dbContext.IsPrivate = false;
}
};
}
C#
public static RouteGroupBuilder MapTodosApi(this RouteGroupBuilder group)
{
group.MapGet("/", GetAllTodos);
group.MapGet("/{id}", GetTodo);
group.MapPost("/", CreateTodo);
group.MapPut("/{id}", UpdateTodo);
group.MapDelete("/{id}", DeleteTodo);
return group;
}
Nesse cenário, você pode usar um endereço relativo para o Location cabeçalho no 201
Created resultado:
C#
public static async Task<Created<Todo>> CreateTodo(Todo todo, TodoDb
database)
{
await database.AddAsync(todo);
await database.SaveChangesAsync();
return TypedResults.Created($"{todo.Id}", todo);
}
O primeiro grupo de pontos de extremidade corresponderá apenas às solicitações
prefixadas com /public/todos e estarão acessíveis sem nenhuma autenticação. O
segundo grupo de pontos de extremidade corresponderá apenas às solicitações
prefixadas com /private/todos e exigirá autenticação.
A QueryPrivateTodos fábrica de filtros de ponto de extremidade é uma função local que
modifica os parâmetros do manipulador de TodoDb rotas para permitir o acesso e o
armazenamento de dados todo privados.
Os grupos de rotas também dão suporte a grupos aninhados e padrões de prefixo
complexos com parâmetros de rota e restrições. No exemplo a seguir, o manipulador de
rotas mapeado para o user grupo pode capturar os {org} parâmetros de rota e
{group} definidos nos prefixos do grupo externo.
O prefixo também pode estar vazio. Isso pode ser útil para adicionar metadados ou
filtros de ponto de extremidade a um grupo de pontos de extremidade sem alterar o
padrão de rota.
C#
var all = app.MapGroup("").WithOpenApi();
var org = all.MapGroup("{org}");
var user = org.MapGroup("{user}");
user.MapGet("", (string org, string user) => $"{org}/{user}");
Adicionar filtros ou metadados a um grupo se comporta da mesma maneira que
adicioná-los individualmente a cada ponto de extremidade antes de adicionar filtros ou
metadados extras que possam ter sido adicionados a um grupo interno ou ponto de
extremidade específico.
C#
var outer = app.MapGroup("/outer");
var inner = outer.MapGroup("/inner");
inner.AddEndpointFilter((context, next) =>
{
app.Logger.LogInformation("/inner group filter");
return next(context);
});
outer.AddEndpointFilter((context, next) =>
{
app.Logger.LogInformation("/outer group filter");
return next(context);
});
inner.MapGet("/", () => "Hi!").AddEndpointFilter((context, next) =>
{
app.Logger.LogInformation("MapGet filter");
return next(context);
});
No exemplo acima, o filtro externo registrará a solicitação de entrada antes do filtro
interno, mesmo que tenha sido adicionado em segundo lugar. Como os filtros foram
aplicados a grupos diferentes, a ordem em que foram adicionados em relação uns aos
outros não importa. Os filtros de pedido são adicionados importam se aplicados ao
mesmo grupo ou ponto de extremidade específico.
Uma solicitação para /outer/inner/ registrará o seguinte:
CLI do .NET
/outer group filter
/inner group filter
MapGet filter
gRPC
JSTranscodificação ON
A transcodificação gRPC JSON é uma extensão para ASP.NET Core que cria RESTAPIs on
ful JSpara serviços gRPC. A transcodificação gRPC JSON permite:
Aplicativos para chamar serviços gRPC com conceitos HTTP conhecidos.
ASP.NET Core aplicativos gRPC para dar suporte a APIs gRPC e RESTFUL JSON sem
replicar a funcionalidade.
Suporte experimental para gerar OpenAPI de APIs ful transcodificadas
RESTintegrando-se ao Swashbuckle.
Para obter mais informações, consulte transcodificação gRPC JSON em aplicativos gRPC
ASP.NET Core e Usar OpenAPI com transcodificação gRPC JSON ASP.NET Core
aplicativos.
Verificações de integridade do gRPC no ASP.NET Core
O protocolo de verificação de integridade gRPC é um padrão para relatar a
integridade de aplicativos de servidor gRPC. Um aplicativo expõe verificações de
integridade como um serviço gRPC. Normalmente, eles são usados com um serviço de
monitoramento externo para verificar o status de um aplicativo.
O gRPC ASP.NET Core adicionou suporte interno para verificações de integridade do
gRPC com o Grpc.AspNetCore.HealthChecks pacote. Os resultados das verificações de
integridade do .NET são relatados aos chamadores.
Para obter mais informações, consulte verificações de integridade do gRPC no ASP.NET
Core.
Suporte aprimorado a credenciais de chamada
As credenciais de chamada são a maneira recomendada de configurar um cliente gRPC
para enviar um token de autenticação para o servidor. Os clientes gRPC dão suporte a
dois novos recursos para facilitar o uso de credenciais de chamada:
Suporte para credenciais de chamada com conexões de texto sem formatação.
Anteriormente, uma chamada gRPC só enviava credenciais de chamada se a
conexão fosse protegida com TLS. Uma nova configuração em
GrpcChannelOptions , chamada UnsafeUseInsecureChannelCallCredentials , permite
que esse comportamento seja personalizado. Há implicações de segurança para
não proteger uma conexão com o TLS.
Um novo método chamado AddCallCredentials está disponível com a fábrica de
clientes gRPC. AddCallCredentials é uma maneira rápida de configurar credenciais
de chamada para um cliente gRPC e integra-se bem à DI (injeção de dependência).
O código a seguir configura a fábrica de clientes gRPC para enviar Authorization
metadados:
C#
builder.Services
.AddGrpcClient<Greeter.GreeterClient>(o =>
{
o.Address = new Uri("https://localhost:5001");
})
.AddCallCredentials((context, metadata) =>
{
if (!string.IsNullOrEmpty(_token))
{
metadata.Add("Authorization", $"Bearer {_token}");
}
return Task.CompletedTask;
});
Para obter mais informações, consulte Configurar um token de portador com a fábrica
de clientes gRPC.
SignalR
Resultados do cliente
O servidor agora dá suporte à solicitação de um resultado de um cliente. Isso exige que
o servidor use ISingleClientProxy.InvokeAsync e que o cliente retorne um resultado de
seu .On manipulador. Hubs fortemente tipados também podem retornar valores de
métodos de interface.
Para obter mais informações, consulte Resultados do cliente
Injeção de dependência para SignalR métodos de hub
SignalR Os métodos hub agora dão suporte à injeção de serviços por meio de DI
(injeção de dependência).
Os construtores de hub podem aceitar serviços de DI como parâmetros, que podem ser
armazenados em propriedades na classe para uso em um método de hub. Para obter
mais informações, consulte Injetar serviços em um hub
Blazor
Manipular eventos de alteração de local e estado de
navegação
No .NET 7, dá Blazor suporte à alteração de local de eventos e à manutenção do estado
de navegação. Isso permite que você avise os usuários sobre o trabalho não salvo ou
execute ações relacionadas quando o usuário executa uma navegação de página.
Para obter mais informações, consulte as seções a seguir do artigo Roteamento e
navegação :
Opções de navegação
Manipular/impedir alterações de local
Modelos de projeto vazios Blazor
Blazor tem dois novos modelos de projeto para começar a partir de uma lousa em
branco. Os novos Blazor Server modelos de projeto App Empty e Blazor WebAssembly
App Empty são exatamente como seus equivalentes não vazios, mas sem código de
exemplo. Esses modelos vazios incluem apenas uma home page básica e removemos o
Bootstrap para que você possa começar com uma estrutura CSS diferente.
Para obter mais informações, consulte os seguintes artigos:
Ferramentas para ASP.NET Core Blazor
Blazor estrutura do projeto ASP.NET Core
Elementos personalizados de Blazor
O Microsoft.AspNetCore.Components.CustomElements pacote permite criar
elementos DOM personalizados baseados em padrões usando Blazor.
Para obter mais informações, consulte ASP.NET Core Razor componentes.
Associar modificadores ( @bind:after , @bind:get ,
@bind:set )
) Importante
Os @bind:after // @bind:get @bind:set recursos estão recebendo mais atualizações
no momento. Para aproveitar as atualizações mais recentes, confirme se você
instalou o SDK mais recente.
Não há suporte para o uso de um parâmetro de retorno de chamada de evento
( [Parameter] public EventCallback<string> ValueChanged { get; set; } ). Em vez
disso, passe um Actionmétodo -returning ou Task-returning
para/ @bind:set @bind:after .
Para saber mais, consulte os recursos a seguir:
Blazor@bind:after não funcionando na versão rtm do .NET 7
(dotnet/aspnetcore #44957)
BindGetSetAfter701 aplicativo de exemplo ( javiercn/BindGetSetAfter701
repositório GitHub)
No .NET 7, você pode executar a lógica assíncrona após a conclusão de um evento de
associação usando o novo @bind:after modificador. No exemplo a seguir, o método
assíncrono PerformSearch é executado automaticamente após qualquer alteração no
texto de pesquisa ser detectada:
razor
<input @bind="searchText" @bind:after="PerformSearch" />
@code {
private string searchText;
private async Task PerformSearch()
{
...
}
}
No .NET 7, também é mais fácil configurar a associação para parâmetros de
componente. Os componentes podem dar suporte à associação de dados bidirecional
definindo um par de parâmetros:
@bind:get : especifica o valor a ser associado.
@bind:set : especifica um retorno de chamada para quando o valor é alterado.
Os @bind:get modificadores e @bind:set são sempre usados juntos.
Exemplos:
razor
@* Elements *@
<input type="text" @bind="text" @bind:after="() => { }" />
<input type="text" @bind:get="text" @bind:set="(value) => { }" />
<input type="text" @bind="text" @bind:after="AfterAsync" />
<input type="text" @bind:get="text" @bind:set="SetAsync" />
<input type="text" @bind="text" @bind:after="() => { }" />
<input type="text" @bind:get="text" @bind:set="(value) => { }" />
<input type="text" @bind="text" @bind:after="AfterAsync" />
<input type="text" @bind:get="text" @bind:set="SetAsync" />
@* Components *@
<InputText @bind-Value="text" @bind-Value:after="() => { }" />
<InputText @bind-Value:get="text" @bind-Value:set="(value) => { }" />
<InputText @bind-Value="text" @bind-Value:after="AfterAsync" />
<InputText @bind-Value:get="text" @bind-Value:set="SetAsync" />
<InputText @bind-Value="text" @bind-Value:after="() => { }" />
<InputText @bind-Value:get="text" @bind-Value:set="(value) => { }" />
<InputText @bind-Value="text" @bind-Value:after="AfterAsync" />
<InputText @bind-Value:get="text" @bind-Value:set="SetAsync" />
@code {
private string text = "";
private void After(){}
private void Set() {}
private Task AfterAsync() { return Task.CompletedTask; }
private Task SetAsync(string value) { return Task.CompletedTask; }
}
Para obter mais informações sobre o InputText componente, consulte ASP.NET Core
Blazor formulários e componentes de entrada.
melhorias Recarga Dinâmica
No .NET 7, Recarga Dinâmica suporte inclui o seguinte:
Os componentes redefinem seus parâmetros para seus valores padrão quando um
valor é removido.
Blazor WebAssembly:
Adicione novos tipos.
Adicionar classes aninhadas.
Adicione métodos estáticos e de instância a tipos existentes.
Adicione campos e métodos estáticos a tipos existentes.
Adicione lambdas estáticos aos métodos existentes.
Adicione lambdas que capturam this métodos existentes que já foram
capturados this anteriormente.
Solicitações de autenticação dinâmica com MSAL no
Blazor WebAssembly
Novo no .NET 7, Blazor WebAssembly dá suporte à criação de solicitações de
autenticação dinâmica em runtime com parâmetros personalizados para lidar com
cenários de autenticação avançada.
Para obter mais informações, consulte os seguintes artigos:
Proteger ASP.NET Core Blazor WebAssembly
Cenários de segurança adicionais do ASP.NET Core Blazor WebAssembly
Blazor WebAssembly aprimoramentos de depuração
Blazor WebAssembly A depuração tem as seguintes melhorias:
Suporte para a configuração Apenas Meu Código para mostrar ou ocultar
membros de tipo que não são do código do usuário.
Suporte para inspecionar matrizes multidimensionais.
Pilha de Chamadas agora mostra o nome correto para métodos assíncronos.
Avaliação de expressão aprimorada.
Tratamento correto da new palavra-chave em membros derivados.
Suporte para atributos relacionados ao depurador no System.Diagnostics .
System.Security.Cryptography suporte no WebAssembly
O .NET 6 deu suporte à família SHA de algoritmos de hash durante a execução no
WebAssembly. O .NET 7 permite mais algoritmos criptográficos aproveitando
SubtleCrypto , quando possível, e voltando para uma implementação do .NET quando
SubtleCrypto não pode ser usado. Os seguintes algoritmos têm suporte no
WebAssembly no .NET 7:
SHA1
SHA256
SHA384
SHA512
HMACSHA1
HMACSHA256
HMACSHA384
HMACSHA512
AES-CBC
PBKDF2
HKDF
Para obter mais informações, consulte Os desenvolvedores direcionados ao browser-
wasm podem usar APIs de criptografia da Web (dotnet/runtime #40074) .
Injetar serviços em atributos de validação personalizados
Agora você pode injetar serviços em atributos de validação personalizados. Blazor
configura o ValidationContext para que ele possa ser usado como um provedor de
serviços.
Para obter mais informações, consulte ASP.NET Core Blazor formulários e componentes
de entrada.
Input* componentes fora de um EditContext / EditForm
Os componentes de entrada internos agora têm suporte fora de um formulário na Razor
marcação de componente.
Para obter mais informações, consulte ASP.NET Core Blazor formulários e componentes
de entrada.
Alterações no modelo de projeto
Quando o .NET 6 foi lançado no ano passado, a marcação HTML da _Host página
( Pages/_Host.chstml ) foi dividida entre a _Host página e uma nova _Layout página
( Pages/_Layout.chstml ) no modelo de projeto do .NET 6 Blazor Server .
No .NET 7, a marcação HTML foi recombinada com a _Host página em modelos de
projeto.
Várias alterações adicionais foram feitas nos modelos de Blazor projeto. Não é viável
listar todas as alterações nos modelos na documentação. Para migrar um aplicativo para
o .NET 7 para adotar todas as alterações, consulte Migrar de ASP.NET Core 6.0 para 7.0.
Componente experimental QuickGrid
O novo QuickGrid componente fornece um componente de grade de dados
conveniente para os requisitos mais comuns e como uma linha de base de desempenho
e arquitetura de referência para qualquer pessoa que crie Blazor componentes de grade
de dados.
Para obter mais informações, consulte componentes ASP.NET CoreRazor.
Demonstração ao vivo: QuickGrid para Blazor aplicativo de exemplo
Aprimoramentos de virtualização
Aprimoramentos de virtualização no .NET 7:
O Virtualize componente dá suporte ao uso do documento em si como a raiz de
rolagem, como uma alternativa para ter algum outro elemento com overflow-y:
scroll aplicado.
Se o Virtualize componente for colocado dentro de um elemento que requer um
nome de marca filho específico, SpacerElement permitirá que você obtenha ou
defina o nome da marca do espaçador de virtualização.
Para obter mais informações, consulte as seguintes seções do artigo Virtualização :
Virtualização de nível raiz
Controlar o nome da marca de elemento do espaçador
MouseEventArgs Atualizações
MovementX e MovementY foram adicionados a MouseEventArgs .
Para obter mais informações, consulte ASP.NET Core Blazor manipulação de eventos.
Nova Blazor página de carregamento
O Blazor WebAssembly modelo de projeto tem uma nova interface do usuário de
carregamento que mostra o progresso do carregamento do aplicativo.
Para obter mais informações, consulte ASP.NET Core Blazor inicialização.
Diagnóstico aprimorado para autenticação no Blazor
WebAssembly
Para ajudar a diagnosticar problemas de autenticação em Blazor WebAssembly
aplicativos, o log detalhado está disponível.
Para obter mais informações, consulte ASP.NET Core Blazor registro em log.
Interoperabilidade do JavaScript no WebAssembly
A API de interoperabilidade do JavaScript [JSImport] / [JSExport] é um novo
mecanismo de baixo nível para usar o .NET em aplicativos baseados em Blazor
WebAssembly JavaScript e . Com essa nova funcionalidade de interoperabilidade do
JavaScript, você pode invocar o código .NET do JavaScript usando o runtime do
WebAssembly do .NET e chamar a funcionalidade JavaScript do .NET sem nenhuma
dependência no modelo de componente da interface do Blazor usuário.
Para mais informações:
Javascript JS Interoperabilidade de importação/JSexportação com ASP.NET Core
Blazor WebAssembly: pertence somente a Blazor WebAssembly aplicativos.
Executar o .NET do JavaScript: pertence somente a aplicativos JavaScript que não
dependem do modelo de componente da interface do Blazor usuário.
Registro condicional do provedor de estado de
autenticação
Antes do lançamento do .NET 7, AuthenticationStateProvider era registrado no
contêiner de serviço com AddScoped . Isso dificulta a depuração de aplicativos, pois
forçou uma ordem específica de registros de serviço ao fornecer uma implementação
personalizada. Devido a alterações na estrutura interna ao longo do tempo, não é mais
necessário se registrar AuthenticationStateProvider no AddScoped .
No código do desenvolvedor, faça a seguinte alteração no registro de serviço do
provedor de estado de autenticação:
diff
- builder.Services.AddScoped<AuthenticationStateProvider,
ExternalAuthStateProvider>();
+ builder.Services.TryAddScoped<AuthenticationStateProvider,
ExternalAuthStateProvider>();
No exemplo anterior, ExternalAuthStateProvider é a implementação do serviço do
desenvolvedor.
Melhorias nas ferramentas de build do WebAssembly do
.NET
Novos recursos na carga de trabalho do wasm-tools .NET 7 que ajudam a melhorar o
desempenho e lidar com exceções:
WebAssembly Single Instruction, Suporte a VÁRIOS Dados (SIMD) (somente com
AOT, sem suporte do Apple Safari)
Suporte ao tratamento de exceções do WebAssembly
Para obter mais informações, consulte Ferramentas para ASP.NET Core Blazor.
Blazor Hybrid
URLs externas
Foi adicionada uma opção que permite abrir páginas da Web externas no navegador.
Para obter mais informações, consulte roteamento e navegação ASP.NET CoreBlazor
Hybrid.
Segurança
Novas diretrizes estão disponíveis para Blazor Hybrid cenários de segurança. Para obter
mais informações, consulte os seguintes artigos:
Autenticação e autorização de Blazor Hybrid no ASP.NET Core
Considerações de segurança do ASP.NET Core Blazor Hybrid
Desempenho
Middleware de cache de saída
O cache de saída é um novo middleware que armazena respostas de um aplicativo Web
e as serve de um cache em vez de computá-las todas as vezes. O cache de saída difere
do cache de resposta das seguintes maneiras:
O comportamento de cache é configurável no servidor.
As entradas de cache podem ser invalidadas programaticamente.
O bloqueio de recursos reduz o risco de debandada de cache e rebanho
estrondoso .
A revalidação de cache significa que o servidor pode retornar um 304 Not
Modified código de status HTTP em vez de um corpo de resposta armazenado em
cache.
A mídia de armazenamento em cache é extensível.
Para obter mais informações, consulte Visão geral do middleware de cache e cache de
saída.
Melhorias de HTTP/3
Esta versão:
Torna o HTTP/3 totalmente compatível com ASP.NET Core, ele não é mais
experimental.
Melhora o Kestrelsuporte do para HTTP/3. As duas principais áreas de melhoria
são a paridade de recursos com HTTP/1.1 e HTTP/2 e desempenho.
Fornece suporte completo para UseHttps(ListenOptions, X509Certificate2) com
HTTP/3. Kestreloferece opções avançadas para configurar certificados de conexão,
como conectar-se à SNI (Indicação de Nome do Servidor).
Adiciona suporte para HTTP/3 em HTTP.sys e IIS.
O exemplo a seguir mostra como usar um retorno de chamada SNI para resolver opções
de TLS:
C#
using Microsoft.AspNetCore.Server.Kestrel.Core;
using Microsoft.AspNetCore.Server.Kestrel.Https;
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;
var builder = WebApplication.CreateBuilder(args);
builder.WebHost.ConfigureKestrel(options =>
{
options.ListenAnyIP(8080, listenOptions =>
{
listenOptions.Protocols = HttpProtocols.Http1AndHttp2AndHttp3;
listenOptions.UseHttps(new TlsHandshakeCallbackOptions
{
OnConnection = context =>
{
var options = new SslServerAuthenticationOptions
{
ServerCertificate =
MyResolveCertForHost(context.ClientHelloInfo.ServerName)
};
return new ValueTask<SslServerAuthenticationOptions>
(options);
},
});
});
});
Foi feito um trabalho significativo no .NET 7 para reduzir as alocações http/3. Você pode
ver algumas dessas melhorias nas seguintes PR do GitHub:
HTTP/3: evitar alocações de token de cancelamento por solicitação
HTTP/3: evitar alocações connectionAbortedException
HTTP/3: pooling valueTask
Melhorias de desempenho http/2
O .NET 7 apresenta uma arquitetura significativa de como Kestrel processa solicitações
HTTP/2. ASP.NET Core aplicativos com conexões HTTP/2 ocupadas terão uso reduzido
da CPU e maior taxa de transferência.
Anteriormente, a implementação de multiplexação HTTP/2 dependia de um bloqueio
que controlava qual solicitação pode gravar na conexão TCP subjacente. Uma fila
thread-safe substitui o bloqueio de gravação. Agora, em vez de lutar sobre qual
thread pode usar o bloqueio de gravação, as solicitações agora são enfileiradas e um
consumidor dedicado as processa. Os recursos de CPU desperdiçados anteriormente
estão disponíveis para o restante do aplicativo.
Um local em que essas melhorias podem ser observadas é no gRPC, uma estrutura RPC
popular que usa HTTP/2. Kestrel + Os parâmetros de comparação de gRPC mostram
uma melhoria dramática:
Foram feitas alterações no código de gravação de quadro HTTP/2 que melhora o
desempenho quando há vários fluxos tentando gravar dados em uma única conexão
HTTP/2. Agora, enviamos o trabalho do TLS para o pool de threads e liberamos mais
rapidamente um bloqueio de gravação que outros fluxos podem adquirir para gravar
seus dados. A redução dos tempos de espera pode gerar melhorias significativas de
desempenho nos casos em que há contenção para esse bloqueio de gravação. Um
parâmetro de comparação gRPC com 70 fluxos em uma única conexão (com TLS)
mostrou uma melhoria de aproximadamente 15% nas solicitações por segundo (RPS)
com essa alteração.
Suporte a WebSockets http/2
O .NET 7 apresenta o suporte a Websockets por HTTP/2 para Kestrel, o SignalR cliente
JavaScript e SignalR com Blazor WebAssembly.
O uso de WebSockets por HTTP/2 aproveita os novos recursos, como:
Compactação de cabeçalho.
Multiplexação, que reduz o tempo e os recursos necessários ao fazer várias
solicitações ao servidor.
Esses recursos com suporte estão disponíveis em Kestrel todas as plataformas
habilitadas para HTTP/2. A negociação de versão é automática em navegadores e
Kestrel, portanto, nenhuma nova APIs é necessária.
Para obter mais informações, consulte Suporte a WebSockets Http/2.
Kestrel melhorias de desempenho em computadores de
alto núcleo
Kestrel usa ConcurrentQueue<T> para muitas finalidades. Uma das finalidades é
agendar operações de E/S no Kestreltransporte de soquete padrão. Particionar o
ConcurrentQueue com base no soquete associado reduz a contenção e aumenta a taxa
de transferência em computadores com muitos núcleos de CPU.
A criação de perfil em computadores de núcleo alto no .NET 6 mostrou contenção
significativa em uma das Kestreloutras ConcurrentQueue instâncias do , a
PinnedMemoryPool que Kestrel usa para armazenar buffers de bytes em cache.
No .NET 7, Kestrelo pool de memória é particionado da mesma maneira que sua fila de
E/S, o que leva a uma contenção muito menor e maior taxa de transferência em
computadores de núcleo alto. Nas VMs ARM64 de 80 núcleos, estamos vendo uma
melhoria de mais de 500% nas RPS (respostas por segundo) no parâmetro de
comparação de texto sem formatação TechEmpower. Em VMs AMD de 48 Núcleos, o
aprimoramento é de quase 100% em nosso parâmetro de comparação HTTPS JSON.
ServerReady evento para medir o tempo de inicialização
Os aplicativos que usam o EventSource podem medir o tempo de inicialização para
entender e otimizar o desempenho da inicialização. O novo ServerReady evento em
representa o ponto em Microsoft.AspNetCore.Hosting que o servidor está pronto para
responder às solicitações.
Servidor
Novo evento ServerReady para medir o tempo de
inicialização
O ServerReady evento foi adicionado para medir o tempo de inicialização de
aplicativos ASP.NET Core.
IIS
Cópia de sombra no IIS
A cópia de assemblies de aplicativos de sombra para o ANCM (Módulo ASP.NET Core)
para IIS pode fornecer uma experiência melhor do usuário final do que interromper o
aplicativo implantando um arquivo offline do aplicativo.
Para obter mais informações, consulte Cópia de sombra no IIS.
Diversos
Kestrel aprimoramentos completos da cadeia de
certificados
HttpsConnectionAdapterOptions tem uma nova propriedade ServerCertificateChain do
tipo X509Certificate2Collection, o que facilita a validação de cadeias de certificados,
permitindo que uma cadeia completa, incluindo certificados intermediários, seja
especificada. Consulte dotnet/aspnetcore#21513 para obter mais detalhes.
dotnet watch
Saída aprimorada do console para dotnet watch
A saída do console do relógio dotnet foi aprimorada para se alinhar melhor ao registro
em log de ASP.NET Core e se destacar com 😮emojis😍.
Aqui está um exemplo de como a nova saída se parece:
Para obter mais informações, consulte esta solicitação de pull do GitHub .
Configurar o dotnet watch para sempre reiniciar para
edições rudes
Edições rudes são edições que não podem ser recarregadas quentes. Para configurar o
dotnet watch para sempre reiniciar sem um prompt para edições rudes, defina a variável
de DOTNET_WATCH_RESTART_ON_RUDE_EDIT ambiente como true .
Modo escuro da página de exceção do desenvolvedor
O suporte ao modo escuro foi adicionado à página de exceção do desenvolvedor,
graças a uma contribuição de Patrick Westerhoff . Para testar o modo escuro em um
navegador, na página ferramentas de desenvolvedor, defina o modo como escuro. Por
exemplo, no Firefox:
No Chrome:
Opção de modelo de projeto para usar o método
Program.Main em vez de instruções de nível superior
Os modelos do .NET 7 incluem uma opção para não usar instruções de nível superior e
gerar um namespace método e Main declarado em uma Program classe.
Usando a CLI do .NET, use a opção --use-program-main :
CLI do .NET
dotnet new web --use-program-main
Com o Visual Studio, marque a nova caixa de seleção Não usar instruções de nível
superior durante a criação do projeto:
Modelos de Angular e React atualizados
O modelo de projeto Angular foi atualizado para Angular 14. O modelo de projeto
React foi atualizado para React 18.2.
Gerenciar JSTokens Web ON em desenvolvimento com
dotnet user-jwts
A nova dotnet user-jwts ferramenta de linha de comando pode criar e gerenciar JWTs
(Tokens Web ON) locaisJS específicos do aplicativo. Para obter mais informações,
consulte Gerenciar JStokens Web ON em desenvolvimento com dotnet user-jwts.
Suporte para cabeçalhos de solicitação adicionais no
W3CLogger
Agora você pode especificar cabeçalhos de solicitação adicionais para registrar em log
ao usar o agente W3C chamando AdditionalRequestHeaders() em W3CLoggerOptions:
C#
services.AddW3CLogging(logging =>
{
logging.AdditionalRequestHeaders.Add("x-forwarded-for");
logging.AdditionalRequestHeaders.Add("x-client-ssl-protocol");
});
Para obter mais informações, consulte Opções do W3CLogger.
Solicitação de descompactação
O novo middleware de descompactação de solicitação:
Permite que os pontos de extremidade de API aceitem solicitações com conteúdo
compactado.
Usa o Content-Encoding cabeçalho HTTP para identificar e descompactar
automaticamente solicitações que contêm conteúdo compactado.
Elimina a necessidade de escrever código para lidar com solicitações compactadas.
Para obter mais informações, consulte Solicitar middleware de descompactação.
Novidades no ASP.NET Core 6.0
Artigo • 28/11/2022 • 31 minutos para o fim da leitura
Este artigo destaca as alterações mais significativas no ASP.NET Core 6.0 com links para
a documentação relevante.
ASP.NET Core MVC e Razor melhorias
APIs mínimas
APIs mínimas são arquitetas para criar APIs HTTP com dependências mínimas. Eles são
ideais para microsserviços e aplicativos que desejam incluir apenas os arquivos mínimos,
recursos e dependências em ASP.NET Core. Para obter mais informações, consulte:
Tutorial: Criar uma API Web mínima com ASP.NET Core
Diferenças entre APIs mínimas e APIs com controladores
Referência rápida de APIs mínimas
Exemplos de código migrados para o novo modelo de hospedagem mínima na
versão 6.0
SignalR
Marca de atividade de execução prolongada para SignalR
conexões
SignalR usa o novo Microsoft.AspNetCore.Http.Features.IHttpActivityFeature.Activity
para adicionar uma http.long_running marca à atividade de solicitação.
IHttpActivityFeature.Activity é usado por serviços do APM como o Application
Insights do Azure Monitor para filtrar SignalR solicitações da criação de alertas de
solicitação de execução prolongada.
Aprimoramentos no desempenho de SignalR
Aloque HubCallerClients uma vez por conexão em vez de cada chamada de
método de hub.
Evite a alocação de fechamento em SignalR DefaultHubDispatcher.Invoke . O estado
é passado para uma função estática local por meio de parâmetros para evitar uma
alocação de fechamento. Para obter mais informações, consulte esta solicitação de
pull do GitHub .
Aloque um único StreamItemMessage por fluxo em vez de por item de fluxo no
streaming de servidor para cliente. Para obter mais informações, consulte esta
solicitação de pull do GitHub .
Razor Compilador
Razor compilador atualizado para usar geradores de
origem
O Razor compilador agora é baseado em geradores de origem C#. Os geradores de
origem são executados durante a compilação e inspecionam o que está sendo
compilado para produzir arquivos adicionais compilados junto com o restante do
projeto. O uso de geradores de origem simplifica o Razor compilador e acelera
significativamente os tempos de compilação.
Razor O compilador não produz mais um assembly de
Exibições separado
O Razor compilador utilizou anteriormente um processo de compilação em duas etapas
que produziu um assembly views separado que continha as exibições e páginas geradas
( .cshtml arquivos) definidas no aplicativo. Os tipos gerados eram públicos e sob o
AspNetCore namespace .
O compilador atualizado Razor cria os tipos de exibições e páginas no assembly
principal do projeto. Esses tipos agora são gerados por padrão como lacrados internos
no AspNetCoreGeneratedDocument namespace . Essa alteração melhora o desempenho do
build, permite a implantação de arquivo único e permite que esses tipos participem de
Recarga Dinâmica.
Para obter mais informações sobre essa alteração, consulte o problema de comunicado
relacionado no GitHub.
melhorias de desempenho e API do ASP.NET
Core
Muitas alterações foram feitas para reduzir as alocações e melhorar o desempenho em
toda a pilha:
Aplicativo não alocador. Use o método de extensão. A nova sobrecarga de
app.Use requer passar o contexto para next o qual salva duas alocações internas
por solicitação necessárias ao usar a outra sobrecarga.
Redução de alocações de memória ao acessar HttpRequest.Cookies. Saiba mais
neste tópico do GitHub .
Use LoggerMessage.Define para as janelas somente HTTP.sys servidor Web. As
ILogger chamadas de métodos de extensão foram substituídas por chamadas para
LoggerMessage.Define .
Reduza a sobrecarga por conexão em SocketConnection em aproximadamente
30%. Para obter mais informações, consulte esta solicitação de pull do GitHub .
Reduza as alocações removendo delegados de log em tipos genéricos. Para obter
mais informações, consulte esta solicitação de pull do GitHub .
Acesso GET mais rápido (cerca de 50%) a recursos comumente usados, como
IHttpRequestFeature, IHttpResponseFeature, IHttpResponseBodyFeature,
IRouteValuesFeaturee IEndpointFeature. Para obter mais informações, consulte esta
solicitação de pull do GitHub .
Use cadeias de caracteres de instância única para nomes de cabeçalho conhecidos,
mesmo que não estejam no bloco de cabeçalho preservado. O uso de cadeia de
caracteres de instância única ajuda a evitar várias duplicatas da mesma cadeia de
caracteres em conexões de longa duração, por exemplo, em
Microsoft.AspNetCore.WebSockets. Saiba mais neste tópico do GitHub .
Reutilize HttpProtocol CancellationTokenSource em Kestrel. Use o novo método
CancellationTokenSource.TryReset em CancellationTokenSource para reutilizar
tokens se eles não tiverem sido cancelados. Para obter mais informações, consulte
este problema do GitHub e este vídeo .
Implemente e use um AdaptiveCapacityDictionary na
Microsoft.AspNetCore.HttpColeção de SolicitaçõesCookie para obter acesso
mais eficiente aos dicionários. Para obter mais informações, consulte esta
solicitação de pull do GitHub .
Volume de memória reduzido para conexões TLS ociosas
Para conexões TLS de longa execução em que os dados são enviados apenas
ocasionalmente para frente e para trás, reduzimos significativamente o volume de
memória de aplicativos ASP.NET Core no .NET 6. Isso deve ajudar a melhorar a
escalabilidade de cenários como servidores WebSocket. Isso foi possível devido a várias
melhorias em System.IO.Pipelines, SslStreame Kestrel. As seções a seguir detalham
algumas das melhorias que contribuíram para a redução do volume de memória:
Reduzir o tamanho de System.IO.Pipelines.Pipe
Para cada conexão estabelecida, dois pipes são alocados em Kestrel:
A camada de transporte para o aplicativo para a solicitação.
A camada de aplicativo para o transporte para a resposta.
Ao reduzir o tamanho de System.IO.Pipelines.Pipe 368 bytes para 264 bytes (cerca de
28,2% de redução), 208 bytes por conexão são salvos (104 bytes por Pipe).
Pool SocketSender
SocketSender os objetos (essa subclasse SocketAsyncEventArgs) têm cerca de 350 bytes
em runtime. Em vez de alocar um novo SocketSender objeto por conexão, eles podem
ser agrupados. SocketSender objetos podem ser agrupados porque os envios
geralmente são muito rápidos. O pooling reduz a sobrecarga por conexão. Em vez de
alocar 350 bytes por conexão, apenas pagar 350 bytes por IOQueue são alocados. A
alocação é feita por fila para evitar contenção. Nosso servidor WebSocket com 5.000
conexões ociosas passou da alocação de ~1,75 MB (350 bytes * 5000) para a alocação
de ~2,8 kb (350 bytes * 8) para SocketSender objetos.
Leituras de zero bytes com SslStream
As leituras sem buffer são uma técnica empregada em ASP.NET Core para evitar o
aluguel de memória do pool de memória se não houver dados disponíveis no soquete.
Antes dessa alteração, nosso servidor WebSocket com 5.000 conexões ociosas exigia
cerca de 200 MB sem TLS em comparação com cerca de 800 MB com TLS. Algumas
dessas alocações (4k por conexão) eram de Kestrel ter que manter um ArrayPool<T>
buffer enquanto aguardavam a conclusão das leituras SslStream . Considerando que
essas conexões estavam ociosas, nenhuma das leituras foi concluída e retornou seus
buffers para o ArrayPool , forçando o ArrayPool a alocar mais memória. As alocações
restantes estavam em SslStream si: buffer de 4k para handshakes TLS e buffer de 32k
para leituras normais. No .NET 6, quando o usuário executa uma leitura SslStream de
zero byte e não tem dados disponíveis, SslStream executa internamente uma leitura de
zero byte no fluxo encapsulado subjacente. Na melhor das hipóteses (conexão ociosa),
essas alterações resultam em uma economia de 40 Kb por conexão, ao mesmo tempo
em que permitem que o consumidor (Kestrel) seja notificado quando os dados
estiverem disponíveis sem manter os buffers não utilizados.
Leituras de bytes zero com PipeReader
Com leituras sem buffer com suporte em SslStream , uma opção foi adicionada para
executar leituras de bytes zero para StreamPipeReader , o tipo interno que adapta um
Stream em um PipeReader . No Kestrel, um StreamPipeReader é usado para adaptar o
subjacente SslStream a um PipeReader . Portanto, era necessário expor essas semânticas
de leitura de bytes zero no PipeReader .
Agora é possível criar um PipeReader que dá suporte a leituras de zero bytes em
qualquer subjacente Stream que dê suporte à semântica de leitura de bytes zero (por
exemplo, SslStream , NetworkStream, etc. usando a seguinte API:
CLI do .NET
var reader = PipeReader.Create(stream, new
StreamPipeReaderOptions(useZeroByteReads: true));
Remover lajes do SlabMemoryPool
Para reduzir a fragmentação do heap, Kestrel empregou uma técnica em que alocava
lajes de memória de 128 KB como parte de seu pool de memória. As lajes foram então
divididas ainda mais em blocos de 4 KB que foram usados internamente Kestrel . As
lajes tinham que ser maiores que 85 KB para forçar a alocação no heap de objetos
grandes para tentar impedir que o GC realocasse essa matriz. No entanto, com a
introdução da nova geração do GC, o POH ( Pinned Object Heap ), não faz mais
sentido alocar blocos na laje. Kestrel agora aloca diretamente blocos no POH, reduzindo
a complexidade envolvida no gerenciamento do pool de memória. Essa alteração deve
facilitar a execução de melhorias futuras, como facilitar a redução do pool de memória
usado pelo Kestrel.
IAsyncDisposable com suporte
IAsyncDisposable agora está disponível para controladores, Razor páginas e
componentes de exibição. Versões assíncronas foram adicionadas às interfaces
relevantes em fábricas e ativadores:
Os novos métodos oferecem uma implementação de interface padrão que delega
para a versão síncrona e chama Dispose.
As implementações substituem a implementação padrão e lidam com
implementações de IAsyncDisposable descarte.
As implementações favorecem IAsyncDisposable quando IDisposable ambas as
interfaces são implementadas.
Os extensores devem substituir os novos métodos incluídos para dar suporte
IAsyncDisposable a instâncias.
IAsyncDisposable é benéfico ao trabalhar com:
Enumeradores assíncronos, por exemplo, em fluxos assíncronos.
Recursos não gerenciados que têm operações de E/S com uso intensivo de
recursos a serem liberados.
Ao implementar essa interface, use o DisposeAsync método para liberar recursos.
Considere um controlador que cria e usa um Utf8JsonWriter. Utf8JsonWriter é um
IAsyncDisposable recurso:
C#
public class HomeController : Controller, IAsyncDisposable
{
private Utf8JsonWriter? _jsonWriter;
private readonly ILogger<HomeController> _logger;
public HomeController(ILogger<HomeController> logger)
{
_logger = logger;
_jsonWriter = new Utf8JsonWriter(new MemoryStream());
}
IAsyncDisposable deve implementar DisposeAsync :
C#
public async ValueTask DisposeAsync()
{
if (_jsonWriter is not null)
{
await _jsonWriter.DisposeAsync();
}
_jsonWriter = null;
}
Porta vcpkg para SignalR o cliente C++
O Vcpkg é um gerenciador de pacotes de linha de comando multiplataforma para
bibliotecas C e C++. Recentemente, adicionamos uma porta para vcpkg adicionar CMake
suporte nativo ao SignalR cliente C++. vcpkg também funciona com o MSBuild.
O SignalR cliente pode ser adicionado a um projeto do CMake com o seguinte snippet
quando o vcpkg é incluído no arquivo de cadeia de ferramentas:
CLI do .NET
find_package(microsoft-signalr CONFIG REQUIRED)
link_libraries(microsoft-signalr::microsoft-signalr)
Com o snippet anterior, o SignalR cliente C++ está pronto para usar #include e usado
em um projeto sem nenhuma configuração adicional. Para obter um exemplo completo
de um aplicativo C++ que utiliza o SignalR cliente C++, consulte o repositório
halter73/SignalR-Client-Cpp-Sample .
Blazor
Alterações no modelo de projeto
Várias alterações de modelo de projeto foram feitas para Blazor aplicativos, incluindo o
uso do Pages/_Layout.cshtml arquivo para conteúdo de layout que apareceu no
_Host.cshtml arquivo para aplicativos anteriores Blazor Server . Estude as alterações
criando um aplicativo de um modelo de projeto 6.0 ou acessando o ASP.NET Core fonte
de referência para os modelos de projeto:
Blazor Server
Blazor WebAssembly
Blazor WebAssembly suporte a dependências nativas
Blazor WebAssembly os aplicativos podem usar dependências nativas criadas para
serem executadas no WebAssembly. Para obter mais informações, consulte ASP.NET
Core Blazor WebAssembly dependências nativas.
Compilação e revinculação de runtime do WebAssembly
Ahead-of-Time (AOT)
Blazor WebAssembly dá suporte à compilação AOT (antecipada), na qual você pode
compilar seu código .NET diretamente no WebAssembly. A compilação AOT resulta em
melhorias de desempenho de runtime em detrimento de um tamanho de aplicativo
maior. A revinculação do runtime webAssembly do .NET corta o código de runtime não
utilizado e, portanto, melhora a velocidade de download. Para obter mais informações,
consulte Compilação AOT (antecipada) e Revinculação de runtime.
Manter o estado pré-gerado
Blazor dá suporte ao estado persistente em uma página pré-gerada para que o estado
não precise ser recriado quando o aplicativo for totalmente carregado. Para obter mais
informações, consulte Pré-gerar e integrar componentes ASP.NET CoreRazor.
Limites de erro
Os limites de erro fornecem uma abordagem conveniente para lidar com exceções no
nível da interface do usuário. Para obter mais informações, consulte Tratar erros em
aplicativos ASP.NET CoreBlazor.
Suporte a SVG
O <foreignObject> elemento de elemento tem suporte para exibir HTML arbitrário
em um SVG. Para obter mais informações, consulte componentes ASP.NET CoreRazor.
Blazor Server suporte para transferência de matriz de
bytes na JS Interoperabilidade
Blazor dá suporte à interoperabilidade de matriz JS de bytes otimizada que evita a
codificação e a decodificação de matrizes de bytes em Base64. Para saber mais, consulte
os recursos a seguir:
Chamar funções JavaScript de métodos .NET no ASP.NET Core Blazor
Chamar métodos .NET de funções JavaScript no ASP.NET Core Blazor
Aprimoramentos de cadeia de caracteres de consulta
O suporte para trabalhar com cadeias de caracteres de consulta foi aprimorado. Para
obter mais informações, consulte roteamento e navegação ASP.NET CoreBlazor.
Associação para selecionar vários
A associação dá suporte à seleção de várias opções com <input> elementos. Para saber
mais, consulte os recursos a seguir:
Blazor ASP.NET Core associação de dados
Blazor ASP.NET Core formulários e componentes de entrada
Controle de conteúdo de cabeçalho ( <head> )
Razor os componentes podem modificar o conteúdo do elemento HTML <head> de
uma página, incluindo a definição do título da página ( <title> elemento) e a
modificação de metadados ( <meta> elementos). Para obter mais informações, consulte
Controlar <head> conteúdo em aplicativos ASP.NET CoreBlazor.
Gerar componentes Angular e React
Gere componentes JavaScript específicos da estrutura de Razor componentes para
estruturas da Web, como Angular ou React. Para obter mais informações, consulte
componentes ASP.NET CoreRazor.
Renderizar componentes do JavaScript
Renderize componentes dinamicamente Razor do JavaScript para aplicativos JavaScript
existentes. Para obter mais informações, consulte componentes ASP.NET CoreRazor.
Elementos personalizados
O suporte experimental está disponível para a criação de elementos personalizados, que
usam interfaces HTML padrão. Para obter mais informações, consulte componentes
ASP.NET CoreRazor.
Inferir tipos genéricos de componentes ancestrais
Um componente ancestral pode colocar em cascata um parâmetro de tipo por nome
para descendentes usando o novo [CascadingTypeParameter] atributo . Para obter mais
informações, consulte componentes ASP.NET CoreRazor.
Componentes renderizados dinamicamente
Use o novo componente interno DynamicComponent para renderizar componentes por
tipo. Para obter mais informações, consulte Componentes de ASP.NET Core Razor
renderizados dinamicamente.
Acessibilidade aprimorada Blazor
Use o novo FocusOnNavigate componente para definir o foco da interface do usuário
como um elemento com base em um seletor CSS depois de navegar de uma página
para outra. Para obter mais informações, consulte roteamento e navegação ASP.NET
CoreBlazor.
Suporte a argumento de evento personalizado
Blazor dá suporte a argumentos de evento personalizados, que permitem passar dados
arbitrários para manipuladores de eventos .NET com eventos personalizados. Para obter
mais informações, consulte ASP.NET Core Blazor manipulação de eventos.
Parâmetros obrigatórios
Aplique o novo [EditorRequired] atributo para especificar um parâmetro de
componente necessário. Para obter mais informações, consulte componentes ASP.NET
CoreRazor.
Ordenação de arquivos JavaScript com páginas, exibições
e componentes
Coloque arquivos JavaScript para páginas, exibições e Razor componentes como uma
maneira conveniente de organizar scripts em um aplicativo. Para obter mais
informações, consulte ASP.NET Core Blazor interoperabilidade do JavaScript
(JSinteroperabilidade).
Inicializadores de JavaScript
Os inicializadores do JavaScript executam a lógica antes e depois do carregamento de
um Blazor aplicativo. Para obter mais informações, consulte ASP.NET Core Blazor
interoperabilidade do JavaScript (JSinteroperabilidade).
Interoperabilidade do JavaScript de streaming
Blazor agora dá suporte a dados de streaming diretamente entre o .NET e o JavaScript.
Para saber mais, consulte os recursos a seguir:
Transmitir do .NET para o JavaScript
Transmitir do JavaScript para o .NET
Restrições de tipo genérico
Agora há suporte para parâmetros de tipo genérico. Para obter mais informações,
consulte componentes ASP.NET CoreRazor.
Layout de implantação do WebAssembly
Use um layout de implantação para habilitar Blazor WebAssembly downloads de
aplicativos em ambientes de segurança restritos. Para obter mais informações, consulte
Layout de implantação para aplicativos ASP.NET CoreBlazor WebAssembly.
Novos Blazor artigos
Além dos Blazor recursos descritos nas seções anteriores, novos Blazor artigos estão
disponíveis sobre os seguintes assuntos:
Blazor ASP.NET Core downloads de arquivo: saiba como baixar um arquivo usando
a interoperabilidade de streaming nativa byte[] para garantir uma transferência
eficiente para o cliente.
Trabalhar com imagens no ASP.NET CoreBlazor: descubra como trabalhar com
imagens em Blazor aplicativos, incluindo como transmitir dados de imagem e
visualizar uma imagem.
Criar Blazor Hybrid aplicativos com .NET MAUI,
WPF e Windows Forms
Use Blazor Hybrid para combinar estruturas de cliente nativas da área de trabalho e
móveis com .NET e Blazor:
.NET Multi-platform App UI (.NET MAUI) é uma estrutura multiplataforma para
criar aplicativos móveis e de área de trabalho nativos com C# e XAML.
Blazor Hybridos aplicativos podem ser criados com estruturas de Windows
Presentation Foundation (WPF) e Windows Forms.
) Importante
Blazor Hybrid está em versão prévia e não deve ser usado em aplicativos de
produção até o lançamento final.
Para saber mais, consulte os recursos a seguir:
Documentação da versão prévia do ASP.NET Core Blazor Hybrid
O que é o .NET MAUI?
Blog do Microsoft .NET (categoria: ".NET MAUI")
Kestrel
HTTP/3 está atualmente em rascunho e, portanto, sujeito a alterações. O suporte a
HTTP/3 no ASP.NET Core não é lançado, é um recurso de visualização incluído no .NET
6.
Kestrel agora dá suporte a HTTP/3. Para obter mais informações, consulte Usar HTTP/3
com o servidor Web ASP.NET Core Kestrel e o suporte à entrada de blog HTTP/3 no
.NET 6 .
Novas Kestrel categorias de log para registro em log
selecionado
Antes dessa alteração, habilitar o log detalhado para Kestrel era proibitivamente caro,
pois todo o Microsoft.AspNetCore.Server.Kestrel nome da categoria de Kestrel registro
em log compartilhado. Microsoft.AspNetCore.Server.Kestrel ainda está disponível, mas
as novas subcategorias a seguir permitem mais controle do registro em log:
Microsoft.AspNetCore.Server.Kestrel (categoria atual): ApplicationError , ,
ConnectionHeadResponseBodyWrite , ApplicationNeverCompleted , RequestBodyStart ,
RequestBodyDone , RequestBodyNotEntirelyRead , RequestBodyDrainTimedOut ,
ResponseMinimumDataRateNotSatisfied , InvalidResponseHeaderRemoved ,
HeartbeatSlow .
Microsoft.AspNetCore.Server.Kestrel.BadRequests : ConnectionBadRequest ,
RequestProcessingError , RequestBodyMinimumDataRateNotSatisfied .
Microsoft.AspNetCore.Server.Kestrel.Connections : ConnectionAccepted ,
ConnectionStart , ConnectionStop , ConnectionPause , ConnectionResume ,
ConnectionKeepAlive , ConnectionRejected , ConnectionDisconnect ,
NotAllConnectionsClosedGracefully , NotAllConnectionsAborted ,
ApplicationAbortedConnection .
Microsoft.AspNetCore.Server.Kestrel.Http2 : Http2ConnectionError ,
Http2ConnectionClosing , Http2ConnectionClosed , Http2StreamError ,
Http2StreamResetAbort , HPackDecodingError , HPackEncodingError ,
Http2FrameReceived , Http2FrameSending , Http2MaxConcurrentStreamsReached .
Microsoft.AspNetCore.Server.Kestrel.Http3 : Http3ConnectionError ,
Http3ConnectionClosing , Http3ConnectionClosed , Http3StreamAbort ,
Http3FrameReceived , Http3FrameSending .
As regras existentes continuam funcionando, mas agora você pode ser mais seletivo em
quais regras você habilita. Por exemplo, a sobrecarga de observabilidade de habilitar
Debug o registro em log apenas para solicitações incorretas é muito reduzida e pode ser
habilitada com a seguinte configuração:
XML
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning",
"Microsoft.AspNetCore.Kestrel.BadRequests": "Debug"
}
}
A filtragem de log aplica regras com o prefixo de categoria correspondente mais longo.
Para obter mais informações, consulte Como as regras de filtragem são aplicadas
KestrelEmitir ServerOptions por meio do evento
EventSource
O KestrelEventSource emite um novo evento que contém o JSon-serialized
KestrelServerOptions quando habilitado com detalhamento EventLevel.LogAlways . Esse
evento facilita o raciocínio sobre o comportamento do servidor ao analisar
rastreamentos coletados. O seguinte JSON é um exemplo do conteúdo do evento:
JSON
{
"AllowSynchronousIO": false,
"AddServerHeader": true,
"AllowAlternateSchemes": false,
"AllowResponseHeaderCompression": true,
"EnableAltSvc": false,
"IsDevCertLoaded": true,
"RequestHeaderEncodingSelector": "default",
"ResponseHeaderEncodingSelector": "default",
"Limits": {
"KeepAliveTimeout": "00:02:10",
"MaxConcurrentConnections": null,
"MaxConcurrentUpgradedConnections": null,
"MaxRequestBodySize": 30000000,
"MaxRequestBufferSize": 1048576,
"MaxRequestHeaderCount": 100,
"MaxRequestHeadersTotalSize": 32768,
"MaxRequestLineSize": 8192,
"MaxResponseBufferSize": 65536,
"MinRequestBodyDataRate": "Bytes per second: 240, Grace Period:
00:00:05",
"MinResponseDataRate": "Bytes per second: 240, Grace Period: 00:00:05",
"RequestHeadersTimeout": "00:00:30",
"Http2": {
"MaxStreamsPerConnection": 100,
"HeaderTableSize": 4096,
"MaxFrameSize": 16384,
"MaxRequestHeaderFieldSize": 16384,
"InitialConnectionWindowSize": 131072,
"InitialStreamWindowSize": 98304,
"KeepAlivePingDelay": "10675199.02:48:05.4775807",
"KeepAlivePingTimeout": "00:00:20"
},
"Http3": {
"HeaderTableSize": 0,
"MaxRequestHeaderFieldSize": 16384
}
},
"ListenOptions": [
{
"Address": "https://127.0.0.1:7030",
"IsTls": true,
"Protocols": "Http1AndHttp2"
},
{
"Address": "https://[::1]:7030",
"IsTls": true,
"Protocols": "Http1AndHttp2"
},
{
"Address": "http://127.0.0.1:5030",
"IsTls": false,
"Protocols": "Http1AndHttp2"
},
{
"Address": "http://[::1]:5030",
"IsTls": false,
"Protocols": "Http1AndHttp2"
}
]
}
Novo evento DiagnosticSource para solicitações HTTP
rejeitadas
Kestrel agora emite um novo DiagnosticSource evento para solicitações HTTP rejeitadas
na camada de servidor. Antes dessa alteração, não havia como observar essas
solicitações rejeitadas. O novo DiagnosticSource evento
Microsoft.AspNetCore.Server.Kestrel.BadRequest contém um
IBadRequestExceptionFeature que pode ser usado para introspectar o motivo para
rejeitar a solicitação.
C#
using Microsoft.AspNetCore.Http.Features;
using System.Diagnostics;
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
var diagnosticSource = app.Services.GetRequiredService<DiagnosticListener>
();
using var badRequestListener = new BadRequestEventListener(diagnosticSource,
(badRequestExceptionFeature) =>
{
app.Logger.LogError(badRequestExceptionFeature.Error, "Bad request
received");
});
app.MapGet("/", () => "Hello world");
app.Run();
class BadRequestEventListener : IObserver<KeyValuePair<string, object>>,
IDisposable
{
private readonly IDisposable _subscription;
private readonly Action<IBadRequestExceptionFeature> _callback;
public BadRequestEventListener(DiagnosticListener diagnosticListener,
Action<IBadRequestExceptionFeature>
callback)
{
_subscription = diagnosticListener.Subscribe(this!, IsEnabled);
_callback = callback;
}
private static readonly Predicate<string> IsEnabled = (provider) =>
provider switch
{
"Microsoft.AspNetCore.Server.Kestrel.BadRequest" => true,
_ => false
};
public void OnNext(KeyValuePair<string, object> pair)
{
if (pair.Value is IFeatureCollection featureCollection)
{
var badRequestFeature =
featureCollection.Get<IBadRequestExceptionFeature>();
if (badRequestFeature is not null)
{
_callback(badRequestFeature);
}
}
}
public void OnError(Exception error) { }
public void OnCompleted() { }
public virtual void Dispose() => _subscription.Dispose();
}
Para obter mais informações, confira Registro em log e diagnóstico no Kestrel.
Criar um ConnectionContext a partir de um Soquete de
Aceitação
O novo SocketConnectionContextFactory possibilita criar um ConnectionContext de um
soquete aceito. Isso possibilita criar um soquete personalizado baseado sem
IConnectionListenerFactory perder todo o trabalho de desempenho e o pooling que
acontecem no SocketConnection .
Veja este exemplo de um IConnectionListenerFactory personalizado que mostra como
usar esse SocketConnectionContextFactory .
Kestrel é o perfil de inicialização padrão do Visual Studio
O perfil de inicialização padrão para todos os novos projetos Web dotnet é Kestrel. A
inicialização Kestrel é significativamente mais rápida e resulta em uma experiência mais
responsiva ao desenvolver aplicativos.
IIS Express ainda está disponível como um perfil de inicialização para cenários como
Autenticação do Windows ou compartilhamento de porta.
As portas localhost para Kestrel são aleatórias
Consulte Portas geradas por modelo para Kestrel neste documento para obter mais
informações.
Autenticação e autorização
Servidores de autenticação
O .NET 3 para o .NET 5 usou Identityo Server4 como parte do nosso modelo para dar
suporte à emissão de tokens JWT para SPA e Blazor aplicativos. Os modelos agora usam
o Servidor DuendeIdentity .
Se você estiver estendendo os modelos de identidade e estiver atualizando projetos
existentes, precisará atualizar os namespaces em seu código de para
Duende.IdentityServer e seguir as instruções de
IdentityServer4.IdentityServer migração .
O modelo de licença do Duende Identity Server foi alterado para uma licença recíproca,
o que pode exigir taxas de licença quando ele é usado comercialmente em produção.
Confira a página Licença do Duende para obter mais detalhes.
Negociação de certificado de cliente atrasada
Os desenvolvedores agora podem aceitar usar a negociação de certificado de cliente
atrasada especificando ClientCertificateMode.DelayCertificate no
HttpsConnectionAdapterOptions. Isso só funciona com conexões HTTP/1.1 porque
HTTP/2 proíbe a renegociação de certificados atrasadas. O chamador dessa API deve
armazenar o corpo da solicitação em buffer antes de solicitar o certificado do cliente:
C#
using Microsoft.AspNetCore.Server.Kestrel.Https;
using Microsoft.AspNetCore.WebUtilities;
var builder = WebApplication.CreateBuilder(args);
builder.WebHost.UseKestrel(options =>
{
options.ConfigureHttpsDefaults(adapterOptions =>
{
adapterOptions.ClientCertificateMode =
ClientCertificateMode.DelayCertificate;
});
});
var app = builder.Build();
app.Use(async (context, next) =>
{
bool desiredState = GetDesiredState();
// Check if your desired criteria is met
if (desiredState)
{
// Buffer the request body
context.Request.EnableBuffering();
var body = context.Request.Body;
await body.DrainAsync(context.RequestAborted);
body.Position = 0;
// Request client certificate
var cert = await context.Connection.GetClientCertificateAsync();
// Disable buffering on future requests if the client doesn't
provide a cert
}
await next(context);
});
app.MapGet("/", () => "Hello World!");
app.Run();
OnCheckSlidingExpiration evento para controlar a cookie
renovação
Cookie A expiração deslizante de autenticação agora pode ser personalizada ou
suprimida usando o novo OnCheckSlidingExpiration. Por exemplo, esse evento pode ser
usado por um aplicativo de página única que precisa executar ping periodicamente no
servidor sem afetar a sessão de autenticação.
Diversos
Hot Reload
Faça rapidamente atualizações de interface do usuário e de código para aplicativos em
execução sem perder o estado do aplicativo para uma experiência de desenvolvedor
mais rápida e produtiva usando Recarga Dinâmica. Para obter mais informações,
consulte Suporte ao .NET Recarga Dinâmica para ASP.NET Core e Atualização no
progresso do .NET Recarga Dinâmica e Realces do Visual Studio 2022 .
Modelos de SPA (aplicativo de página única) aprimorados
Os modelos de projeto ASP.NET Core foram atualizados para Angular e React usar um
padrão aprimorado para aplicativos de página única mais flexíveis e mais alinhados com
padrões comuns para o desenvolvimento web de front-end moderno.
Anteriormente, o modelo de ASP.NET Core para Angular e React usava middleware
especializado durante o desenvolvimento para iniciar o servidor de desenvolvimento
para a estrutura de front-end e, em seguida, solicitações de proxy de ASP.NET Core para
o servidor de desenvolvimento. A lógica para iniciar o servidor de desenvolvimento de
front-end era específica para a interface de linha de comando para a estrutura de front-
end correspondente. Dar suporte a estruturas front-end adicionais usando esse padrão
significava adicionar lógica adicional a ASP.NET Core.
Os modelos de ASP.NET Core atualizados para Angular e React no .NET 6 invertem essa
disposição e aproveitam o suporte interno a proxying nos servidores de
desenvolvimento da maioria das estruturas de front-end modernas. Quando o aplicativo
ASP.NET Core é iniciado, o servidor de desenvolvimento de front-end é iniciado
exatamente como antes, mas o servidor de desenvolvimento é configurado para
solicitações de proxy para o processo de ASP.NET Core de back-end. Toda a
configuração específica de front-end para configurar o proxy faz parte do aplicativo,
não ASP.NET Core. A configuração de projetos ASP.NET Core para trabalhar com outras
estruturas de front-end agora é direta: configure o servidor de desenvolvimento de
front-end para a estrutura escolhida para proxy para o back-end ASP.NET Core usando
o padrão estabelecido nos modelos de Angular e React.
O código de inicialização do aplicativo ASP.NET Core não precisa mais de nenhuma
lógica específica do aplicativo de página única. A lógica para iniciar o servidor de
desenvolvimento front-end durante o desenvolvimento é injetar no aplicativo em
runtime pelo novo pacote Microsoft.AspNetCore.SpaProxy . O roteamento de fallback
é tratado usando o roteamento de ponto de extremidade em vez do middleware
específico do SPA.
Os modelos que seguem esse padrão ainda podem ser executados como um único
projeto no Visual Studio ou usando dotnet run a partir da linha de comando. Quando o
aplicativo é publicado, o código de front-end na pasta ClientApp é criado e coletado
como antes na raiz da Web do host ASP.NET Core aplicativo e servido como arquivos
estáticos. Os scripts incluídos no modelo configuram o servidor de desenvolvimento de
front-end para usar HTTPS usando o certificado de desenvolvimento ASP.NET Core.
Rascunho de suporte a HTTP/3 no .NET 6
HTTP/3 está atualmente em rascunho e, portanto, sujeito a alterações. O suporte a
HTTP/3 no ASP.NET Core não é lançado, é um recurso de visualização incluído no .NET
6.
Confira o suporte à entrada de blog HTTP/3 no .NET 6 .
Anotações de tipo de referência anuláveis
Partes do código-fonte ASP.NET Core 6.0 tiveram anotações de nulidade aplicadas.
Ao utilizar o novo recurso anulável no C# 8, ASP.NET Core pode fornecer segurança em
tempo de compilação adicional na manipulação de tipos de referência. Por exemplo,
proteger contra null exceções de referência. Os projetos que optaram por usar
anotações anuláveis podem ver novos avisos de tempo de compilação de APIs de
ASP.NET Core.
Para habilitar tipos de referência anuláveis, adicione a seguinte propriedade aos
arquivos de projeto:
XML
<PropertyGroup>
<Nullable>enable</Nullable>
</PropertyGroup>
Para obter mais informações, confira Tipos de referência anuláveis.
Análise de código-fonte
Vários analisadores de plataforma do compilador .NET foram adicionados que
inspecionam o código do aplicativo em busca de problemas como configuração ou
ordem incorreta de middleware, conflitos de roteamento etc. Para obter mais
informações, consulte Análise de código em aplicativos ASP.NET Core.
Aprimoramentos do modelo de aplicativo Web
Os modelos de aplicativo Web:
Use o novo modelo de hospedagem mínima.
Reduz significativamente o número de arquivos e linhas de código necessários
para criar um aplicativo. Por exemplo, o ASP.NET Core aplicativo Web vazio cria um
arquivo C# com quatro linhas de código e é um aplicativo completo.
Unifica Startup.cs e Program.cs em um único Program.cs arquivo.
Usa instruções de nível superior para minimizar o código necessário para um
aplicativo.
Usa diretivas globais using para eliminar ou minimizar o número de linhas de using
instrução necessárias.
Portas geradas por modelo para Kestrel
Portas aleatórias são atribuídas durante a criação do projeto para uso pelo Kestrel
servidor Web. Portas aleatórias ajudam a minimizar um conflito de porta quando vários
projetos são executados no mesmo computador.
Quando um projeto é criado, uma porta HTTP aleatória entre 5000-5300 e uma porta
HTTPS aleatória entre 7000-7300 é especificada no arquivo gerado
Properties/launchSettings.json . As portas podem ser alteradas no
Properties/launchSettings.json arquivo. Se nenhuma porta for especificada, Kestrel o
padrão será as portas HTTP 5000 e HTTPS 5001. Para obter mais informações, consulte
Configurar pontos de extremidade para o servidor Web ASP.NET CoreKestrel.
Novos padrões de registro em log
As seguintes alterações foram feitas em e
appsettings.json appsettings.Development.json :
diff
- "Microsoft": "Warning",
- "Microsoft.Hosting.Lifetime": "Information"
+ "Microsoft.AspNetCore": "Warning"
A alteração de "Microsoft": "Warning" para "Microsoft.AspNetCore": "Warning" resulta
no registro em log de todas as mensagens informativas do Microsoft namespace ,
exceto Microsoft.AspNetCore . Por exemplo, Microsoft.EntityFrameworkCore agora está
registrado no nível informativo.
Página de exceção do desenvolvedor Middleware
adicionada automaticamente
No ambiente de desenvolvimento, o DeveloperExceptionPageMiddleware é adicionado
por padrão. Não é mais necessário adicionar o seguinte código aos aplicativos de
interface do usuário da Web:
C#
if (app.Environment.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
Suporte para cabeçalhos de solicitação codificados em
Latin1 no HttpSysServer
HttpSysServer agora dá suporte à decodificação de cabeçalhos de solicitação
codificados Latin1 definindo a UseLatin1RequestHeaders propriedade como
HttpSysOptions true :
C#
var builder = WebApplication.CreateBuilder(args);
builder.WebHost.UseHttpSys(o => o.UseLatin1RequestHeaders = true);
var app = builder.Build();
app.MapGet("/", () => "Hello World!");
app.Run();
Os logs do Módulo ASP.NET Core incluem carimbos de
data/hora e PID
Os logs de diagnóstico aprimorados do ANCM (Módulo ASP.NET Core) para IIS (ANCM)
incluem carimbos de data/hora e PID do processo que emite os logs. Registrar
carimbos de data/hora e PID facilita o diagnóstico de problemas com reinicializações de
processo sobrepostas no IIS quando vários processos de trabalho do IIS estão em
execução.
Os logs resultantes agora se assemelham ao exemplo de saída mostrado abaixo:
CLI do .NET
[2021-07-28T19:23:44.076Z, PID: 11020] [aspnetcorev2.dll] Initializing logs
for 'C:\<path>\aspnetcorev2.dll'. Process Id: 11020. File Version:
16.0.21209.0. Description: IIS ASP.NET Core Module V2. Commit:
96475a2acdf50d7599ba8e96583fa73efbe27912.
[2021-07-28T19:23:44.079Z, PID: 11020] [aspnetcorev2.dll] Resolving hostfxr
parameters for application: '.\InProcessWebSite.exe' arguments: '' path:
'C:\Temp\e86ac4e9ced24bb6bacf1a9415e70753\'
[2021-07-28T19:23:44.080Z, PID: 11020] [aspnetcorev2.dll] Known dotnet.exe
location: ''
Tamanho do buffer de entrada inconsumável configurável
para o IIS
O servidor IIS anteriormente armazenava em buffer apenas 64 KiB de corpos de
solicitação não armazenados em buffer. O buffer de 64 KiB resultou em leituras restritas
a esse tamanho máximo, o que afeta o desempenho com grandes corpos de entrada,
como uploads. No .NET 6, o tamanho do buffer padrão muda de 64 KiB para 1 MiB, o
que deve melhorar a taxa de transferência para carregamentos grandes. Em nossos
testes, um upload de 700 MiB que costumava levar 9 segundos agora leva apenas 2,5
segundos.
A desvantagem de um tamanho de buffer maior é um aumento no consumo de
memória por solicitação quando o aplicativo não está lendo rapidamente do corpo da
solicitação. Portanto, além de alterar o tamanho do buffer padrão, o tamanho do buffer
configurável, permitindo que os aplicativos configurem o tamanho do buffer com base
na carga de trabalho.
Exibir auxiliares de marcação de componentes
Considere um componente de exibição com um parâmetro opcional, conforme
mostrado no seguinte código:
C#
class MyViewComponent
{
IViewComponentResult Invoke(bool showSomething = false) { ... }
}
Com ASP.NET Core 6, o auxiliar de marca pode ser invocado sem precisar especificar um
valor para o showSomething parâmetro :
razor
<vc:my />
Angular modelo atualizado para Angular 12
O modelo ASP.NET Core 6.0 para Angular agora usa Angular 12 .
O modelo React foi atualizado para React 17 .
Limite de buffer configurável antes de gravar em disco no
formatador de saída Json.NET
Observação: recomendamos usar o System.Text.Json formatador de saída, exceto
quando o Newtonsoft.Json serializador é necessário por motivos de compatibilidade. O
System.Text.Json serializador é totalmente async e funciona com eficiência para cargas
maiores.
O Newtonsoft.Json formatador de saída por padrão armazena respostas de até 32 KiB
na memória antes de fazer buffer no disco. Isso é para evitar a execução de E/S síncrona,
o que pode resultar em outros efeitos colaterais, como a falta de threads e deadlocks de
aplicativo. No entanto, se a resposta for maior que 32 KiB, ocorrerá uma E/S de disco
considerável. O limite de memória agora é configurável por meio da propriedade
MvcNewtonsoftJsonOptions.OutputFormatterMemoryBufferThreshold antes de fazer
buffer no disco:
C#
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages()
.AddNewtonsoftJson(options =>
{
options.OutputFormatterMemoryBufferThreshold = 48 * 1024;
});
var app = builder.Build();
Para obter mais informações, consulte esta solicitação de pull do GitHub e o arquivo
NewtonsoftJsonOutputFormatterTest.cs .
Obter e definir mais rapidamente para cabeçalhos HTTP
Novas APIs foram adicionadas para expor todos os cabeçalhos comuns disponíveis em
Microsoft.Net.Http.Headers.HeaderNames como propriedades, resultando
IHeaderDictionary em uma API mais fácil de usar. Por exemplo, o middleware em linha
no código a seguir obtém e define cabeçalhos de solicitação e resposta usando as
novas APIs:
C#
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.MapGet("/", () => "Hello World!");
app.Use(async (context, next) =>
{
var hostHeader = context.Request.Headers.Host;
app.Logger.LogInformation("Host header: {host}", hostHeader);
context.Response.Headers.XPoweredBy = "ASP.NET Core 6.0";
await next.Invoke(context);
var dateHeader = context.Response.Headers.Date;
app.Logger.LogInformation("Response date: {date}", dateHeader);
});
app.Run();
Para cabeçalhos implementados, os acessadores get e set são implementados
acessando diretamente o campo e ignorando a pesquisa. Para cabeçalhos não
implementados, os acessadores podem ignorar a pesquisa inicial em relação aos
cabeçalhos implementados e executar diretamente a Dictionary<string, StringValues>
pesquisa. Evitar a pesquisa resulta em acesso mais rápido para ambos os cenários.
Streaming assíncrono
ASP.NET Core agora dá suporte ao streaming assíncrono de ações e respostas do
controlador do JS Formatador ON. Retornar um IAsyncEnumerable de uma ação não
armazena mais em buffer o conteúdo da resposta na memória antes de ser enviado. O
não buffer ajuda a reduzir o uso de memória ao retornar grandes conjuntos de dados
que podem ser enumerados de forma assíncrona.
Observe que o Entity Framework Core fornece implementações de IAsyncEnumerable
para consultar o banco de dados. O suporte aprimorado para IAsyncEnumerable em
ASP.NET Core no .NET 6 pode tornar o uso EF Core com ASP.NET Core mais eficiente.
Por exemplo, o código a seguir não armazena mais os dados do produto na memória
antes de enviar a resposta:
C#
public IActionResult GetMovies()
{
return Ok(_context.Movie);
}
No entanto, ao usar o carregamento lento no EF Core, esse novo comportamento pode
resultar em erros devido à execução simultânea da consulta enquanto os dados estão
sendo enumerados. Os aplicativos podem reverter para o comportamento anterior
armazenando os dados em buffer:
C#
public async Task<IActionResult> GetMovies2()
{
return Ok(await _context.Movie.ToListAsync());
}
Consulte o comunicado relacionado para obter detalhes adicionais sobre essa
alteração no comportamento.
Middleware de log HTTP
O log HTTP é um novo middleware interno que registra informações sobre solicitações
HTTP e respostas HTTP, incluindo os cabeçalhos e todo o corpo:
C#
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.UseHttpLogging();
app.MapGet("/", () => "Hello World!");
app.Run();
Navegando até / com as informações de logs de código anteriores semelhantes à
seguinte saída:
CLI do .NET
info: Microsoft.AspNetCore.HttpLogging.HttpLoggingMiddleware[1]
Request:
Protocol: HTTP/2
Method: GET
Scheme: https
PathBase:
Path: /
Accept:
text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,
*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9
Cache-Control: max-age=0
Connection: close
Cookie: [Redacted]
Host: localhost:44372
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64)
AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.54 Safari/537.36
Edg/95.0.1020.30
sec-ch-ua: [Redacted]
sec-ch-ua-mobile: [Redacted]
sec-ch-ua-platform: [Redacted]
upgrade-insecure-requests: [Redacted]
sec-fetch-site: [Redacted]
sec-fetch-mode: [Redacted]
sec-fetch-user: [Redacted]
sec-fetch-dest: [Redacted]
info: Microsoft.AspNetCore.HttpLogging.HttpLoggingMiddleware[2]
Response:
StatusCode: 200
Content-Type: text/plain; charset=utf-8
A saída anterior foi habilitada com o seguinte appsettings.Development.json arquivo:
JSON
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning",
"Microsoft.AspNetCore.HttpLogging.HttpLoggingMiddleware":
"Information"
}
}
}
O registro em log HTTP fornece logs de:
Informações de solicitação HTTP
Propriedades comuns
Cabeçalhos
Corpo
Informações de resposta HTTP
Para configurar o middleware de log HTTP, especifique HttpLoggingOptions:
C#
using Microsoft.AspNetCore.HttpLogging;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddHttpLogging(logging =>
{
// Customize HTTP logging.
logging.LoggingFields = HttpLoggingFields.All;
logging.RequestHeaders.Add("My-Request-Header");
logging.ResponseHeaders.Add("My-Response-Header");
logging.MediaTypeOptions.AddText("application/javascript");
logging.RequestBodyLogLimit = 4096;
logging.ResponseBodyLogLimit = 4096;
});
var app = builder.Build();
app.UseHttpLogging();
app.MapGet("/", () => "Hello World!");
app.Run();
IConnectionSocketFeature
O IConnectionSocketFeature recurso de solicitação fornece acesso ao soquete de
aceitação subjacente associado à solicitação atual. Ele pode ser acessado por meio do
FeatureCollection em HttpContext .
Por exemplo, o aplicativo a seguir define a LingerState propriedade no soquete aceito:
C#
var builder = WebApplication.CreateBuilder(args);
builder.WebHost.ConfigureKestrel(serverOptions =>
{
serverOptions.ConfigureEndpointDefaults(listenOptions =>
listenOptions.Use((connection, next) =>
{
var socketFeature =
connection.Features.Get<IConnectionSocketFeature>();
socketFeature.Socket.LingerState = new LingerOption(true, seconds:
10);
return next();
}));
});
var app = builder.Build();
app.MapGet("/", (Func<string>)(() => "Hello world"));
await app.RunAsync();
Restrições de tipo genérico em Razor
Ao definir parâmetros de tipo genérico no Razor uso da diretiva , restrições @typeparam
de tipo genérico agora podem ser especificadas usando a sintaxe padrão do C#:
SignalRScripts menores , Blazor Servere MessagePack
Os SignalRscripts , MessagePack e Blazor Server agora são significativamente menores,
permitindo downloads menores, menos análise e compilação de JavaScript pelo
navegador e inicialização mais rápida. As reduções de tamanho:
signalr.js : 70%
blazor.server.js : 45%
Os scripts menores são resultado de uma contribuição da comunidade de Ben Adams .
Para obter mais informações sobre os detalhes da redução de tamanho, consulte
Solicitação de pull do GitHub de Ben .
Habilitar sessões de criação de perfil do Redis
Uma contribuição da comunidade de Gabriel Lucaci habilita a sessão de criação de
perfil do Redis com Microsoft.Extensions.Caching.StackExchangeRedis :
C#
using StackExchange.Redis.Profiling;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddStackExchangeRedisCache(options =>
{
options.ProfilingSession = () => new ProfilingSession();
});
Para obter mais informações, consulte Criação de perfil do StackExchange.Redis .
Cópia de sombra no IIS
Um recurso experimental foi adicionado ao ANCM (Módulo ASP.NET Core) para IIS para
adicionar suporte para assemblies de aplicativo de cópia de sombra. Atualmente, o .NET
bloqueia binários de aplicativos ao ser executado no Windows, impossibilitando a
substituição de binários quando o aplicativo está em execução. Embora nossa
recomendação permaneça para usar um arquivo offline do aplicativo, reconhecemos
que há determinados cenários (por exemplo, implantações ftp) em que não é possível
fazê-lo.
Nesses cenários, habilite a cópia de sombra personalizando as configurações do
manipulador de módulo ASP.NET Core. Na maioria dos casos, ASP.NET Core aplicativos
não têm um web.config controle do código-fonte verificado que você pode modificar.
Em ASP.NET Core, web.config normalmente é gerado pelo SDK. O exemplo web.config
a seguir pode ser usado para começar:
XML
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<!-- To customize the asp.net core module uncomment and edit the following
section.
For more info see https://go.microsoft.com/fwlink/?linkid=838655 -->
<system.webServer>
<handlers>
<remove name="aspNetCore"/>
<add name="aspNetCore" path="*" verb="*" modules="AspNetCoreModuleV2"
resourceType="Unspecified"/>
</handlers>
<aspNetCore processPath="%LAUNCHER_PATH%" arguments="%LAUNCHER_ARGS%"
stdoutLogEnabled="false" stdoutLogFile=".\logs\stdout">
<handlerSettings>
<handlerSetting name="experimentalEnableShadowCopy" value="true" />
<handlerSetting name="shadowCopyDirectory"
value="../ShadowCopyDirectory/" />
<!-- Only enable handler logging if you encounter issues-->
<!--<handlerSetting name="debugFile" value=".\logs\aspnetcore-
debug.log" />-->
<!--<handlerSetting name="debugLevel" value="FILE,TRACE" />-->
</handlerSettings>
</aspNetCore>
</system.webServer>
</configuration>
A cópia de sombra no IIS é um recurso experimental que não tem garantia de fazer
parte do ASP.NET Core. Deixe comentários sobre a cópia de Sombra do IIS neste
problema do GitHub .
Recursos adicionais
Exemplos de código migrados para o novo modelo de hospedagem mínimo na
versão 6.0
Novidades no .NET 6
Novidades no ASP.NET Core 5.0
Artigo • 05/10/2022 • 16 minutos para o fim da leitura
Este artigo destaca as alterações mais significativas no ASP.NET Core 5.0 com links para
a documentação relevante.
ASP.NET Core MVC e Razor melhorias
DateTime de associação de modelo como UTC
A associação de modelo agora dá suporte à associação de cadeias de caracteres de
tempo UTC para DateTime . Se a solicitação contiver uma cadeia de caracteres de tempo
UTC, a associação de modelo a associará a um UTC DateTime . Por exemplo, a cadeia de
caracteres de tempo a seguir está vinculada ao UTC DateTime :
https://example.com/mycontroller/myaction?time=2019-06-14T02%3A30%3A04.0576719Z
Associação e validação de modelo com tipos de registro
C# 9
Os tipos de registro C# 9 podem ser usados com a associação de modelo em um
controlador MVC ou uma Razor página. Os tipos de registro são uma boa maneira de
modelar dados que estão sendo transmitidos pela rede.
Por exemplo, o seguinte PersonController usa o tipo de Person registro com
associação de modelo e validação de formulário:
C#
public record Person([Required] string Name, [Range(0, 150)] int Age);
public class PersonController
{
public IActionResult Index() => View();
[HttpPost]
public IActionResult Index(Person person)
{
// ...
}
}
O arquivo Person/Index.cshtml :
CSHTML
@model Person
Name: <input asp-for="Model.Name" />
<span asp-validation-for="Model.Name" />
Age: <input asp-for="Model.Age" />
<span asp-validation-for="Model.Age" />
Melhorias no DynamicRouteValueTransformer
ASP.NET Core 3.1 introduzido DynamicRouteValueTransformer como uma forma de usar
o ponto de extremidade personalizado para selecionar dinamicamente uma ação do
controlador MVC ou uma Razor página. ASP.NET Core aplicativos 5.0 podem passar o
estado para um DynamicRouteValueTransformer e filtrar o conjunto de pontos de
extremidade escolhidos.
Diversos
O atributo [Compare] pode ser aplicado a propriedades em um Razor modelo de
página.
Parâmetros e propriedades associadas do corpo são considerados exigidos por
padrão.
API Web
Especificação de OpenAPI por padrão
A Especificação openAPI é um padrão do setor para descrever APIs HTTP e integrá-las
a processos de negócios complexos ou a terceiros. O OpenAPI é amplamente
compatível com todos os provedores de nuvem e muitos registros de API. Aplicativos
que emitem documentos OpenAPI de APIs Web têm uma variedade de novas
oportunidades nas quais essas APIs podem ser usadas. Em parceria com os
mantenedores do projeto de software livre Swashbuckle.AspNetCore , o modelo de
API ASP.NET Core contém uma dependência do NuGet no Swashbuckle . O
Swashbuckle é um pacote NuGet de software livre popular que emite documentos
OpenAPI dinamicamente. O Swashbuckle faz isso introspecndo sobre os controladores
de API e gerando o documento OpenAPI em tempo de execução ou em tempo de build
usando a CLI do Swashbuckle.
No ASP.NET Core 5.0, os modelos de API Web habilitam o suporte a OpenAPI por
padrão. Para desabilitar o OpenAPI:
Na linha de comando:
CLI do .NET
dotnet new webapi --no-openapi true
No Visual Studio: desmarque habilitar o suporte ao OpenAPI.
Todos os .csproj arquivos criados para projetos de API Web contêm a referência do
pacote NuGet Swashbuckle.AspNetCore .
XML
<ItemGroup>
<PackageReference Include="Swashbuckle.AspNetCore" Version="5.5.1" />
</ItemGroup>
O código gerado pelo modelo contém código que Startup.ConfigureServices ativa a
geração de documentos OpenAPI:
C#
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers();
services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1", new OpenApiInfo { Title = "WebApp1", Version =
"v1" });
});
}
O Startup.Configure método adiciona o middleware Swashbuckle, que permite:
Processo de geração de documentos.
Página de interface do usuário do Swagger por padrão no modo de
desenvolvimento.
O código gerado pelo modelo não exporá acidentalmente a descrição da API ao
publicar em produção.
C#
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseSwagger();
app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json",
"WebApp1 v1"));
}
app.UseHttpsRedirection();
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
Importação de Gerenciamento de API do Azure
Quando ASP.NET Core projetos de API habilitam o OpenAPI, o Visual Studio 2019 versão
16.8 e a publicação posterior oferecem automaticamente uma etapa adicional no fluxo
de publicação. Os desenvolvedores que usam o Azure Gerenciamento de API têm a
oportunidade de importar automaticamente as APIs para o Azure Gerenciamento de API
durante o fluxo de publicação:
Melhor experiência de inicialização para projetos de API
Web
Com o OpenAPI habilitado por padrão, a experiência de inicialização do aplicativo (F5)
para desenvolvedores de API Web melhora significativamente. Com ASP.NET Core 5.0, o
modelo de API Web vem pré-configurado para carregar a página de interface do
usuário do Swagger. A página de interface do usuário do Swagger fornece a
documentação adicionada para a API publicada e permite testar as APIs com um único
clique.
Blazor
Aprimoramentos de desempenho
Para o .NET 5, fizemos melhorias significativas Blazor WebAssembly no desempenho do
runtime com um foco específico na renderização de interface do usuário complexa e
JSna serialização ON. Em nossos testes de desempenho, Blazor WebAssembly no .NET 5
é duas a três vezes mais rápido para a maioria dos cenários. Para obter mais
informações, consulte ASP.NET Blog: ASP.NET Core atualizações no .NET 5 Release
Candidate 1 .
Isolamento de CSS
Blazor agora dá suporte à definição de estilos CSS que têm como escopo um
determinado componente. Estilos CSS específicos do componente facilitam o raciocínio
sobre os estilos em um aplicativo e evitar efeitos colaterais não intencionais de estilos
globais. Para obter mais informações, consulte ASP.NET Core Blazor isolamento do CSS.
Novo InputFile componente
O InputFile componente permite a leitura de um ou mais arquivos selecionados por
um usuário para upload. Para obter mais informações, consulte ASP.NET Core Blazor
uploads de arquivo.
Novos InputRadio e InputRadioGroup componentes
Blazor InputRadio tem componentes internos e InputRadioGroup que simplificam a
associação de dados a grupos de botões de opção com validação integrada. Para obter
mais informações, consulte ASP.NET Core Blazor formulários e componentes de entrada.
Virtualização de componente
Melhore o desempenho percebido da renderização de componentes usando o Blazor
suporte interno de virtualização da estrutura. Para obter mais informações, consulte
ASP.NET Core Razor virtualização do componente.
ontoggle suporte a eventos
Blazor os eventos agora dão suporte ao ontoggle evento DOM. Para obter mais
informações, consulte ASP.NET Core Blazor tratamento de eventos.
Definir o foco da interface do usuário em Blazor
aplicativos
Use o FocusAsync método de conveniência em referências de elemento para definir o
foco da interface do usuário para esse elemento. Para obter mais informações, consulte
ASP.NET Core Blazor tratamento de eventos.
Atributos de classe CSS de validação personalizada
Atributos de classe CSS de validação personalizada são úteis ao integrar-se a estruturas
CSS, como Bootstrap. Para obter mais informações, consulte ASP.NET Core Blazor
formulários e componentes de entrada.
Suporte a IAsyncDisposable
Razor os componentes agora dão suporte à IAsyncDisposable interface para a versão
assíncrona de recursos alocados.
Referências de objeto e isolamento do JavaScript
Blazor habilita o isolamento javaScript em módulos JavaScript padrão. Para obter mais
informações, consulte Chamar funções JavaScript de métodos .NET no ASP.NET Core
Blazor.
Os componentes de formulário dão suporte ao nome de
exibição
Os seguintes componentes internos dão suporte a nomes de exibição com o
DisplayName parâmetro:
InputDate
InputNumber
InputSelect
Para obter mais informações, consulte ASP.NET Core Blazor formulários e componentes
de entrada.
Parâmetros de rota catch-all
Os parâmetros de rota catch-all, que capturam caminhos entre vários limites de pasta,
têm suporte em componentes. Para obter mais informações, consulte ASP.NET Core
Blazor roteamento e navegação.
Melhorias na depuração
A depuração de Blazor WebAssembly aplicativos é aprimorada no ASP.NET Core 5.0.
Além disso, agora há suporte para depuração em Visual Studio para Mac. Para obter
mais informações, consulte Depurar ASP.NET Core Blazor WebAssembly.
Microsoft Identity v2.0 e MSAL v2.0
Blazor A segurança agora usa Microsoft Identity v2.0 (Microsoft.Identity.Web e
Microsoft.Identity.Web.UI ) e MSAL v2.0. Para obter mais informações, consulte os
tópicos no nó e Identity segurançaBlazor.
Armazenamento protegido do navegador para Blazor
Server
Blazor Serveragora os aplicativos podem usar suporte interno para armazenar o estado
do aplicativo no navegador que foi protegido contra adulteração usando ASP.NET Core
proteção de dados. Os dados podem ser armazenados no armazenamento local do
navegador ou no armazenamento de sessão. Para obter mais informações, consulte
ASP.NET Core Blazor gerenciamento de estado.
Blazor WebAssembly pré-geração
A integração de componentes é aprimorada em modelos de hospedagem e Blazor
WebAssembly os aplicativos agora podem gerar saída no servidor.
Melhorias de corte/vinculação
Blazor WebAssembly executa o corte/vinculação de IL (Linguagem Intermediária)
durante um build para cortar IL desnecessária dos assemblies de saída do aplicativo.
Com a versão do ASP.NET Core 5.0, Blazor WebAssembly executa o corte aprimorado
com opções de configuração adicionais. Para obter mais informações, consulte
Configurar o Trimmer para opções de ASP.NET Core Blazor e Corte.
Analisador de compatibilidade do navegador
Blazor WebAssembly os aplicativos têm como destino a área completa da superfície da
API do .NET, mas nem todas as APIs do .NET têm suporte no WebAssembly devido a
restrições de área restrita do navegador. APIs sem suporte são lançadas
PlatformNotSupportedException ao serem executadas no WebAssembly. Um analisador
de compatibilidade de plataforma avisa o desenvolvedor quando o aplicativo usa APIs
que não têm suporte nas plataformas de destino do aplicativo. Para obter mais
informações, consulte Consumir componentes Razor do ASP.NET Core de uma RCL
(biblioteca de classes) Razor.
Assemblies de carga lentos
Blazor WebAssembly O desempenho de inicialização do aplicativo pode ser aprimorado
adiando o carregamento de alguns assemblies de aplicativo até que eles sejam
necessários. Para obter mais informações, consulte assemblies de carga lentos no
ASP.NET Core Blazor WebAssembly.
Suporte atualizado à globalização
O suporte à globalização está disponível para Blazor WebAssembly base em
Componentes Internacionais para Unicode (UTI). Para obter mais informações, consulte
ASP.NET Core Blazor globalização e localização.
gRPC
Muitas melhorias de pré-formação foram feitas no gRPC . Para obter mais
informações, consulte melhorias no desempenho do gRPC no .NET 5 .
Para obter mais informações sobre gRPC, consulte Visão geral do gRPC no .NET.
SignalR
SignalR Filtros de hub
SignalR Os filtros de hub, chamados de pipelines do Hub em ASP.NET SignalR, são um
recurso que permite que o código seja executado antes e depois que os métodos hub
são chamados. Executar código antes e depois que os métodos hub são chamados é
semelhante a como o middleware tem a capacidade de executar código antes e depois
de uma solicitação HTTP. Os usos comuns incluem registro em log, tratamento de erros
e validação de argumento.
Para obter mais informações, consulte Usar filtros de hub em ASP.NET Core SignalR.
SignalR invocações de hub paralelo
SignalR ASP.NET Core agora é capaz de lidar com invocações de hub paralelo. O
comportamento padrão pode ser alterado para permitir que os clientes invoquem mais
de um método hub por vez:
C#
public void ConfigureServices(IServiceCollection services)
{
services.AddSignalR(options =>
{
options.MaximumParallelInvocationsPerClient = 5;
});
}
Adicionado suporte ao Messagepack no SignalR cliente
Java
Um novo pacote, com.microsoft.signalr.messagepack , adiciona suporte ao
MessagePack ao SignalR cliente Java. Para usar o protocolo do hub MessagePack,
adicione .withHubProtocol(new MessagePackHubProtocol()) ao construtor de conexões:
Java
HubConnection hubConnection = HubConnectionBuilder.create(
"http://localhost:53353/MyHub")
.withHubProtocol(new MessagePackHubProtocol())
.build();
Kestrel
Pontos de extremidade recarregáveis por meio da configuração: Kestrel pode
detectar alterações na configuração passadas paraKestrel ServerOptions.Configure
e desvinculada de pontos de extremidade existentes e associar a novos pontos de
extremidade sem exigir uma reinicialização do aplicativo quando o reloadOnChange
parâmetro for true . Por padrão, ao usar ConfigureWebHostDefaults ou
CreateDefaultBuilder, Kestrel associa-se à subseção de configuração "Kestrel"
com reloadOnChange habilitado. Os aplicativos devem passar reloadOnChange: true
ao chamar KestrelServerOptions.Configure manualmente para obter pontos de
extremidade recarregáveis.
Melhorias de cabeçalhos de resposta HTTP/2. Para obter mais informações,
consulte melhorias de desempenho na próxima seção.
Suporte para tipos de pontos de extremidade adicionais no transporte de
soquetes: adicionando à nova API introduzida System.Net.Sockets, o transporte
Kestrel padrão dos soquetes permite associação a identificadores de arquivo
existentes e soquetes de domínio Unix. O suporte para associação a identificadores
de arquivo existentes permite o uso da integração existente Systemd sem exigir o
libuv transporte.
Decodificação de cabeçalho personalizada em Kestrel: Os aplicativos podem
especificar quais Encoding usar para interpretar cabeçalhos de entrada com base
no nome do cabeçalho em vez de padrão para UTF-8. Defina a
Microsoft.AspNetCore.Server.Kestrel.KestrelServerOptions.RequestHeaderEncoding
Selector propriedade para especificar qual codificação usar:
C#
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.ConfigureKestrel(options =>
{
options.RequestHeaderEncodingSelector = encoding =>
{
return encoding switch
{
"Host" => System.Text.Encoding.Latin1,
_ => System.Text.Encoding.UTF8,
};
};
});
webBuilder.UseStartup<Startup>();
});
Kestrel opções específicas do ponto de extremidade por
meio da configuração
O suporte foi adicionado para configurar Kestrelas opções específicas do ponto de
extremidade por meio da configuração. As configurações específicas do ponto de
extremidade incluem:
Protocolos HTTP usados
Protocolos TLS usados
Certificado selecionado
Modo de certificado do cliente
A configuração permite especificar qual certificado é selecionado com base no nome do
servidor especificado. O nome do servidor faz parte da extensão SNI (Indicação de
Nome do Servidor) para o protocolo TLS, conforme indicado pelo cliente. KestrelA
configuração 's também dá suporte a um prefixo curinga no nome do host.
O exemplo a seguir mostra como especificar ponto de extremidade específico usando
um arquivo de configuração:
JSON
{
"Kestrel": {
"Endpoints": {
"EndpointName": {
"Url": "https://*",
"Sni": {
"a.example.org": {
"Protocols": "Http1AndHttp2",
"SslProtocols": [ "Tls11", "Tls12"],
"Certificate": {
"Path": "testCert.pfx",
"Password": "testPassword"
},
"ClientCertificateMode" : "NoCertificate"
},
"*.example.org": {
"Certificate": {
"Path": "testCert2.pfx",
"Password": "testPassword"
}
},
"*": {
// At least one sub-property needs to exist per
// SNI section or it cannot be discovered via
// IConfiguration
"Protocols": "Http1",
}
}
}
}
}
}
A SNI (Indicação de Nome do Servidor) é uma extensão TLS para incluir um domínio
virtual como parte da negociação de SSL. O que isso significa efetivamente é que o
nome de domínio virtual ou um nome de host pode ser usado para identificar o ponto
de extremidade de rede.
Aprimoramentos de desempenho
HTTP/2
Reduções significativas nas alocações no caminho de código HTTP/2.
Suporte para compactação dinâmica HPack de cabeçalhos de resposta HTTP/2
em Kestrel. Para obter mais informações, consulte o tamanho da tabela cabeçalho
e HPACK: o assassino silencioso (recurso) de HTTP/2 .
Enviando quadros PING HTTP/2: HTTP/2 tem um mecanismo para enviar quadros
PING para garantir que uma conexão ociosa ainda esteja funcional. Garantir uma
conexão viável é especialmente útil ao trabalhar com fluxos de longa duração que
muitas vezes estão ociosos, mas que só veem atividade intermitentemente, por
exemplo, fluxos gRPC. Os aplicativos podem enviar quadros PING periódicos
definindo limites em KestrelKestrelServerOptions:
C#
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.ConfigureKestrel(options =>
{
options.Limits.Http2.KeepAlivePingInterval =
TimeSpan.FromSeconds(10);
options.Limits.Http2.KeepAlivePingTimeout =
TimeSpan.FromSeconds(1);
});
webBuilder.UseStartup<Startup>();
});
Contêineres
Antes do .NET 5.0, a criação e a publicação de um Dockerfile para um aplicativo ASP.NET
Core exigiam a extração de todo o SDK do .NET Core e da imagem ASP.NET Core. Com
essa versão, a extração dos bytes de imagens do SDK é reduzida e os bytes puxados
para a imagem ASP.NET Core são em grande parte eliminados. Para obter mais
informações, consulte este comentário sobre o problema do GitHub .
Autenticação e autorização
Autenticação do Azure Active Directory com a
Microsoft.Identity. Web
Os modelos de projeto ASP.NET Core agora se integram para lidar com
Microsoft.Identity.Web a autenticação com o Azure Active Directory (Azure AD). A
Microsoft.Identity. O pacote Web fornece:
Uma experiência melhor para autenticação por meio de Azure AD.
Uma maneira mais fácil de acessar recursos do Azure em nome de seus usuários,
incluindo o Microsoft Graph. Consulte a Microsoft.Identity. Exemplo da Web , que
começa com um logon básico e avança por meio de vários locatários, usando APIs
do Azure, usando o Microsoft Graph e protegendo suas próprias APIs.
Microsoft.Identity.Web está disponível ao lado do .NET 5.
Permitir acesso anônimo a um ponto de extremidade
O AllowAnonymous método de extensão permite acesso anônimo a um ponto de
extremidade:
C#
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapGet("/", async context =>
{
await context.Response.WriteAsync("Hello World!");
})
.AllowAnonymous();
});
}
Tratamento personalizado de falhas de autorização
O tratamento personalizado de falhas de autorização agora é mais fácil com a nova
interface IAuthorizationMiddlewareResultHandler que é invocada pelo Middleware de
autorização. A implementação padrão permanece a mesma, mas um manipulador
personalizado pode ser registrado em [Injeção de dependência, que permite respostas
HTTP personalizadas com base no motivo pelo qual a autorização falhou. Veja este
exemplo que demonstra o IAuthorizationMiddlewareResultHandler uso do .
Autorização ao usar o roteamento de ponto de
extremidade
A autorização ao usar o roteamento de ponto de extremidade agora recebe a instância
do ponto de extremidade e não a HttpContext instância do ponto de extremidade. Isso
permite que o middleware de autorização acesse as RouteData propriedades e outras
que HttpContext não estavam acessíveis por meio da Endpoint classe. O ponto de
extremidade pode ser buscado do contexto usando contexto . GetEndpoint.
Controle de acesso baseado em função com autenticação
Kerberos e LDAP no Linux
Consulte a autenticação Kerberos e o RBAC (controle de acesso baseado em função)
Melhorias de API
JSMétodos de extensão ON para HttpRequest e
HttpResponse
JSOs dados ON podem ser lidos e gravados em um HttpRequest e HttpResponse usando
os métodos novos ReadFromJsonAsync e WriteAsJsonAsync de extensão. Esses métodos
de extensão usam o serializador System.Text.Json para lidar com os JSdados ON. O novo
HasJsonContentType método de extensão também pode verificar se uma solicitação tem
um JStipo de conteúdo ON.
Os JSmétodos de extensão ON podem ser combinados com o roteamento de ponto de
extremidade para criar JSAPIs ON em um estilo de programação que chamamos de rota
para código. É uma nova opção para desenvolvedores que desejam criar APIs ON
básicas JSde maneira leve. Por exemplo, um aplicativo Web que tem apenas um
punhado de pontos de extremidade pode optar por usar a rota para codificar em vez da
funcionalidade completa de ASP.NET Core MVC:
C#
endpoints.MapGet("/weather/{city:alpha}", async context =>
{
var city = (string)context.Request.RouteValues["city"];
var weather = GetFromDatabase(city);
await context.Response.WriteAsJsonAsync(weather);
});
System.Diagnostics.Activity
O formato padrão, por System.Diagnostics.Activity enquanto, é padrão para o formato
W3C. Isso torna o suporte de rastreamento distribuído em ASP.NET Core interoperável
com mais estruturas por padrão.
FromBodyAttribute
FromBodyAttribute agora dá suporte à configuração de uma opção que permite que
esses parâmetros ou propriedades sejam considerados opcionais:
C#
public IActionResult Post([FromBody(EmptyBodyBehavior =
EmptyBodyBehavior.Allow)]
MyModel model)
{
...
}
Melhorias diversas
Começamos a aplicar anotações anuláveis a ASP.NET Core assemblies. Planejamos
anotar a maior parte da superfície de API pública comum da estrutura do .NET 5.
Controlar ativação de classe de inicialização
Foi adicionada uma sobrecarga adicional UseStartup que permite que um aplicativo
forneça um método de fábrica para controlar Startup a ativação de classe. Startup
Controlar a ativação de classe é útil para passar parâmetros adicionais para Startup os
quais são inicializados junto com o host:
C#
public class Program
{
public static async Task Main(string[] args)
{
var logger = CreateLogger();
var host = Host.CreateDefaultBuilder()
.ConfigureWebHost(builder =>
{
builder.UseStartup(context => new Startup(logger));
})
.Build();
await host.RunAsync();
}
}
Atualização automática com o relógio dotnet
No .NET 5, a execução do relógio dotnet em um projeto ASP.NET Core inicia o
navegador padrão e atualiza automaticamente o navegador à medida que as alterações
são feitas no código. Isso significa que você pode:
Abra um projeto ASP.NET Core em um editor de texto.
Execute dotnet watch .
Concentre-se nas alterações de código enquanto as ferramentas manipulam a
recompilação, a reinicialização e o recarregamento do aplicativo.
Formator do Agente de Console
Foram feitas melhorias no provedor de log do console na Microsoft.Extensions.Logging
biblioteca. Os desenvolvedores agora podem implementar um controle personalizado
ConsoleFormatter para exercer controle completo sobre a formatação e a coloração da
saída do console. As APIs de formatador permitem uma formatação avançada
implementando um subconjunto das sequências de escape VT-100. O VT-100 tem
suporte na maioria dos terminais modernos. O agente de console pode analisar
sequências de escape em terminais sem suporte, permitindo que os desenvolvedores
criem um único formatador para todos os terminais.
JSAgente do Console ON
Além do suporte para formatores personalizados, também adicionamos um formatador
ON interno JSque emite logs ON estruturados JSno console. O código a seguir mostra
como alternar do agente padrão para JSON:
C#
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureLogging(logging =>
{
logging.AddJsonConsole(options =>
{
options.JsonWriterOptions = new JsonWriterOptions()
{ Indented = true };
});
})
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
As mensagens de log emitidas no console são JSon formatadas:
JSON
{
"EventId": 0,
"LogLevel": "Information",
"Category": "Microsoft.Hosting.Lifetime",
"Message": "Now listening on: https://localhost:5001",
"State": {
"Message": "Now listening on: https://localhost:5001",
"address": "https://localhost:5001",
"{OriginalFormat}": "Now listening on: {address}"
}
}
Novidades no ASP.NET Core 3.1
Artigo • 10/01/2023 • 3 minutos para o fim da leitura
Este artigo destaca as alterações mais significativas no ASP.NET Core 3.1 com links para
a documentação relevante.
Suporte de classe parcial para Razor
componentes
Razor os componentes agora são gerados como classes parciais. O código para um
Razor componente pode ser escrito usando um arquivo code-behind definido como
uma classe parcial em vez de definir todo o código para o componente em um único
arquivo. Para obter mais informações, consulte Suporte de classe parcial.
Auxiliar de Marca de Componente e passa
parâmetros para componentes de nível
superior
Em Blazor com ASP.NET Core 3.0, os componentes foram renderizados em páginas e
exibições usando um Auxiliar html ( Html.RenderComponentAsync ). No ASP.NET Core 3.1,
renderize um componente de uma página ou exibição com o novo Auxiliar de Marca de
Componente:
CSHTML
<component type="typeof(Counter)" render-mode="ServerPrerendered" />
O Auxiliar html permanece com suporte no ASP.NET Core 3.1, mas o Auxiliar de Marca
de Componente é recomendado.
Blazor Server Agora, os aplicativos podem passar parâmetros para componentes de
nível superior durante a renderização inicial. Anteriormente, você só podia passar
parâmetros para um componente de nível superior com RenderMode.Static. Com esta
versão, há suporte para RenderMode.Server e RenderMode.ServerPrerendered . Todos
os valores de parâmetro especificados são serializados como JSON e incluídos na
resposta inicial.
Por exemplo, pré-gerar um Counter componente com uma quantidade de incremento
( IncrementAmount ):
CSHTML
<component type="typeof(Counter)" render-mode="ServerPrerendered"
param-IncrementAmount="10" />
Para obter mais informações, consulte Integrar componentes em Razor aplicativos Pages
e MVC.
Suporte para filas compartilhadas no HTTP.sys
HTTP.sysdá suporte à criação de filas de solicitação anônima. No ASP.NET Core 3.1,
adicionamos a capacidade de criar ou anexar a uma fila de solicitação de HTTP.sys
nomeada existente. Criar ou anexar a uma fila de solicitação de HTTP.sys nomeada
existente permite cenários em que o processo do controlador de HTTP.sys que possui a
fila é independente do processo do ouvinte. Essa independência possibilita preservar
conexões existentes e solicitações enfileiradas entre reinicializações do processo do
ouvinte:
C#
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
// ...
webBuilder.UseHttpSys(options =>
{
options.RequestQueueName = "MyExistingQueue";
options.RequestQueueMode = RequestQueueMode.CreateOrAttach;
});
});
Alterações interruptivas para SameSite cookies
O comportamento do SameSite cookies foi alterado para refletir as próximas alterações
no navegador. Isso pode afetar cenários de autenticação como AzureAd,
OpenIdConnect ou WsFederation. Para obter mais informações, consulte Trabalhar com
SameSite cookies no ASP.NET Core.
Impedir ações padrão para eventos em Blazor
aplicativos
Use o @on{EVENT}:preventDefault atributo de diretiva para impedir a ação padrão de
um evento. No exemplo a seguir, a ação padrão de exibir o caractere da chave na caixa
de texto é impedida:
razor
<input value="@_count" @onkeypress="KeyHandler" @onkeypress:preventDefault
/>
Para obter mais informações, consulte Impedir ações padrão.
Interromper a propagação de eventos em
Blazor aplicativos
Use o @on{EVENT}:stopPropagation atributo de diretiva para interromper a propagação
de eventos. No exemplo a seguir, marcar a caixa de seleção impede que eventos de
clique do filho <div> se propaguem para o pai <div> :
razor
<input @bind="_stopPropagation" type="checkbox" />
<div @onclick="OnSelectParentDiv">
<div @onclick="OnSelectChildDiv"
@onclick:stopPropagation="_stopPropagation">
...
</div>
</div>
@code {
private bool _stopPropagation = false;
}
Para obter mais informações, consulte Parar propagação de eventos.
Erros detalhados durante Blazor o
desenvolvimento de aplicativos
Quando um Blazor aplicativo não está funcionando corretamente durante o
desenvolvimento, receber informações detalhadas de erro do aplicativo ajuda na
solução de problemas e na correção do problema. Quando ocorre um erro, Blazor os
aplicativos exibem uma barra de ouro na parte inferior da tela:
Durante o desenvolvimento, a barra de ouro direciona você para o console do
navegador, onde você pode ver a exceção.
Na produção, a barra de ouro notifica o usuário de que ocorreu um erro e
recomenda a atualização do navegador.
Para obter mais informações, consulte Tratar erros em aplicativos ASP.NET CoreBlazor.
Novidades no ASP.NET Core 3.0
Artigo • 10/01/2023 • 16 minutos para o fim da leitura
Este artigo destaca as alterações mais significativas no ASP.NET Core 3.0 com links para
a documentação relevante.
Blazor
Blazoré uma nova estrutura no ASP.NET Core para criar uma interface do usuário da
Web interativa do lado do cliente com o .NET:
Crie interfaces do usuário interativas avançadas usando C# em vez de JavaScript.
Compartilhe a lógica de aplicativo do lado do cliente e do servidor gravada no
.NET.
Renderize a interface do usuário, como HTML e CSS para suporte amplo de
navegadores, incluindo navegadores móveis.
Blazor cenários com suporte da estrutura:
Componentes de interface do usuário reutilizáveis (Razor componentes)
Roteamento do lado do cliente
Layouts de componente
Suporte para injeção de dependência
Formulários e validação
Fornecer Razor componentes em Razor bibliotecas de classes
Interoperabilidade do JavaScript
Para obter mais informações, consulte ASP.NET Core Blazor.
Blazor Server
Blazor separa a lógica de renderização de componentes de como as atualizações de
interface do usuário são aplicadas. O Blazor Server dá suporte para hospedar os
componentes do Razor no servidor em um aplicativo ASP.NET Core. As atualizações da
interface do usuário são tratadas por uma conexão SignalR. Blazor Serverhá suporte no
ASP.NET Core 3.0.
Blazor WebAssembly (versão prévia)
Blazor os aplicativos também podem ser executados diretamente no navegador usando
um runtime do .NET baseado em WebAssembly. Blazor WebAssemblyestá em versão
prévia e não tem suporte no ASP.NET Core 3.0. Blazor WebAssemblyhaverá suporte em
uma versão futura do ASP.NET Core.
Componentes Razor
Blazor os aplicativos são criados a partir de componentes. Os componentes são partes
autossuficientes da interface do usuário (interface do usuário), como uma página, caixa
de diálogo ou formulário. Os componentes são classes .NET normais que definem a
lógica de renderização da interface do usuário e os manipuladores de eventos do lado
do cliente. Você pode criar aplicativos Web interativos avançados sem JavaScript.
Os componentes em Blazor normalmente são criados usando Razor sintaxe, uma
mistura natural de HTML e C#. Razor os componentes são semelhantes aos Razor
modos de exibição Pages e MVC, pois ambos usam Razor. Ao contrário das páginas e
exibições, que se baseiam em um modelo de solicitação-resposta, os componentes são
usados especificamente para lidar com a composição da interface do usuário.
gRPC
gRPC :
É uma estrutura RPC popular e de alto desempenho (chamada de procedimento
remoto).
Oferece uma abordagem de primeiro contrato opinativa para o desenvolvimento
de API.
Usa tecnologias modernas como:
HTTP/2 para transporte.
Buffers de protocolo como a linguagem de descrição da interface.
Formato de serialização binária.
Fornece recursos como:
Autenticação
Streaming bidirecional e controle de fluxo.
Cancelamento e tempos limite.
A funcionalidade gRPC no ASP.NET Core 3.0 inclui:
Grpc.AspNetCore : uma estrutura ASP.NET Core para hospedar serviços gRPC. O
gRPC no ASP.NET Core integra-se aos recursos de ASP.NET Core padrão, como
registro em log, DI (injeção de dependência), autenticação e autorização.
Grpc.Net.Client : um cliente gRPC para .NET Core que se baseia no familiar
HttpClient .
Grpc.Net.ClientFactory : integração do cliente gRPC com HttpClientFactory .
Para obter mais informações, consulte Visão geral do gRPC no .NET.
SignalR
Consulte Atualizar SignalR código para obter instruções de migração. SignalR agora usa
System.Text.Json para serializar/desserializar JSmensagens ON. Consulte Alternar para
Newtonsoft.Json para obter instruções para restaurar o Newtonsoft.Json serializador
baseado em .
Nos clientes JavaScript e .NET para SignalR, o suporte foi adicionado para reconexão
automática. Por padrão, o cliente tenta se reconectar imediatamente e tentar
novamente após 2, 10 e 30 segundos, se necessário. Se o cliente se reconectar com
êxito, ele receberá uma nova ID de conexão. A reconexão automática é aceita:
JavaScript
const connection = new signalR.HubConnectionBuilder()
.withUrl("/chathub")
.withAutomaticReconnect()
.build();
Os intervalos de reconexão podem ser especificados passando uma matriz de durações
baseadas em milissegundos:
JavaScript
.withAutomaticReconnect([0, 3000, 5000, 10000, 15000, 30000])
//.withAutomaticReconnect([0, 2000, 10000, 30000]) The default intervals.
Uma implementação personalizada pode ser passada para controle total dos intervalos
de reconexão.
Se a reconexão falhar após o último intervalo de reconexão:
O cliente considera que a conexão está offline.
O cliente para de tentar se reconectar.
Durante as tentativas de reconexão, atualize a interface do usuário do aplicativo para
notificar o usuário de que a reconexão está sendo tentada.
Para fornecer comentários da interface do usuário quando a conexão for interrompida, a
API do SignalR cliente foi expandida para incluir os seguintes manipuladores de eventos:
onreconnecting : dá aos desenvolvedores a oportunidade de desabilitar a interface
do usuário ou informar aos usuários que o aplicativo está offline.
onreconnected : dá aos desenvolvedores a oportunidade de atualizar a interface do
usuário depois que a conexão for restabelecida.
O código a seguir usa onreconnecting para atualizar a interface do usuário ao tentar se
conectar:
JavaScript
connection.onreconnecting((error) => {
const status = `Connection lost due to error "${error}". Reconnecting.`;
document.getElementById("messageInput").disabled = true;
document.getElementById("sendButton").disabled = true;
document.getElementById("connectionStatus").innerText = status;
});
O código a seguir usa onreconnected para atualizar a interface do usuário na conexão:
JavaScript
connection.onreconnected((connectionId) => {
const status = `Connection reestablished. Connected.`;
document.getElementById("messageInput").disabled = false;
document.getElementById("sendButton").disabled = false;
document.getElementById("connectionStatus").innerText = status;
});
SignalR 3.0 e posterior fornece um recurso personalizado para manipuladores de
autorização quando um método de hub requer autorização. O recurso é uma instância
do HubInvocationContext . O HubInvocationContext inclui:
HubCallerContext
Nome do método hub que está sendo invocado.
Argumentos para o método hub.
Considere o exemplo a seguir de um aplicativo de sala de chat que permite a entrada de
várias organizações por meio do Azure Active Directory. Qualquer pessoa com uma
conta microsoft pode entrar no chat, mas apenas membros da organização proprietária
podem proibir usuários ou exibir históricos de chat dos usuários. O aplicativo pode
restringir determinadas funcionalidades de usuários específicos.
C#
public class DomainRestrictedRequirement :
AuthorizationHandler<DomainRestrictedRequirement, HubInvocationContext>,
IAuthorizationRequirement
{
protected override Task
HandleRequirementAsync(AuthorizationHandlerContext context,
DomainRestrictedRequirement requirement,
HubInvocationContext resource)
{
if (context.User?.Identity?.Name == null)
{
return Task.CompletedTask;
}
if (IsUserAllowedToDoThis(resource.HubMethodName,
context.User.Identity.Name))
{
context.Succeed(requirement);
}
return Task.CompletedTask;
}
private bool IsUserAllowedToDoThis(string hubMethodName, string
currentUsername)
{
if (hubMethodName.Equals("banUser",
StringComparison.OrdinalIgnoreCase))
{
return currentUsername.Equals("
[email protected]",
StringComparison.OrdinalIgnoreCase);
}
return currentUsername.EndsWith("@jabbr.net",
StringComparison.OrdinalIgnoreCase));
}
}
No código anterior, DomainRestrictedRequirement serve como um personalizado
IAuthorizationRequirement . Como o HubInvocationContext parâmetro de recurso está
sendo passado, a lógica interna pode:
Inspecione o contexto no qual o Hub está sendo chamado.
Tome decisões sobre como permitir que o usuário execute métodos de Hub
individuais.
Métodos de Hub Individuais podem ser marcados com o nome da política que o código
verifica em tempo de execução. À medida que os clientes tentam chamar métodos de
Hub individuais, o DomainRestrictedRequirement manipulador executa e controla o
acesso aos métodos. Com base na maneira como os DomainRestrictedRequirement
controles acessam:
Todos os usuários conectados podem chamar o SendMessage método .
Somente os usuários que fizeram logon com um @jabbr.net endereço de email
podem exibir os históricos dos usuários.
Somente
[email protected] os usuários podem proibir usuários da sala de chat.
C#
[Authorize]
public class ChatHub : Hub
{
public void SendMessage(string message)
{
}
[Authorize("DomainRestricted")]
public void BanUser(string username)
{
}
[Authorize("DomainRestricted")]
public void ViewUserHistory(string username)
{
}
}
A criação da DomainRestricted política pode envolver:
No Startup.cs , adicionando a nova política.
Forneça o requisito personalizado DomainRestrictedRequirement como um
parâmetro.
Registrando-se DomainRestricted com o middleware de autorização.
C#
services
.AddAuthorization(options =>
{
options.AddPolicy("DomainRestricted", policy =>
{
policy.Requirements.Add(new DomainRestrictedRequirement());
});
});
SignalR os hubs usam o Roteamento de Ponto de Extremidade. SignalR A conexão do
hub foi feita explicitamente:
C#
app.UseSignalR(routes =>
{
routes.MapHub<ChatHub>("hubs/chat");
});
Na versão anterior, os desenvolvedores precisavam conectar controladores, Razor
páginas e hubs em uma variedade de locais. A conexão explícita resulta em uma série
de segmentos de roteamento quase idênticos:
C#
app.UseSignalR(routes =>
{
routes.MapHub<ChatHub>("hubs/chat");
});
app.UseRouting(routes =>
{
routes.MapRazorPages();
});
SignalR Os hubs 3.0 podem ser roteados por meio do roteamento de ponto de
extremidade. Com o roteamento de ponto de extremidade, normalmente todo o
roteamento pode ser configurado em UseRouting :
C#
app.UseRouting(routes =>
{
routes.MapRazorPages();
routes.MapHub<ChatHub>("hubs/chat");
});
ASP.NET Core 3.0 SignalR adicionado:
Streaming de cliente para servidor. Com o streaming de cliente para servidor, os
métodos do lado do servidor podem usar instâncias de um IAsyncEnumerable<T> ou
ChannelReader<T> . No seguinte exemplo de C#, o UploadStream método no Hub
receberá um fluxo de cadeias de caracteres do cliente:
C#
public async Task UploadStream(IAsyncEnumerable<string> stream)
{
await foreach (var item in stream)
{
// process content
}
}
Os aplicativos cliente .NET podem passar uma IAsyncEnumerable<T> instância ou
ChannelReader<T> como o stream argumento do UploadStream método Hub acima.
Depois que o for loop for concluído e a função local for encerrada, a conclusão do
fluxo será enviada:
C#
async IAsyncEnumerable<string> clientStreamData()
{
for (var i = 0; i < 5; i++)
{
var data = await FetchSomeData();
yield return data;
}
}
await connection.SendAsync("UploadStream", clientStreamData());
Os aplicativos cliente JavaScript usam o SignalR Subject (ou um Assunto RxJS ) para o
stream argumento do UploadStream método Hub acima.
JavaScript
let subject = new signalR.Subject();
await connection.send("StartStream", "MyAsciiArtStream", subject);
O código JavaScript pode usar o subject.next método para manipular cadeias de
caracteres conforme elas são capturadas e prontas para serem enviadas ao servidor.
JavaScript
subject.next("example");
subject.complete();
Usando código como os dois snippets anteriores, experiências de streaming em tempo
real podem ser criadas.
Nova JSserialização ON
ASP.NET Core 3.0 agora usa System.Text.Json por padrão para JSserialização ON:
Lê e grava JSON de forma assíncrona.
É otimizado para texto UTF-8.
Normalmente, um desempenho mais alto do que Newtonsoft.Json .
Para adicionar Json.NET ao ASP.NET Core 3.0, consulte Adicionar suporte ao formato ON
baseado em JSNewtonsoft.Json.
Novas Razor diretivas
A lista a seguir contém novas Razor diretivas:
@attribute: a @attribute diretiva aplica o atributo determinado à classe da página
ou exibição gerada. Por exemplo, @attribute [Authorize] .
@implements: a @implements diretiva implementa uma interface para a classe
gerada. Por exemplo, @implements IDisposable .
IdentityO Server4 dá suporte à autenticação e
autorização para APIs Web e SPAs
ASP.NET Core 3.0 oferece autenticação em SPAs (Aplicativos de Página Única) usando o
suporte para autorização de API Web. Identity ASP.NET Core para autenticar e
armazenar usuários é combinado com Identityo Server4 para implementar o OpenID
Connect.
IdentityServer4 é uma estrutura OpenID Connect e OAuth 2.0 para ASP.NET Core 3.0. Ele
habilita os seguintes recursos de segurança:
Autenticação como serviço (AaaS)
SSO (logon único) em vários tipos de aplicativo
Controle de acesso para APIs
Gateway de Federação
Para obter mais informações, consulte a documentação do IdentityServer4 ou
Autenticação e autorização para SPAs.
Autenticação De certificado e Kerberos
A autenticação de certificado requer:
Configurando o servidor para aceitar certificados.
Adicionando o middleware de autenticação no Startup.Configure .
Adicionando o serviço de autenticação de certificado no
Startup.ConfigureServices .
C#
public void ConfigureServices(IServiceCollection services)
{
services.AddAuthentication(
CertificateAuthenticationDefaults.AuthenticationScheme)
.AddCertificate();
// Other service configuration removed.
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
app.UseAuthentication();
// Other app configuration removed.
}
As opções de autenticação de certificado incluem a capacidade de:
Aceite certificados autoassinados.
Verifique se há revogação de certificado.
Verifique se o certificado oferecido tem os sinalizadores de uso corretos.
Uma entidade de usuário padrão é construída com base nas propriedades do
certificado. A entidade de segurança do usuário contém um evento que permite
complementar ou substituir a entidade de segurança. Para obter mais informações,
consulte Configurar a autenticação de certificado no ASP.NET Core.
A Autenticação do Windows foi estendida para Linux e macOS. Nas versões anteriores, a
Autenticação do Windows era limitada ao IIS e HTTP.sys. No ASP.NET Core 3.0, Kestrel
tem a capacidade de usar Negotiate, Kerberos e NTLM no Windows, Linux e macOS
para hosts ingressados no domínio do Windows. Kestrel O suporte a esses esquemas de
autenticação é fornecido pelo pacote NuGet
Microsoft.AspNetCore.Authentication.Negotiate . Assim como acontece com os
outros serviços de autenticação, configure o aplicativo de autenticação em todo o e
configure o serviço:
C#
public void ConfigureServices(IServiceCollection services)
{
services.AddAuthentication(NegotiateDefaults.AuthenticationScheme)
.AddNegotiate();
// Other service configuration removed.
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
app.UseAuthentication();
// Other app configuration removed.
}
Requisitos de host:
Os hosts do Windows devem ter SPNs ( Nomes de Entidade de Serviço )
adicionados à conta de usuário que hospeda o aplicativo.
Os computadores Linux e macOS devem ser ingressados no domínio.
Os SPNs devem ser criados para o processo da Web.
Os arquivos keytab devem ser gerados e configurados no computador host.
Para obter mais informações, consulte Configurar a Autenticação do Windows no
ASP.NET Core.
Alterações de modelo
Os modelos de interface do usuário da Web (Razor Páginas, MVC com controlador e
exibições) foram removidos:
A cookie interface do usuário de consentimento não está mais incluída. Para
habilitar o cookie recurso de consentimento em um aplicativo gerado por modelo
ASP.NET Core 3.0, confira Suporte ao RGPD (Regulamento Geral sobre a Proteção
de Dados) em ASP.NET Core.
Scripts e ativos estáticos relacionados agora são referenciados como arquivos
locais em vez de usar CDNs. Para obter mais informações, consulte Scripts e ativos
estáticos relacionados agora são referenciados como arquivos locais em vez de
usar CDNs com base no ambiente atual (dotnet/AspNetCore.Docs #14350) .
O modelo Angular atualizado para usar Angular 8.
O Razor modelo de RCL (biblioteca de classes) usa como padrão o Razor
desenvolvimento de componentes. Uma nova opção de modelo no Visual Studio
fornece suporte de modelo para páginas e exibições. Ao criar uma RCL a partir do
modelo em um shell de comando, passe a opção --support-pages-and-views ( dotnet
new razorclasslib --support-pages-and-views ).
Host Genérico
Os modelos do ASP.NET Core 3.0 usam o Host Genérico do .NET em ASP.NET Core.
Versões anteriores usavam WebHostBuilder. O uso do Host Genérico do .NET Core
(HostBuilder) fornece uma melhor integração de aplicativos ASP.NET Core com outros
cenários de servidor que não são específicos da Web. Para obter mais informações,
consulte HostBuilder substitui WebHostBuilder.
Configuração do host
Antes do lançamento do ASP.NET Core 3.0, variáveis de ambiente prefixadas com
ASPNETCORE_ eram carregadas para a configuração de host do Host da Web. Na 3.0,
AddEnvironmentVariables é usado para carregar variáveis de ambiente prefixadas com
DOTNET_ para a configuração do host com CreateDefaultBuilder .
Alterações na injeção de construtor de inicialização
O Host Genérico dá suporte apenas aos seguintes tipos para Startup injeção de
construtor:
IHostEnvironment
IWebHostEnvironment
IConfiguration
Todos os serviços ainda podem ser injetados diretamente como argumentos para o
Startup.Configure método . Para obter mais informações, consulte Host Genérico
restringe a injeção de construtor de inicialização (aspnet/Announcements #353) .
Kestrel
Kestrel A configuração foi atualizada para a migração para o Host Genérico. Na
versão 3.0, Kestrel é configurado no construtor de host da Web fornecido pelo
ConfigureWebHostDefaults .
Os adaptadores de Kestrel conexão foram removidos e substituídos pelo
Middleware de Conexão, que é semelhante ao Middleware HTTP no pipeline de
ASP.NET Core, mas para conexões de nível inferior.
A Kestrel camada de transporte foi exposta como uma interface pública no
Connections.Abstractions .
A ambiguidade entre cabeçalhos e trailers foi resolvida movendo cabeçalhos à
direita para uma nova coleção.
APIs de E/S síncronas, como HttpRequest.Body.Read , são uma fonte comum de
fome de thread que leva a falhas de aplicativo. Na versão 3.0, AllowSynchronousIO
é desabilitado por padrão.
Para obter mais informações, consulte Migrar de ASP.NET Core 2.2 para 3.0.
HTTP/2 habilitado por padrão
O HTTP/2 está habilitado por padrão no Kestrel para pontos de extremidade HTTPS. O
suporte a HTTP/2 para IIS ou HTTP.sys é habilitado quando compatível com o sistema
operacional.
EventCounters na solicitação
O EventSource de Hospedagem, Microsoft.AspNetCore.Hosting , emite os seguintes
novos EventCounter tipos relacionados a solicitações de entrada:
requests-per-second
total-requests
current-requests
failed-requests
Roteamento de ponto de extremidade
O Roteamento de Ponto de Extremidade, que permite que estruturas (por exemplo,
MVC) funcionem bem com middleware, é aprimorado:
A ordem do middleware e dos pontos de extremidade é configurável no pipeline
de processamento de solicitação do Startup.Configure .
Os pontos de extremidade e o middleware compõem-se bem com outras
tecnologias baseadas em ASP.NET Core, como verificações de integridade.
Os pontos de extremidade podem implementar uma política, como CORS ou
autorização, no middleware e no MVC.
Filtros e atributos podem ser colocados em métodos em controladores.
Saiba mais em Roteamento no ASP.NET Core.
Verificações de Integridade
As Verificações de Integridade usam o roteamento de ponto de extremidade com o
Host Genérico. Em Startup.Configure , chame MapHealthChecks no construtor de ponto
de extremidade com a URL do ponto de extremidade ou o caminho relativo:
C#
app.UseEndpoints(endpoints =>
{
endpoints.MapHealthChecks("/health");
});
Os pontos de extremidade de Verificações de Integridade podem:
Especifique um ou mais hosts/portas permitidos.
Exigir autorização.
Exigir CORS.
Para obter mais informações, consulte os seguintes artigos:
Migrar do ASP.NET Core 2.2 para o 3.0
Verificações de integridade no ASP.NET Core
Pipes em HttpContext
Agora é possível ler o corpo da solicitação e gravar o corpo da resposta usando a
System.IO.Pipelines API. A HttpRequest.BodyReader propriedade fornece um PipeReader
que pode ser usado para ler o corpo da solicitação. A HttpResponse.BodyWriter
propriedade fornece um PipeWriter que pode ser usado para gravar o corpo da
resposta. HttpRequest.BodyReader é um análogo do HttpRequest.Body fluxo.
HttpResponse.BodyWriter é um análogo do HttpResponse.Body fluxo.
Relatórios de erros aprimorados no IIS
Os erros de inicialização ao hospedar aplicativos ASP.NET Core no IIS agora produzem
dados de diagnóstico mais avançados. Esses erros são relatados ao Log de Eventos do
Windows com rastreamentos de pilha sempre que aplicável. Além disso, todos os avisos,
erros e exceções sem tratamento são registrados no Log de Eventos do Windows.
SDK de Trabalho e Serviço de Trabalho
O .NET Core 3.0 apresenta o novo modelo de aplicativo do Serviço de Trabalho. Este
modelo fornece um ponto de partida para escrever serviços de longa execução no .NET
Core.
Para obter mais informações, consulte:
Trabalhos do .NET Core como Serviços windows
Tarefas em segundo plano com serviços hospedados no ASP.NET Core
Hospedar o ASP.NET Core em um serviço Windows
Melhorias de middleware de cabeçalhos
encaminhados
Nas versões anteriores do ASP.NET Core, chamar UseHsts e UseHttpsRedirection era
problemático quando implantado em um Linux do Azure ou atrás de qualquer proxy
reverso diferente do IIS. A correção para versões anteriores está documentada em
Encaminhar o esquema para proxies reversos linux e não IIS.
Esse cenário é corrigido no ASP.NET Core 3.0. O host habilita o Middleware cabeçalhos
encaminhados quando a ASPNETCORE_FORWARDEDHEADERS_ENABLED variável de ambiente é
definida como true . ASPNETCORE_FORWARDEDHEADERS_ENABLED é definido como true em
nossas imagens de contêiner.
Aprimoramentos de desempenho
ASP.NET Core 3.0 inclui muitos aprimoramentos que reduzem o uso de memória e
melhoram a taxa de transferência:
Redução no uso de memória ao usar o contêiner de injeção de dependência
interno para serviços com escopo.
Redução de alocações em toda a estrutura, incluindo cenários de middleware e
roteamento.
Redução no uso de memória para conexões WebSocket.
Redução de memória e melhorias de taxa de transferência para conexões HTTPS.
Novo serializador ON otimizado e totalmente assíncrono JS.
Redução no uso de memória e melhorias de taxa de transferência na análise de
formulários.
ASP.NET Core 3.0 só é executado no .NET Core
3.0
A partir do ASP.NET Core 3.0, .NET Framework não é mais uma estrutura de destino com
suporte. Projetos direcionados .NET Framework podem continuar de forma totalmente
compatível usando a versão do .NET Core 2.1 LTS . A maioria dos pacotes relacionados
ASP.NET Core 2.1.x terá suporte indefinidamente, além do período lts de três anos para
o .NET Core 2.1.
Para obter informações de migração, consulte Portar seu código de .NET Framework
para o .NET Core.
Usar a estrutura compartilhada ASP.NET Core
A estrutura compartilhada ASP.NET Core 3.0, contida no metapacote
Microsoft.AspNetCore.App, não requer mais um elemento explícito <PackageReference
/> no arquivo de projeto. A estrutura compartilhada é referenciada automaticamente ao
usar o Microsoft.NET.Sdk.Web SDK no arquivo de projeto:
XML
<Project Sdk="Microsoft.NET.Sdk.Web">
Assemblies removidos da estrutura
compartilhada ASP.NET Core
Os assemblies mais notáveis removidos da estrutura compartilhada ASP.NET Core 3.0
são:
Newtonsoft.Json (Json.NET). Para adicionar Json.NET ao ASP.NET Core 3.0,
consulte Adicionar suporte ao formato ON baseado em JSNewtonsoft.Json.
ASP.NET Core 3.0 apresenta System.Text.Json para leitura e gravação JSon. Para
obter mais informações, consulte Nova JSserialização ON neste documento.
Entity Framework Core
Para obter uma lista completa de assemblies removidos da estrutura compartilhada,
consulte Assemblies sendo removidos do Microsoft.AspNetCore.App 3.0 . Para obter
mais informações sobre a motivação dessa alteração, consulte Alterações interruptivas
em Microsoft.AspNetCore.App na versão 3.0 e Uma primeira olhada nas alterações
que estão chegando no ASP.NET Core 3.0 .
Novidades do ASP.NET Core 2.2
Artigo • 10/01/2023 • 6 minutos para o fim da leitura
Este artigo destaca as alterações mais significativas no ASP.NET Core 2.2, com links para
a documentação relevante.
Convenções de analisadores & de OpenAPI
OpenAPI (anteriormente conhecido como Swagger) é uma especificação independente
de linguagem para descrever REST APIs. O ecossistema do Open API tem ferramentas
que permitem descobrir, testar e produzir o código do cliente usando a especificação. O
suporte para gerar e visualizar documentos OpenAPI no ASP.NET Core MVC é fornecido
por meio de projetos orientados pela comunidade, como NSwag e
Swashbuckle.AspNetCore . O ASP.NET Core 2.2 fornece ferramentas e experiências de
runtime aprimoradas para a criação de documentos do OpenAPI.
Para saber mais, consulte os recursos a seguir:
Usar os analisadores da API Web
Usar convenções de API Web
ASP.NET Core 2.2.0-preview1: Analisadores & de OpenAPI Convenções
Suporte de detalhes do problema
O ASP.NET Core 2.1 introduziu o ProblemDetails , com base na especificação RFC
7807 para transmitir os detalhes de um erro com uma Resposta HTTP. No 2.2,
ProblemDetails é a resposta padrão para códigos de erro do cliente em controladores
atribuídos com ApiControllerAttribute . Um IActionResult que retorna um código de
status de erro do cliente (4xx) retorna um corpo ProblemDetails . O resultado também
inclui uma ID de correlação que pode ser usada para correlacionar o erro usando logs
de solicitação. Para erros do cliente, ProducesResponseType usa como padrão
ProblemDetails como o tipo de resposta. Isso é documentado na saída do
OpenAPI/Swagger gerada com o NSwag ou o Swashbuckle.AspNetCore.
Roteamento de ponto de extremidade
O ASP.NET Core 2.2 usa um novo sistema de roteamento de ponto de extremidade para
expedição aprimorada de solicitações. As alterações incluem novos membros da API de
geração de link e transformadores de parâmetro de rota.
Para saber mais, consulte os recursos a seguir:
Roteamento de ponto de extremidade no 2.2
Transformadores de parâmetro de rota (confira a seção Roteamento)
Diferenças entre o roteamento baseado em IRouter e em ponto de extremidade
Verificações de integridade
Um novo serviço de verificações de integridade facilita o uso do ASP.NET Core em
ambientes que exigem verificações de integridade, como o Kubernetes. As verificações
de integridade incluem middleware e um conjunto de bibliotecas que definem um
serviço e uma abstração IHealthCheck .
As verificações de integridade são usadas por um orquestrador de contêineres ou um
balanceador de carga para determinar rapidamente se um sistema está respondendo às
solicitações normalmente. Um orquestrador de contêineres pode responder a uma
verificação de integridade com falha interrompendo uma implantação sem interrupção
ou reiniciando um contêiner. Um balanceador de carga pode responder a uma
verificação de integridade encaminhando o tráfego para fora da instância com falha do
serviço.
As verificações de integridade são expostas por um aplicativo como um ponto de
extremidade HTTP usado por sistemas de monitoramento. As verificações de
integridade podem ser configuradas para uma variedade de cenários de monitoramento
em tempo real e sistemas de monitoramento. O serviço de verificações de integridade é
integrado ao projeto BeatPulse . que facilita a adição de verificações para dezenas de
sistemas e dependências populares.
Para obter mais informações, confira Verificações de integridade no ASP.NET Core.
HTTP/2 em Kestrel
O ASP.NET Core 2.2 adiciona suporte ao HTTP/2.
O HTTP/2 é uma revisão principal do protocolo HTTP. Os recursos notáveis do HTTP/2
incluem:
Suporte para compactação de cabeçalho.
Fluxos totalmente multiplexados em uma única conexão.
Embora HTTP/2 preserve a semântica do HTTP (por exemplo, cabeçalhos e métodos
HTTP), é uma alteração interruptiva de HTTP/1.x sobre como os dados são enquadrados
e enviados entre o cliente e o servidor.
Como consequência dessa alteração no enquadramento, os servidores e os clientes
precisam negociar a versão de protocolo usada. O recurso ALPN (Negociação de
Protocolo da Camada de Aplicativo) é uma extensão TLS com a qual o servidor e o
cliente podem negociar a versão de protocolo usada como parte do handshake TLS.
Embora seja possível ter um conhecimento prévio entre o servidor e o cliente sobre o
protocolo, todos os principais navegadores dão suporte ALPN como a única maneira de
estabelecer uma conexão HTTP/2.
Para obter mais informações, confira Suporte ao HTTP/2.
Configuração de Kestrel
Em versões anteriores do ASP.NET Core, Kestrel as opções são configuradas chamando
UseKestrel . Na versão 2.2, Kestrel as opções são configuradas chamando
ConfigureKestrel no construtor de host. Essa alteração resolve um problema com a
ordem dos registros IServer para a hospedagem em processo. Para saber mais,
consulte os recursos a seguir:
Atenuar conflitos do UseIIS
Configurar Kestrel opções de servidor com ConfigurarKestrel
Hospedagem em processo do IIS
Em versões anteriores do ASP.NET Core, o IIS funciona como um proxy reverso. No 2.2,
o Módulo do ASP.NET Core pode inicializar o CoreCLR e hospedar um aplicativo dentro
do processo de trabalho do IIS (w3wp.exe). A hospedagem em processo fornece ganhos
de desempenho e diagnóstico durante a execução com o IIS.
Para obter mais informações, confira Hospedagem em processo para IIS.
SignalR Cliente Java
ASP.NET Core 2.2 apresenta um Cliente Java para SignalR. Esse cliente dá suporte à
conexão com um servidor ASP.NET Core SignalR do código Java, incluindo aplicativos
Android.
Para obter mais informações, consulte ASP.NET Core SignalR cliente Java.
Melhorias do CORS
Em versões anteriores do ASP.NET Core, o Middleware do CORS permite o envio dos
cabeçalhos Accept , Accept-Language , Content-Language e Origin , independentemente
dos valores configurados em CorsPolicy.Headers . No 2.2, uma correspondência de
política do Middleware do CORS só é possível quando os cabeçalhos enviados em
Access-Control-Request-Headers corresponder exatamente aos cabeçalhos indicados
em WithHeaders .
Para obter mais informações, confira Middleware do CORS.
Compactação de resposta
O ASP.NET Core 2.2 pode compactar respostas com o formato de compactação Brotli .
Para obter mais informações, confira O middleware de compactação de resposta dá
suporte à compactação Brotli.
Modelos de projeto
Os modelos de projeto Web ASP.NET Core foram atualizados para o Bootstrap 4 eo
Angular 6 . A nova aparência é visualmente mais simples e facilita a visualização das
estruturas importantes do aplicativo.
Desempenho de validação
O sistema de validação do MVC foi projetado para ser extensível e flexível, permitindo
que você determine por solicitação quais validadores se aplicam a um determinado
modelo. Isso é ótimo para a criação de provedores de validação complexa. No entanto,
no caso mais comum, um aplicativo usa apenas os validadores internos e não exige essa
flexibilidade extra. Validadores internos incluem DataAnnotations como [Required] e
[StringLength], e IValidatableObject .
No ASP.NET Core 2.2, o MVC poderá causar um curto-circuito na validação se ele
determinar que um grafo de modelo fornecido não exige validação. Ignorar a validação
resulta em melhorias significativas ao validar modelos que não podem ou não têm
nenhum validador. Isso inclui objetos, como coleções de primitivos (como byte[] ,
string[] , Dictionary<string, string> ), ou grafos de objeto complexo sem muitos
validadores.
Desempenho do Cliente HTTP
No ASP.NET Core 2.2, o desempenho do SocketsHttpHandler foi aprimorado, reduzindo
a contenção de bloqueio do pool de conexão. Para aplicativos que fazem muitas
solicitações HTTP de saída, como algumas arquiteturas de microsserviços, a taxa de
transferência foi aprimorada. Sob carga, a taxa de transferência do HttpClient pode ser
melhorada em até 60% no Linux e 20% no Windows.
Para obter mais informações, confira a solicitação de pull que fez essa melhoria .
Informações adicionais
Para obter a lista completa de alterações, confira as Notas sobre a versão do ASP.NET
Core 2.2 .
Novidades do ASP.NET Core 2.1
Artigo • 10/01/2023 • 6 minutos para o fim da leitura
Este artigo destaca as alterações mais significativas no ASP.NET Core 2.1, com links para
a documentação relevante.
SignalR
SignalRfoi reescrito para ASP.NET Core 2.1.
SignalR ASP.NET Core inclui uma série de melhorias:
Um modelo de expansão simplificado.
Um novo cliente JavaScript sem dependência jQuery.
Um novo protocolo binário compacto com base em MessagePack.
Suporte para protocolos personalizados.
Um novo modelo de resposta de transmissão.
Suporte para clientes com base em WebSockets básicos.
Para obter mais informações, consulte ASP.NET Core SignalR.
Razor bibliotecas de classes
ASP.NET Core 2.1 facilita a compilação e a inclusão Razorda interface do usuário
baseada em uma biblioteca e compartilhá-la em vários projetos. O novo Razor SDK
permite a criação de Razor arquivos em um projeto de biblioteca de classes que pode
ser empacotado em um pacote NuGet. Exibições e páginas em bibliotecas são
descobertas automaticamente e podem ser substituídas pelo aplicativo. Integrando a
Razor compilação ao build:
O tempo de inicialização do aplicativo é significativamente mais rápido.
Atualizações rápidas para Razor exibições e páginas em runtime ainda estão
disponíveis como parte de um fluxo de trabalho de desenvolvimento iterativo.
Para obter mais informações, consulte Criar interface do usuário reutilizável usando o
Razor projeto biblioteca de classes.
Identity Scaffolding da biblioteca & de
interface do usuário
ASP.NET Core 2.1 fornece ASP.NET Core Identity como uma Razor biblioteca de classes.
Os aplicativos que incluem Identity podem aplicar o novo Identity scaffolder para
adicionar seletivamente o código-fonte contido na IdentityRazor RCL (Biblioteca de
Classes). Talvez você queira gerar o código-fonte para que você possa modificar o
código e alterar o comportamento. Por exemplo, você pode instruir o scaffolder a gerar
o código usado no registro. O código gerado tem precedência sobre o mesmo código
na Identity RCL.
Aplicativos que não incluem autenticação podem aplicar a Identity scaffolder para
adicionar o pacote RCL Identity . Você tem a opção de selecionar Identity o código a ser
gerado.
Para obter mais informações, consulte Scaffold Identity em projetos ASP.NET Core.
HTTPS
Com o foco cada vez maior em segurança e privacidade, é importante habilitar HTTPS
para aplicativos Web. A imposição de HTTPS está se tornando cada vez mais rígida na
Web. Sites que não usam HTTPS são considerados inseguros. Navegadores (Chrome,
Mozilla) estão começando a impor o uso de recursos Web em um contexto de seguro. O
RGPD requer o uso de HTTPS para proteger a privacidade do usuário. Quando usar
HTTPS em produção for fundamental, usar HTTPS no desenvolvimento pode ajudar a
evitar problemas de implantação (por exemplo, links inseguros). O ASP.NET Core 2.1
inclui uma série de melhorias que tornam mais fácil usar HTTPS em desenvolvimento e
configurar HTTPS em produção. Para mais informações, consulte Impor o HTTPS.
Ativado por padrão
Para facilitar o desenvolvimento seguro de sites, o HTTPS agora está habilitado por
padrão. A partir da 2.1, Kestrel escuta https://localhost:5001 quando um certificado de
desenvolvimento local está presente. Um certificado de desenvolvimento é criado:
Como parte da experiência de primeira execução do SDK do .NET Core, quando
você usa o SDK pela primeira vez.
Manualmente usando a nova ferramenta dev-certs .
Execute dotnet dev-certs https --trust para confiar no certificado.
Redirecionamento e imposição de HTTPS
Aplicativos Web geralmente precisam escutar em HTTP e HTTPS, mas, então
redirecionam todo o tráfego HTTP para HTTPS. Na versão 2.1, foi introduzido o
middleware de redirecionamento de HTTPS especializado que redireciona de modo
inteligente com base na presença de portas do servidor associado ou de configuração.
O uso de HTTPS pode ser imposto ainda mais empregando HSTS (Protocolo de
Segurança do Transporte Estrita HTTP). HSTS instrui navegadores a sempre acessarem o
site por meio de HTTPS. O ASP.NET Core 2.1 adiciona middleware HSTS compatível com
opções para idade máxima, subdomínios e a lista de pré-carregamento de HSTS.
Configuração para produção
Em produção, HTTPS precisa ser configurado explicitamente. Na versão 2.1, o esquema
de configuração padrão para a configuração do HTTPS foi Kestrel adicionado. Os
aplicativos podem ser configurados para usar:
Vários pontos de extremidade incluindo as URLs. Para obter mais informações,
consulte Kestrel Implementação do servidor Web: configuração do ponto de
extremidade.
O certificado a ser usado para HTTPS de um arquivo no disco ou de um repositório
de certificados.
GDPR
O ASP.NET Core fornece APIs e modelos para ajudar a atender alguns dos requisitos do
RGPD (Regulamento de Proteção de Dados Geral) da UE . Para obter mais
informações, veja Suporte RGPD no ASP.NET Core. Um aplicativo de exemplo mostra
como usar e permite que você teste a maioria dos pontos de extensão RGPD e APIs
adicionados aos modelos do ASP.NET Core 2.1.
Testes de integração
É introduzido um novo pacote que simplifica a criação e a execução do teste. O pacote
Microsoft.AspNetCore.Mvc.Testing lida com as seguintes tarefas:
Copia o arquivo de dependência (*.deps) do aplicativo testado para a pasta bin do
projeto de teste.
Define a raiz de conteúdo para a raiz do projeto do aplicativo testado para que
arquivos estáticos e páginas/exibições sejam encontrados quando os testes forem
executados.
Fornece a WebApplicationFactory<TEntryPoint> classe para simplificar a
inicialização do aplicativo testado com TestServer.
O teste a seguir usa xUnit para verificar se a página de índice é carregada com um
código de status de êxito e o cabeçalho Content-Type correto:
C#
public class BasicTests
: IClassFixture<WebApplicationFactory<RazorPagesProject.Startup>>
{
private readonly HttpClient _client;
public BasicTests(WebApplicationFactory<RazorPagesProject.Startup>
factory)
{
_client = factory.CreateClient();
}
[Fact]
public async Task GetHomePage()
{
// Act
var response = await _client.GetAsync("/");
// Assert
response.EnsureSuccessStatusCode(); // Status Code 200-299
Assert.Equal("text/html; charset=utf-8",
response.Content.Headers.ContentType.ToString());
}
}
Para obter mais informações, veja o tópico Testes de integração.
[ApiController], ActionResult<T>
O ASP.NET Core 2.1 adiciona novas convenções de programação que facilitam o build
de APIs Web limpas e descritivas. ActionResult<T> é um novo tipo adicionado para
permitir que um aplicativo retorne um tipo de resposta ou qualquer outro resultado da
ação (semelhante a IActionResult), enquanto ainda indica o tipo de resposta. O atributo
[ApiController] também foi adicionado como a maneira de aceitar convenções e
comportamentos específicos da API Web.
Para obter mais informações, veja Criar APIs Web com ASP.NET Core.
IHttpClientFactory
O ASP.NET Core 2.1 inclui um novo serviço IHttpClientFactory que torna mais fácil
configurar e consumir instâncias de HttpClient em aplicativos. O HttpClient já tem o
conceito de delegar manipuladores que podem ser vinculados uns aos outros para
solicitações HTTP de saída. O alocador:
Torna o registro de instâncias de HttpClient por cliente nomeado mais intuitivo.
Implementa um manipulador Polly que permite que políticas Polly sejam usadas
para Retry, CircuitBreakers etc.
Para obter mais informações, veja Iniciar solicitações de HTTP.
Kestrel Configuração de transporte libuv
Com o lançamento do ASP.NET Core 2.1, Kestrelo transporte padrão não é mais
baseado no Libuv, mas sim com base em soquetes gerenciados. Para obter mais
informações, consulte Kestrel Implementação do servidor Web: configuração de
transporte libuv.
Construtor de host genérico
O Construtor de Host Genérico ( HostBuilder ) foi introduzido. Este construtor pode ser
usado para aplicativos que não processam solicitações HTTP (mensagens, tarefas em
segundo plano etc.).
Para saber mais, confira Host Genérico do .NET.
Modelos do SPA atualizados
Os modelos de Aplicativo de Página Única para Angular, React e React com Redux são
atualizados para usar estruturas de projeto padrão e criar sistemas para cada estrutura.
O modelo Angular se baseia na CLI Angular e os modelos React baseiam-se em create-
react-app.
Para obter mais informações, consulte:
Usar Angular com ASP.NET Core
Usar React com ASP.NET Core
Usar o modelo de projeto do React com Redux com o ASP.NET Core
Razor Páginas pesquisam Razor ativos
Na versão 2.1, Razor o Pages pesquisa Razor ativos (como layouts e parciais) nos
seguintes diretórios na ordem listada:
1. Pasta de Páginas atual.
2. /Pages/Shared/
3. /Views/Shared/
Razor Páginas em uma área
Razor As páginas agora dão suporte a áreas. Para ver um exemplo de áreas, crie um
novo Razor aplicativo Web Pages com contas de usuário individuais. Um Razor
aplicativo Web Pages com contas de usuário individuais inclui /Areas/Identity/Pages.
Versão de compatibilidade do MVC
O método SetCompatibilityVersion permite que um aplicativo aceite ou recuse as
possíveis alterações da falha de comportamento introduzidas no ASP.NET Core MVC 2.1
ou posteriores.
Para obter mais informações, consulte Versão de compatibilidade para ASP.NET Core
MVC.
Migrar de 2.0 para 2.1
Veja Migrar do ASP.NET Core 2.0 para 2.1.
Informações adicionais
Para obter uma lista de alterações, vejas as Notas de versão do ASP.NET Core 2.1 .
Novidades do ASP.NET Core 2.0
Artigo • 10/01/2023 • 6 minutos para o fim da leitura
Este artigo destaca as alterações mais significativas no ASP.NET Core 2.0, com links para
a documentação relevante.
Razor Pages
RazorPages é um novo recurso de ASP.NET Core MVC que torna os cenários focados em
página de codificação mais fáceis e produtivos.
Para obter mais informações, consulte a introdução e o tutorial:
Introdução às Razor Páginas
Introdução ao Razor Pages
Metapacote do ASP.NET Core
Um novo metapacote do ASP.NET Core inclui todos os pacotes feitos e com suporte
pelas equipes do ASP.NET Core e do Entity Framework Core, juntamente com as
respectivas dependências internas e de terceiros. Você não precisa mais escolher
recursos individuais do ASP.NET Core por pacote. Todos os recursos estão incluídos no
pacote Microsoft.AspNetCore.All . Os modelos padrão usam este pacote.
Para obter mais informações, consulte Metapacote do Microsoft.AspNetCore.All para
ASP.NET Core 2.0.
Repositório de runtime
Aplicativos que usam o metapacote Microsoft.AspNetCore.All aproveitam
automaticamente o novo repositório de runtime do .NET Core. O repositório contém
todos os ativos de runtime necessários para executar aplicativos ASP.NET Core 2.0.
Quando você usa o metapacote Microsoft.AspNetCore.All , nenhum ativo dos pacotes
NuGet do ASP.NET Core referenciados são implantados com o aplicativo porque eles já
estão no sistema de destino. Os ativos no repositório de runtime também são pré-
compilados para melhorar o tempo de inicialização do aplicativo.
Para obter mais informações, consulte Repositório de runtime
.NET Standard 2.0
Os pacotes do ASP.NET Core 2.0 são direcionados ao .NET Standard 2.0. Os pacotes
podem ser referenciados por outras bibliotecas do .NET Standard 2.0 e podem ser
executados em implementações em conformidade com o .NET Standard 2.0, incluindo o
.NET Core 2.0 e o .NET Framework 4.6.1.
O metapacote Microsoft.AspNetCore.All aborda apenas o .Net Core 2.0 porque ele foi
projetado para ser utilizado com o repositório de runtime do .Net Core 2.0.
Atualização da configuração
Uma instância de IConfiguration é adicionada ao contêiner de serviços por padrão no
ASP.NET Core 2.0. IConfiguration no contêiner de serviços torna mais fácil para
aplicativos recuperarem valores de configuração do contêiner.
Para obter informações sobre o status da documentação planejada, consulte o
problema do GitHub .
Atualização de registro em log
No ASP.NET Core 2.0, o log será incorporado no sistema de DI (injeção de dependência)
por padrão. Você adiciona provedores e configura a Program.cs filtragem no arquivo
em vez de no Startup.cs arquivo. E o ILoggerFactory padrão dá suporte à filtragem de
forma que lhe permite usar uma abordagem flexível para filtragem entre provedores e
filtragem específica do provedor.
Para obter mais informações, consulte Introdução ao registro em log.
Atualização de autenticação
Um novo modelo de autenticação torna mais fácil configurar a autenticação para um
aplicativo usando a DI.
Novos modelos estão disponíveis para configurar a autenticação para aplicativos Web e
APIs Web usando o Azure AD B2C .
Para obter informações sobre o status da documentação planejada, consulte o
problema do GitHub .
atualização de Identity
Facilitamos a criação de APIs Web seguras usando Identity no ASP.NET Core 2.0. Você
pode adquirir tokens de acesso para acessar suas APIs Web usando a MSAL (Biblioteca
de Autenticação da Microsoft) .
Para obter mais informações sobre alterações de autenticação no 2.0, consulte os
seguintes recursos:
Confirmação de conta e de recuperação de senha no ASP.NET Core
Habilitar a geração de código QR para aplicativos de autenticador no ASP.NET
Core
Migrar Autenticação e Identity para ASP.NET Core 2.0
Modelos do SPA
Modelos de projeto de SPA (aplicativo de página único) para Angular, Aurelia,
Knockout.js, React.js e React.js com Redux estão disponíveis. O modelo Angular foi
atualizado para Angular 4. Os modelos Angular e React estão disponíveis por padrão.
Para saber como obter os outros modelos, confira Criar um novo projeto de SPA. Para
obter informações sobre como criar um SPA no ASP.NET Core, consulte Usar serviços
JavaScript para criar aplicativos de página única no ASP.NET Core.
Aprimoramentos Kestrel
O Kestrel servidor Web tem novos recursos que o tornam mais adequado como um
servidor voltado para a Internet. Uma série de opções de configuração de restrição de
servidor serão adicionadas na nova propriedade Limits da classe KestrelServerOptions .
Adicione limites para o seguinte:
Número máximo de conexões de cliente
Tamanho máximo do corpo da solicitação
Taxa de dados mínima do corpo da solicitação
Para obter mais informações, consulte Kestrel Implementação de servidor Web em
ASP.NET Core.
WebListener renomeado para HTTP.sys
Os pacotes Microsoft.AspNetCore.Server.WebListener e Microsoft.Net.Http.Server
foram mesclados em um novo pacote Microsoft.AspNetCore.Server.HttpSys . Os
namespaces foram atualizados para corresponderem.
Para obter mais informações, consulte Implementação do servidor Web HTTP.sys no
ASP.NET Core.
Suporte aprimorado a cabeçalho HTTP
Ao usar o MVC para transmitir um FileStreamResult ou um FileContentResult , agora
você tem a opção de definir uma ETag ou uma data LastModified no conteúdo que
você transmitir. Você pode definir esses valores no conteúdo retornado com código
semelhante ao seguinte:
C#
var data = Encoding.UTF8.GetBytes("This is a sample text from a binary
array");
var entityTag = new EntityTagHeaderValue("\"MyCalculatedEtagValue\"");
return File(data, "text/plain", "downloadName.txt", lastModified:
DateTime.UtcNow.AddSeconds(-5), entityTag: entityTag);
O arquivo retornado aos visitantes tem os cabeçalhos HTTP apropriados para os ETag
valores e LastModified .
Se um visitante do aplicativo solicitar o conteúdo com um cabeçalho de solicitação de
intervalo, o ASP.NET Core reconhecerá a solicitação e lidará com o cabeçalho. Se parte
do conteúdo solicitado puder ser entregue, o ASP.NET Core ignorará a parte em
questão e retornará apenas o conjunto de bytes solicitado. Você não precisa gravar
nenhum manipulador especial em seus métodos para adaptar ou manipular esse
recurso; ele é manipulado automaticamente para você.
Inicialização de hospedagem e o Application
Insights
Ambientes de hospedagem podem injetar dependências de pacote extras e executar
código durante a inicialização do aplicativo, sem que o aplicativo precise tomar uma
dependência explicitamente ou chamar algum método. Esse recurso pode ser usado
para habilitar determinados ambientes para recursos de "esclarecimento" exclusivos
para esse ambiente sem que o aplicativo precise saber antecipadamente.
No ASP.NET Core 2.0, esse recurso é usado para habilitar o diagnóstico do Application
Insights automaticamente durante a depuração no Visual Studio e (depois de optar por
isto) quando em execução nos Serviços de Aplicativos do Azure. Como resultado, os
modelos de projeto não adicionam mais código e pacotes do Application Insights por
padrão.
Para obter informações sobre o status da documentação planejada, consulte o
problema do GitHub .
Uso automático de tokens antifalsificação
O ASP.NET Core sempre ajudou a fazer a codificação HTML do conteúdo por padrão,
mas com a nova versão é necessário um passo adicional para ajudar a impedir ataques
de XSRF (falsificação de solicitação entre sites). O ASP.NET Core agora emitirá tokens
antifalsificação por padrão e os validará em ações de POST de formulário e em páginas
sem configuração adicional.
Para obter mais informações, consulte Impedir ataques de XSRF/CSRF (solicitação
intersite forjada) no ASP.NET Core.
Pré-compilação automática
Razor A pré-compilação de exibição é habilitada durante a publicação por padrão,
reduzindo o tamanho da saída de publicação e o tempo de inicialização do aplicativo.
Para obter mais informações, consulte Razor exibir compilação e pré-compilação em
ASP.NET Core.
Razor suporte para C# 7.1
O Razor mecanismo de exibição foi atualizado para funcionar com o novo compilador
Roslyn. Isso inclui suporte para recursos do C# 7.1 como expressões padrão, nomes de
tupla inferidos e correspondência de padrões com genéricos. Para usar o C# 7.1 em seu
projeto, adicione a seguinte propriedade no arquivo de projeto e, em seguida,
recarregue a solução:
XML
<LangVersion>latest</LangVersion>
Para obter informações sobre o status dos recursos do C# 7.1, consulte o repositório
GitHub do Roslyn .
Outras atualizações de documentação para 2.0
Perfis de publicação do Visual Studio para a implantação do aplicativo ASP.NET
Core
Gerenciamento de chaves
Configurar a autenticação do Facebook
Configurar a autenticação do Twitter
Configurar a autenticação do Google
Configurar a autenticação da conta da Microsoft
Guia de migração
Para obter diretrizes sobre como migrar aplicativos ASP.NET Core 1.x para o ASP.NET
Core 2.0, consulte os seguintes recursos:
Migrar do ASP.NET Core 1.x para o ASP.NET Core 2.0
Migrar Autenticação e Identity para ASP.NET Core 2.0
Informações adicionais
Para obter uma lista de alterações, consulte as Notas de versão do ASP.NET Core 2.0 .
Para se conectar ao progresso e aos planos da equipe de desenvolvimento do ASP.NET
Core, fique ligado no ASP.NET Community Standup .
Novidades do ASP.NET Core 1.1
Artigo • 10/01/2023 • 2 minutos para o fim da leitura
O ASP.NET Core 1.1 inclui os seguintes novos recursos:
Middleware de regravação de URL
Middleware de Cache de Resposta
Componentes de exibição como auxiliares de marcação
Middleware como filtros MVC
CookieProvedor TempData baseado em
Provedor de logs do Serviço de Aplicativo do Azure
Provedor de configuração do Azure Key Vault
Repositórios de chaves da Proteção de Dados de armazenamento do Azure e do
Redis
Servidor WebListener para Windows
Suporte a WebSockets
Escolhendo entre as versões 1.0 e 1.1 do
ASP.NET Core
ASP.NET Core 1.1 tem mais recursos do que ASP.NET Core 1.0. Em geral, recomendamos
o uso da última versão.
Informações adicionais
Notas de versão do ASP.NET Core 1.1.0
Para se conectar ao progresso e aos planos da equipe de desenvolvimento do
ASP.NET Core, fique ligado no ASP.NET Community Standup .
Escolher uma interface do usuário da
Web ASP.NET Core
Artigo • 04/01/2023 • 9 minutos para o fim da leitura
ASP.NET Core é uma estrutura de interface do usuário completa. Escolha quais
funcionalidades combinar que se ajustam às necessidades da interface do usuário da
Web do aplicativo.
Benefícios versus custos da interface do
usuário renderizada por servidor e cliente
Há três abordagens gerais para criar uma interface do usuário da Web moderna com
ASP.NET Core:
Aplicativos que renderizam a interface do usuário do servidor.
Aplicativos que renderizam a interface do usuário no cliente no navegador.
Aplicativos híbridos que aproveitam as abordagens de renderização da interface
do usuário do servidor e do cliente. Por exemplo, a maior parte da interface do
usuário da Web é renderizada no servidor e os componentes renderizados do
cliente são adicionados conforme necessário.
Há benefícios e desvantagens a serem considerados ao renderizar a interface do usuário
no servidor ou no cliente.
Interface do usuário renderizada do servidor
Um aplicativo de interface do usuário da Web que é renderizado no servidor gera
dinamicamente o HTML e o CSS da página no servidor em resposta a uma solicitação de
navegador. A página chega ao cliente pronto para exibição.
Benefícios:
Os requisitos do cliente são mínimos porque o servidor faz o trabalho de geração
de página e lógica:
Ótimo para dispositivos de baixa extremidade e conexões de baixa largura de
banda.
Permite uma ampla variedade de versões do navegador no cliente.
Tempos de carregamento rápidos da página inicial.
Mínimo para nenhum JavaScript para efetuar pull para o cliente.
Flexibilidade de acesso aos recursos do servidor protegido:
Acesso ao banco de dados.
Acesso a segredos, como valores para chamadas à API para o armazenamento
do Azure.
Vantagens da análise de site estático, como a otimização do mecanismo de
pesquisa.
Exemplos de cenários comuns de aplicativos de interface do usuário da Web
renderizados pelo servidor:
Sites dinâmicos, como aqueles que fornecem páginas, dados e formulários
personalizados.
Exiba dados somente leitura, como listas de transações.
Exibir páginas de blog estáticas.
Um sistema de gerenciamento de conteúdo voltado para o público.
Desvantagens:
O custo de computação e o uso de memória estão concentrados no servidor, em
vez de em cada cliente.
As interações do usuário exigem uma viagem de ida e volta ao servidor para gerar
atualizações da interface do usuário.
Interface do usuário renderizada pelo cliente
Um aplicativo renderizado pelo cliente renderiza dinamicamente a interface do usuário
da Web no cliente, atualizando diretamente o DOM do navegador conforme necessário.
Benefícios:
Permite uma interatividade avançada que é quase instantânea, sem a necessidade
de uma viagem de ida e volta para o servidor. A manipulação de eventos e a lógica
da interface do usuário são executadas localmente no dispositivo do usuário com
latência mínima.
Dá suporte a atualizações incrementais, salvando formulários ou documentos
parcialmente concluídos sem que o usuário precise selecionar um botão para
enviar um formulário.
Pode ser projetado para ser executado em um modo desconectado. Atualizações
para o modelo do lado do cliente serão sincronizados novamente com o servidor
depois que uma conexão for restabelecida.
Carga e custo reduzidos do servidor, o trabalho é descarregado para o cliente.
Muitos aplicativos renderizados pelo cliente também podem ser hospedados
como sites estáticos.
Aproveita os recursos do dispositivo do usuário.
Exemplos de interface do usuário da Web renderizada pelo cliente:
Um painel interativo.
Um aplicativo com funcionalidade de arrastar e soltar
Um aplicativo social responsivo e colaborativo.
Desvantagens:
O código para a lógica deve ser baixado e executado no cliente, adicionando ao
tempo de carregamento inicial.
Os requisitos do cliente podem excluir os usuários que têm dispositivos de baixa
extremidade, versões mais antigas do navegador ou conexões de baixa largura de
banda.
Escolher um servidor renderizado ASP.NET Core
solução de interface do usuário
A seção a seguir explica o ASP.NET Core modelos renderizados do servidor de interface
do usuário da Web disponíveis e fornece links para começar. Razor ASP.NET Core Pages
e ASP.NET Core MVC são estruturas baseadas em servidor para criar aplicativos Web
com o .NET.
Razor páginas do ASP.NET Core
Razor Pages é um modelo baseado em página. As preocupações com a interface do
usuário e a lógica de negócios são mantidas separadas, mas dentro da página.
RazorPages é a maneira recomendada de criar novos aplicativos baseados em página ou
em formulário para desenvolvedores novos em ASP.NET Core. RazorO Pages fornece um
ponto de partida mais fácil do que ASP.NET Core MVC.
Razor Benefícios de páginas, além dos benefícios de renderização do servidor:
Crie e atualize rapidamente a interface do usuário. O código da página é mantido
com a página, mantendo as preocupações da interface do usuário e da lógica de
negócios separadas.
Testável e dimensiona para aplicativos grandes.
Mantenha suas páginas ASP.NET Core organizadas de maneira mais simples do
que ASP.NET MVC:
Os modelos de exibição e lógica específicos podem ser mantidos juntos em seu
próprio namespace e diretório.
Grupos de páginas relacionadas podem ser mantidos em seu próprio
namespace e diretório.
Para começar a usar seu primeiro aplicativo ASP.NET Core Razor Pages, consulte
Tutorial: Introdução ao Razor Pages no ASP.NET Core. Para obter uma visão geral
completa do ASP.NET Core Razor Pages, sua arquitetura e benefícios, consulte:
Introdução às Razor páginas no ASP.NET Core.
ASP.NET Core MVC
ASP.NET MVC renderiza a interface do usuário no servidor e usa um padrão de
arquitetura MVC (Model-View-Controller). O padrão MVC separa um aplicativo em três
grupos principais de componentes: Modelos, Exibições e Controladores. As solicitações
do usuário são roteada para um controlador. O controlador é responsável por trabalhar
com o modelo para executar ações do usuário ou recuperar resultados de consultas. O
controlador escolhe a exibição a ser exibida para o usuário e fornece a ele todos os
dados de modelo necessários. O suporte para Razor Pages é criado em ASP.NET Core
MVC.
Benefícios do MVC, além dos benefícios de renderização do servidor:
Com base em um modelo escalonável e maduro para a criação de aplicativos Web
grandes.
Separação clara de preocupações com a máxima flexibilidade.
A separação de responsabilidades do Model-View-Controller garante que o
modelo de negócios possa evoluir sem ser firmemente acoplado a detalhes de
implementação de baixo nível.
Para começar a usar ASP.NET Core MVC, consulte Introdução ao ASP.NET Core MVC.
Para obter uma visão geral da arquitetura e dos benefícios do ASP.NET Core MVC,
confira Visão geral do ASP.NET Core MVC.
Blazor Server
O Blazor é uma estrutura para criar uma interface do usuário web interativa do lado do
cliente com o .NET:
Crie interfaces do usuário interativas avançadas usando C# em vez de JavaScript .
Compartilhe a lógica de aplicativo do lado do cliente e do servidor gravada no
.NET.
Renderize a interface do usuário, como HTML e CSS para suporte amplo de
navegadores, incluindo navegadores móveis.
Integre-se a plataformas de hospedagem modernas, como o Docker.
Crie aplicativos móveis e de área de trabalho híbrida com .NET e Blazor.
Usar o .NET para desenvolvimento web do lado do cliente oferece as seguintes
vantagens:
escreva o código em C# em vez de JavaScript.
Aproveite o ecossistema .NET existente das bibliotecas .NET.
Compartilhe a lógica de aplicativo entre o servidor e o cliente.
Beneficie-se com o desempenho, confiabilidade e segurança do .NET.
Mantenha-se produtivo no Windows, Linux ou macOS com um ambiente de
desenvolvimento, como o Visual Studio ou o Visual Studio Code .
Crie um conjunto comum de linguagens, estruturas e ferramentas que são estáveis,
com recursos avançados e fáceis de usar.
Blazor Serverfornece suporte para hospedar a interface do usuário renderizada pelo
servidor em um aplicativo ASP.NET Core. As atualizações da interface do usuário do
cliente são tratadas em uma SignalR conexão. O runtime permanece no servidor e
manipula a execução do código C# do aplicativo.
Para obter mais informações, consulte modelos de hospedagem ASP.NET Core Blazor e
ASP.NET CoreBlazor. O modelo de hospedagem renderizado pelo Blazor cliente é
descrito na Blazor WebAssembly seção posteriormente neste artigo.
Escolher uma solução de ASP.NET Core
renderizada pelo cliente
A seção a seguir explica brevemente os modelos renderizados do cliente de interface do
usuário da Web ASP.NET Core disponíveis e fornece links para começar.
Blazor WebAssembly
Blazor WebAssembly é uma estrutura spa (aplicativo de página única) para criar
aplicativos Web interativos do lado do cliente com as características gerais descritas na
Blazor Server seção anterior neste artigo.
A execução do código do .NET em navegadores da Web é possibilitada por
WebAssembly (abreviado como wasm ). O WebAssembly é um formato de código de
bytes compacto, otimizado para download rápido e máxima velocidade de execução. O
WebAssembly é um padrão aberto da Web compatível com navegadores da Web sem
plug-ins. Blazor WebAssembly funciona em todos os navegadores da Web modernos,
incluindo os navegadores móveis.
Quando um Blazor WebAssembly aplicativo é criado e executado:
Os arquivos de código C# e do Razor são compilados em assemblies do .NET.
Os assemblies e o runtime do .NET são baixados no navegador.
O Blazor WebAssembly inicializa o runtime do .NET e o configura para carregar os
assemblies no aplicativo. O Blazor WebAssembly runtime usa a interoperabilidade
JavaScript para manipular a manipulação do DOM (Modelo de Objeto de
Documento) e as chamadas à API do navegador.
Para obter mais informações, consulte ASP.NET Core Blazor e modelos de hospedagem
ASP.NET CoreBlazor. O modelo de hospedagem renderizado pelo Blazor servidor é
descrito na Blazor Server seção anterior neste artigo.
ASP.NET Core SPA (Aplicativo de Página Única) com
Estruturas JavaScript, como Angular e React
Crie lógica do lado do cliente para aplicativos ASP.NET Core usando estruturas
JavaScript populares, como Angular ou React . ASP.NET Core fornece modelos de
projeto para Angular e React e também pode ser usado com outras estruturas
JavaScript.
Benefícios de ASP.NET Core SPA com Estruturas JavaScript, além dos benefícios de
renderização do cliente listados anteriormente:
O ambiente de runtime do JavaScript já é fornecido com o navegador.
Grande comunidade e ecossistema maduro.
Crie lógica do lado do cliente para aplicativos ASP.NET Core usando estruturas
popularesJS, como Angular e React.
Desvantagens:
Mais linguagens de codificação, estruturas e ferramentas necessárias.
Difícil compartilhar código para que alguma lógica possa ser duplicada.
Para começar. confira:
Usar Angular com ASP.NET Core
Usar React com ASP.NET Core
Escolha uma solução híbrida: ASP.NET Core
MVC ou Razor Pages plusBlazor
MVC, Razor Pages e Blazor fazem parte da estrutura ASP.NET Core e foram projetados
para serem usados juntos. Razoros componentes podem ser integrados aos Razor
aplicativos Pages e MVC em uma solução ou Blazor Server hospedadaBlazor
WebAssembly. Quando uma exibição ou página é renderizada, os componentes podem
ser pré-gerados ao mesmo tempo.
Benefícios para MVC ou Razor Pages mais Blazor, além dos benefícios do MVC ou Razor
do Pages:
A pré-geração executa componentes Razor no servidor e os renderiza em uma
exibição ou página, o que melhora o tempo de carga percebido do aplicativo.
Adicione interatividade a exibições ou páginas existentes com o Auxiliar de Marca
de Componente.
Para começar a usar ASP.NET Core MVC ou Razor Pages mais Blazor, confira Pré-gerar e
integrar componentes ASP.NET CoreRazor.
Próximas etapas
Para obter mais informações, consulte:
ASP.NET Core Blazor
Modelos de hospedagem do ASP.NET Core Blazor
Pré-renderizar e integrar componentes Razor do ASP.NET Core
Comparar serviços gRPC com APIs HTTP
Tutorial: criar um aplicativo Web Razor
Pages com o ASP.NET Core
Artigo • 02/12/2022 • 2 minutos para o fim da leitura
Esta série de tutoriais explica as noções básicas sobre a criação de um aplicativo Web
Razor Pages.
Para ver uma introdução mais avançada voltada para desenvolvedores familiarizados
com controladores e exibições, confira Introdução ao Razor Pages no ASP.NET Core.
Se não estiver familiarizado com o desenvolvimento de ASP.NET Core e não tiver
certeza de qual solução de interface do usuário da Web do ASP.NET Core atenderá
melhor às suas necessidades, consulte Escolher uma interface do usuário do ASP.NET
Core.
Esta série inclui os seguintes tutoriais:
1. Criar um aplicativo Web Razor Pages
2. Adicionar um modelo a um aplicativo Razor Pages
3. Scaffold (gerar) páginas Razor
4. Trabalhar com um banco de dados
5. Atualizar páginas Razor
6. Adicionar pesquisa
7. Adicionar um novo campo
8. Adicionar validação
No final, você terá um aplicativo que pode exibir e gerenciar um banco de dados de
filmes.
Tutorial: introdução ao Razor Pages no
ASP.NET Core
Artigo • 02/12/2022 • 24 minutos para o fim da leitura
De Rick Anderson
Este é o primeiro tutorial de uma série que ensina os conceitos básicos da criação de um
aplicativo Web ASP.NET Core Razor Pages.
Para obter uma introdução mais avançada voltada para desenvolvedores que estão
familiarizados com controladores e exibições, consulte Introdução às Razor páginas.
Para obter uma introdução em vídeo, consulte Entity Framework Core para iniciantes .
Se não estiver familiarizado com o desenvolvimento de ASP.NET Core e não tiver
certeza de qual solução de interface do usuário da Web do ASP.NET Core atenderá
melhor às suas necessidades, consulte Escolher uma interface do usuário do ASP.NET
Core.
No final deste tutorial, você terá um Razor aplicativo Web Pages que gerencia um banco
de dados de filmes.
Pré-requisitos
Visual Studio
Visual Studio 2022 com a carga de trabalho de desenvolvimento Web e do
ASP.NET.
Criar um aplicativo Web Razor Pages
Visual Studio
Inicie o Visual Studio e selecione Criar um projeto.
Na caixa de diálogo Criar um novo projeto, selecione ASP.NET Core
Aplicativo> WebAvançar.
Na caixa de diálogo Configurar seu novo projeto , insira RazorPagesMovie
para Nome do projeto. É importante nomear o projeto RazorPagesMovie,
incluindo a correspondência da capitalização, para que os namespaces
correspondam quando você copiar e colar o código de exemplo.
Selecione Avançar.
Na caixa de diálogo Informações adicionais:
Selecione .NET 7.0.
Verificar: não usar instruções de nível superior está desmarcada .
Selecione Criar.
O seguinte projeto inicial é criado:
Para obter abordagens alternativas para criar o projeto, consulte Criar um novo
projeto no Visual Studio.
Execute o aplicativo
Visual Studio
Selecione RazorPagesMovie no Gerenciador de Soluções e pressione Ctrl+F5 para
executar sem o depurador.
O Visual Studio exibe a seguinte caixa de diálogo quando um projeto ainda não
está configurado para usar o SSL:
Selecione Sim se você confia no certificado SSL do IIS Express.
A seguinte caixa de diálogo é exibida:
Selecione Sim se você concordar com confiar no certificado de desenvolvimento.
Para obter informações sobre como confiar no navegador Firefox, consulte Firefox
SEC_ERROR_INADEQUATE_KEY_USAGE erro de certificado.
Visual Studio:
Executa o aplicativo, que inicia o Kestrel servidor.
Inicia o navegador padrão em https://localhost:<port> , que exibe a
interface do usuário dos aplicativos. <port> é a porta aleatória atribuída
quando o aplicativo foi criado.
Examinar os arquivos de projeto
As seções a seguir contêm uma visão geral das pastas e arquivos principais do projeto
com os quais você trabalhará em tutoriais posteriores.
Pasta Páginas
Contém Razor páginas e arquivos de suporte. Cada Razor página é um par de arquivos:
Um .cshtml arquivo que tem marcação HTML com código C# usando Razor
sintaxe.
Um .cshtml.cs arquivo que tem código C# que manipula eventos de página.
Arquivos de suporte têm nomes que começam com um sublinhado. Por exemplo, o
_Layout.cshtml arquivo configura elementos de interface do usuário comuns a todas as
páginas. _Layout.cshtml configura o menu de navegação na parte superior da página e
o aviso de direitos autorais na parte inferior da página. Saiba mais em Layout no
ASP.NET Core.
Pasta wwwroot
Contém ativos estáticos, como arquivos HTML, arquivos JavaScript e arquivos CSS. Saiba
mais em Arquivos estáticos no ASP.NET Core.
appsettings.json
Contém dados de configuração, como cadeias de conexão. Para obter mais informações,
consulte Configuração no ASP.NET Core.
Module.vb
Contém o seguinte código:
C#
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
builder.Services.AddRazorPages();
var app = builder.Build();
// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
// The default HSTS value is 30 days. You may want to change this for
production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthorization();
app.MapRazorPages();
app.Run();
As seguintes linhas de código neste arquivo criam um WebApplicationBuilder com
padrões pré-configurados, adicionam Razor suporte ao Pages ao contêiner di (injeção
de dependência) e criam o aplicativo:
C#
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
builder.Services.AddRazorPages();
var app = builder.Build();
A página de exceção do desenvolvedor é habilitada por padrão e fornece informações
úteis sobre exceções. Os aplicativos de produção não devem ser executados no modo
de desenvolvimento porque a página de exceção do desenvolvedor pode vazar
informações confidenciais.
O código a seguir define o ponto de extremidade de exceção como /Error e habilita o
protocolo HSTS quando o aplicativo não está em execução no modo de
desenvolvimento:
C#
// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
// The default HSTS value is 30 days. You may want to change this for
production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
Por exemplo, o código anterior é executado quando o aplicativo está no modo de
produção ou teste. Para obter mais informações, confira Usar vários ambientes no
ASP.NET Core.
O código a seguir habilita vários middlewares:
app.UseHttpsRedirection(); : redireciona solicitações HTTP para HTTPS.
app.UseStaticFiles(); : permite que arquivos estáticos, como HTML, CSS,
imagens e JavaScript sejam atendidos. Saiba mais em Arquivos estáticos no
ASP.NET Core.
app.UseRouting(); : adiciona a correspondência de rotas ao pipeline de
middleware. Para obter mais informações, consulte Roteamento no ASP.NET Core
app.MapRazorPages(); : configura o roteamento de ponto de extremidade para
Razor o Pages.
app.UseAuthorization(); : autoriza um usuário a acessar recursos seguros. Esse
aplicativo não usa autorização, portanto, essa linha pode ser removida.
app.Run(); : executa o aplicativo.
Solução de problemas com o exemplo
concluído
Se você encontrar um problema que não possa resolver, compare seu código com o
projeto concluído. Exibir ou baixar o projeto concluído (como baixar).
Próximas etapas
Próximo: Adicionar um modelo
Parte 2, adicione um modelo a um
Razor aplicativo Pages no ASP.NET Core
Artigo • 08/12/2022 • 48 minutos para o fim da leitura
Neste tutorial, classes são adicionadas para gerenciar filmes em um banco de dados. As
classes de modelo do aplicativo usam o Entity Framework Core (EF Core) para trabalhar
com o banco de dados. EF Core é um mapeador relacional de objeto (O/RM) que
simplifica o acesso a dados. Você escreve as classes de modelo primeiro e EF Core cria o
banco de dados.
As classes de modelo são conhecidas como classes POCO (de "Plain-O ld CLR Objects")
porque não têm uma dependência de EF Core. Elas definem as propriedades dos dados
que são armazenados no banco de dados.
Adicionar um modelo de dados
Visual Studio
1. Em Gerenciador de Soluções, clique com o botão direito do mouse no
Razorprojeto> PagesMovie Adicionar>Nova Pasta. Nomeie a pasta Models .
2. Clique com o botão direito do mouse na Models pasta. Selecione
Adicionar>Classe. Dê à classe o nome Movie.
3. Adicione as seguintes propriedades à classe Movie :
C#
using System.ComponentModel.DataAnnotations;
namespace RazorPagesMovie.Models;
public class Movie
{
public int Id { get; set; }
public string? Title { get; set; }
[DataType(DataType.Date)]
public DateTime ReleaseDate { get; set; }
public string? Genre { get; set; }
public decimal Price { get; set; }
}
A classe Movie contém:
O campo ID é necessário para o banco de dados para a chave primária.
Um atributo [DataType] que especifica o tipo de dados na ReleaseDate
propriedade . Com esse atributo:
O usuário não precisa inserir informações de hora no campo de data.
Somente a data é exibida, não as informações de tempo.
O ponto de interrogação após string indica que a propriedade é anulável.
Para obter mais informações, confira Tipos de referência anuláveis.
DataAnnotations são abordados em um tutorial posterior.
Crie o projeto para verificar se não há erros de compilação.
Fazer scaffold do modelo de filme
Nesta seção, é feito o scaffold do modelo de filme. Ou seja, a ferramenta de scaffolding
gera páginas para operações de CRUD (Criar, Ler, Atualizar e Excluir) para o modelo do
filme.
Visual Studio
1. Crie a pasta Páginas/Filmes :
a. Clique com o botão direito do mouse na pasta >PáginasAdicionar>Nova
Pasta.
b. Nomeie a pasta Filmes.
2. Clique com o botão direito do mouse na pasta
>Páginas/FilmesAdicionar>Novo Item Com Scaffolded.
3. Na caixa de diálogo Adicionar Novo Scaffold , selecione Razor Páginas
usando o CRUD (Entity Framework)>Adicionar.
4. Conclua a caixa de diálogo Adicionar Razor Páginas usando o CRUD (Entity
Framework ):
a. Na lista suspensa Classe de modelo, selecione Filme
(RazorPagesMovie.Models).
b. Na linha Classe de contexto de dados, selecione o sinal de + (adição).
i. Na caixa de diálogo Adicionar Contexto de Dados , o nome
RazorPagesMovie.Data.RazorPagesMovieContext da classe é gerado.
c. Selecione Adicionar.
O appsettings.json arquivo é atualizado com a cadeia de conexão usada para se
conectar a um banco de dados local.
Arquivos criados e atualizados
O processo de scaffold cria os arquivos a seguir:
Pages/Movies: Create, Delete, Details, Edit e Index.
Data/RazorPagesMovieContext.cs
Os arquivos criados são explicados no próximo tutorial.
O processo de scaffold adiciona o seguinte código realçado ao Program.cs arquivo:
Visual Studio
C#
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using RazorPagesMovie.Data;
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
builder.Services.AddRazorPages();
builder.Services.AddDbContext<RazorPagesMovieContext>(options =>
options.UseSqlServer(builder.Configuration.GetConnectionString("RazorPag
esMovieContext") ?? throw new InvalidOperationException("Connection
string 'RazorPagesMovieContext' not found.")));
var app = builder.Build();
// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
// The default HSTS value is 30 days. You may want to change this
for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthorization();
app.MapRazorPages();
app.Run();
As Program.cs alterações são explicadas posteriormente neste tutorial.
Criar o esquema de banco de dados inicial
usando o recurso de migração do EF
O recurso de migrações no Entity Framework Core fornece uma maneira de:
Crie o esquema inicial do banco de dados.
Atualize incrementalmente o esquema de banco de dados para mantê-lo em
sincronia com o modelo de dados do aplicativo. Os dados existentes no banco de
dados são preservados.
Visual Studio
Nesta seção, a janela PMC ( Console do Gerenciador de Pacotes ) é usada para:
Adicionar uma migração inicial.
Atualize o banco de dados com a migração inicial.
1. No menu Ferramentas selecione Gerenciador de Pacotes NuGet>Console do
Gerenciador de Pacotes.
2. No PMC, insira os seguintes comandos:
PowerShell
Add-Migration InitialCreate
Update-Database
Os comandos anteriores:
Instale as ferramentas mais recentes do Entity Framework Core depois de
desinstalar qualquer versão anterior, se ela existir.
Execute o migrations comando para gerar o código que cria o esquema inicial do
banco de dados.
O seguinte aviso é exibido, que é abordado em uma etapa posterior:
Nenhum tipo foi especificado para a coluna decimal 'Preço' no tipo de entidade
'Filme'. Isso fará com que valores sejam truncados silenciosamente se não couberem
na precisão e na escala padrão. Especifique explicitamente o tipo de coluna do SQL
Server que pode acomodar todos os valores usando 'HasColumnType()'.
O comando migrations gera código para criar o esquema de banco de dados inicial. O
esquema é baseado no modelo especificado em DbContext . O argumento
InitialCreate é usado para nomear as migrações. Qualquer nome pode ser usado,
mas, por convenção, um nome que descreve a migração é selecionado.
O update comando executa o Up método em migrações que não foram aplicadas.
Nesse caso, update executa o Up método no Migrations/<time-
stamp>_InitialCreate.cs arquivo , que cria o banco de dados.
Examinar o contexto registrado com a injeção de
dependência
O ASP.NET Core é construído com a injeção de dependência. Serviços, como o contexto
do EF Core banco de dados, são registrados com injeção de dependência durante a
inicialização do aplicativo. Componentes que exigem esses serviços (como Razor Pages)
são fornecidos por meio de parâmetros de construtor. O código de construtor que
obtém uma instância de contexto do banco de dados é mostrado mais adiante no
tutorial.
A ferramenta de scaffolding criou automaticamente um contexto de banco de dados e o
registrou com o contêiner de injeção de dependência. O código realçado a seguir é
adicionado ao Program.cs arquivo pelo scaffolder:
Visual Studio
C#
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using RazorPagesMovie.Data;
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
builder.Services.AddRazorPages();
builder.Services.AddDbContext<RazorPagesMovieContext>(options =>
options.UseSqlServer(builder.Configuration.GetConnectionString("RazorPag
esMovieContext") ?? throw new InvalidOperationException("Connection
string 'RazorPagesMovieContext' not found.")));
var app = builder.Build();
// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
// The default HSTS value is 30 days. You may want to change this
for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthorization();
app.MapRazorPages();
app.Run();
O contexto RazorPagesMovieContext de dados:
Deriva de Microsoft. EntityFrameworkCore.DbContext.
Especifica quais entidades estão incluídas no modelo de dados.
EF Core Coordena a funcionalidade, como Criar, Ler, Atualizar e Excluir, para o
Movie modelo.
C#
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using RazorPagesMovie.Models;
namespace RazorPagesMovie.Data
{
public class RazorPagesMovieContext : DbContext
{
public RazorPagesMovieContext
(DbContextOptions<RazorPagesMovieContext> options)
: base(options)
{
}
public DbSet<RazorPagesMovie.Models.Movie> Movie { get; set; } =
default!;
}
}
O código anterior cria uma propriedade DbSet<Movie> para o conjunto de entidades.
Na terminologia do Entity Framework, um conjunto de entidades normalmente
corresponde a uma tabela de banco de dados. Uma entidade corresponde a uma linha
da tabela.
O nome da cadeia de conexão é passado para o contexto com a chamada de um
método em um objeto DbContextOptions. Para desenvolvimento local, o sistema de
configuração lê a cadeia de conexão do appsettings.json arquivo.
Testar o aplicativo
1. Executar o aplicativo e acrescentar /Movies à URL no navegador
( http://localhost:port/movies ).
Se você receber o seguinte erro:
Console
SqlException: Cannot open database "RazorPagesMovieContext-GUID"
requested by the login. The login failed.
Login failed for user 'User-name'.
Você perdeu a etapa de migrações.
2. Teste o link Criar Novo .
7 Observação
Talvez você não consiga inserir casas decimais ou vírgulas no campo Price .
Para dar suporte à validação do jQuery para localidades com idiomas
diferentes do inglês que usam uma vírgula (",") para um ponto decimal e
formatos de data diferentes do inglês dos EUA, o aplicativo precisa ser
globalizado. Para obter instruções sobre a globalização, consulte esse
problema no GitHub .
3. Teste os links Editar, Detalhes e Excluir.
O tutorial a seguir explica os arquivos criados por scaffolding.
Solução de problemas com o exemplo
concluído
Se você encontrar um problema que não possa resolver, compare seu código com o
projeto concluído. Exibir ou baixar o projeto concluído (como baixar).
Recursos adicionais
Anterior: Introdução ao Próximo: Páginas com Scaffolded Razor
Parte 3, páginas scaffolded Razor no
ASP.NET Core
Artigo • 02/12/2022 • 26 minutos para o fim da leitura
De Rick Anderson
Este tutorial examina as Razor Páginas criadas por scaffolding no tutorial anterior.
As páginas Create, Delete, Details e Edit
Examine o Pages/Movies/Index.cshtml.cs modelo de página:
C#
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.EntityFrameworkCore;
using RazorPagesMovie.Models;
namespace RazorPagesMovie.Pages.Movies;
public class IndexModel : PageModel
{
private readonly RazorPagesMovie.Data.RazorPagesMovieContext _context;
public IndexModel(RazorPagesMovie.Data.RazorPagesMovieContext context)
{
_context = context;
}
public IList<Movie> Movie { get;set; } = default!;
public async Task OnGetAsync()
{
if (_context.Movie != null)
{
Movie = await _context.Movie.ToListAsync();
}
}
}
Razor As páginas são derivadas de PageModel. Por convenção, a PageModel classe
derivada é chamada PageNameModel de . Por exemplo, a página Índice é chamada
IndexModel de .
O construtor usa injeção de dependência para adicionar o RazorPagesMovieContext à
página:
C#
public class IndexModel : PageModel
{
private readonly RazorPagesMovie.Data.RazorPagesMovieContext _context;
public IndexModel(RazorPagesMovie.Data.RazorPagesMovieContext context)
{
_context = context;
}
Confira Código assíncrono para obter mais informações sobre a programação
assíncrona com o Entity Framework.
Quando uma GET solicitação é feita para a página, o OnGetAsync método retorna uma
lista de filmes para a Razor Página. Em uma Razor Página, OnGetAsync ou OnGet é
chamado para inicializar o estado da página. Nesse caso, OnGetAsync obtém uma lista
de filmes e os exibe.
Quando OnGet retorna void ou OnGetAsync retorna Task , nenhuma instrução return é
usada. Por exemplo, examine a Privacy Página:
C#
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
namespace RazorPagesMovie.Pages
{
public class PrivacyModel : PageModel
{
private readonly ILogger<PrivacyModel> _logger;
public PrivacyModel(ILogger<PrivacyModel> logger)
{
_logger = logger;
}
public void OnGet()
{
}
}
}
Quando o tipo de retorno for IActionResult ou Task<IActionResult> , é necessário
fornecer uma instrução de retorno. Por exemplo, o Pages/Movies/Create.cshtml.cs
OnPostAsync método :
C#
public async Task<IActionResult> OnPostAsync()
{
if (!ModelState.IsValid)
{
return Page();
}
_context.Movie.Add(Movie);
await _context.SaveChangesAsync();
return RedirectToPage("./Index");
}
Examine a Pages/Movies/Index.cshtml Razor Página:
CSHTML
@page
@model RazorPagesMovie.Pages.Movies.IndexModel
@{
ViewData["Title"] = "Index";
}
<h1>Index</h1>
<p>
<a asp-page="Create">Create New</a>
</p>
<table class="table">
<thead>
<tr>
<th>
@Html.DisplayNameFor(model => model.Movie[0].Title)
</th>
<th>
@Html.DisplayNameFor(model => model.Movie[0].ReleaseDate)
</th>
<th>
@Html.DisplayNameFor(model => model.Movie[0].Genre)
</th>
<th>
@Html.DisplayNameFor(model => model.Movie[0].Price)
</th>
<th></th>
</tr>
</thead>
<tbody>
@foreach (var item in Model.Movie) {
<tr>
<td>
@Html.DisplayFor(modelItem => item.Title)
</td>
<td>
@Html.DisplayFor(modelItem => item.ReleaseDate)
</td>
<td>
@Html.DisplayFor(modelItem => item.Genre)
</td>
<td>
@Html.DisplayFor(modelItem => item.Price)
</td>
<td>
<a asp-page="./Edit" asp-route-id="@item.Id">Edit</a> |
<a asp-page="./Details" asp-route-id="@item.Id">Details</a>
|
<a asp-page="./Delete" asp-route-id="@item.Id">Delete</a>
</td>
</tr>
}
</tbody>
</table>
Razor pode fazer a transição de HTML para C# ou para Razormarcação específica.
Quando um @ símbolo é seguido por uma Razor palavra-chave reservada, ele faz a
transição para Razoruma marcação específica, caso contrário, ele faz a transição para
C#.
A diretiva @page
A @page Razor diretiva torna o arquivo uma ação MVC, o que significa que ele pode lidar
com solicitações. @page deve ser a primeira diretiva do Razor em uma página. @page e
@model são exemplos de transição para Razormarcação específica. Consulte Razor
sintaxe para obter mais informações.
A diretiva @model
CSHTML
@page
@model RazorPagesMovie.Pages.Movies.IndexModel
A @model diretiva especifica o tipo do modelo passado para a Razor Página. No exemplo
anterior, a @model linha disponibiliza a PageModel classe derivada para a Razor Página. O
modelo é usado nos auxiliares HTML @Html.DisplayNameFor e @Html.DisplayFor na
página.
Examine a expressão lambda usada no auxiliar HTML a seguir:
CSHTML
@Html.DisplayNameFor(model => model.Movie[0].Title)
O auxiliar HTML DisplayNameFor inspeciona a propriedade Title referenciada na
expressão lambda para determinar o nome de exibição. A expressão lambda é
inspecionada em vez de avaliada. Isso significa que não há violação de acesso quando
model , model.Movie ou model.Movie[0] está ou está null vazio. Quando a expressão
lambda é avaliada, por exemplo, com @Html.DisplayFor(modelItem => item.Title) , os
valores de propriedade do modelo são avaliados.
A página de layout
Selecione os links Razorde menu PagesMovie, Homee Privacy. Cada página mostra o
mesmo layout de menu. O layout do menu é implementado no
Pages/Shared/_Layout.cshtml arquivo.
Abra e examine o Pages/Shared/_Layout.cshtml arquivo.
Os modelos de layout permitem que o layout do contêiner HTML seja:
Especificado em um único lugar.
Aplicado a várias páginas no site.
Localize a linha @RenderBody() . RenderBody é um espaço reservado em que todas as
exibições específicas da página são mostradas, encapsuladas na página de layout. Por
exemplo, selecione o Privacy link e a exibição Pages/Privacy.cshtml é renderizada
dentro do RenderBody método .
ViewData e layout
Considere a seguinte marcação do Pages/Movies/Index.cshtml arquivo:
CSHTML
@page
@model RazorPagesMovie.Pages.Movies.IndexModel
@{
ViewData["Title"] = "Index";
}
A marcação realçada anterior é um exemplo de Razor transição para C#. Os caracteres
{ e } circunscrevem um bloco de código C#.
A PageModel classe base contém uma ViewData propriedade de dicionário que pode ser
usada para passar dados para um Modo de Exibição. Os objetos são adicionados ao
ViewData dicionário usando um padrão de valor de chave . No exemplo anterior, a
propriedade Title é adicionada ao dicionário ViewData .
A Title propriedade é usada no Pages/Shared/_Layout.cshtml arquivo . A marcação a
seguir mostra as primeiras linhas do _Layout.cshtml arquivo.
CSHTML
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>@ViewData["Title"] - RazorPagesMovie</title>
<link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.min.css"
/>
<link rel="stylesheet" href="~/css/site.css" asp-append-version="true"
/>
<link rel="stylesheet" href="~/RazorPagesMovie.styles.css" asp-append-
version="true" />
A linha @*Markup removed for brevity.*@ é um Razor comentário. Ao contrário dos
comentários <!-- --> HTML, Razor os comentários não são enviados ao cliente. Confira
Documentos da Web do MDN: Introdução ao HTML para obter mais informações.
Atualizar o layout
1. Altere o <title> elemento no Pages/Shared/_Layout.cshtml arquivo para exibir
Movie em vez de RazorPagesMovie.
CSHTML
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-
scale=1.0" />
<title>@ViewData["Title"] - Movie</title>
2. Localize o seguinte elemento de âncora no Pages/Shared/_Layout.cshtml arquivo.
CSHTML
<a class="navbar-brand" asp-area="" asp-
page="/Index">RazorPagesMovie</a>
3. Substitua o elemento anterior pela marcação a seguir:
CSHTML
<a class="navbar-brand" asp-page="/Movies/Index">RpMovie</a>
O elemento de âncora anterior é um Auxiliar de Marcas. Nesse caso, ele é o
Auxiliar de Marcas de Âncora. O asp-page="/Movies/Index" atributo e o valor do
Auxiliar de Marca criam um link para a /Movies/Index Razor Página. O valor do
atributo asp-area está vazio e, portanto, a área não é usada no link. Confira Áreas
para obter mais informações.
4. Salve as alterações e teste o aplicativo selecionando o link RpMovie . Confira o
arquivo _Layout.cshtml no GitHub caso tenha problemas.
5. Teste os Homelinks , RpMovie, Criar, Editar e Excluir . Cada página define o título,
que você pode ver na guia do navegador. Quando você marca uma página, o
título é usado para o indicador.
7 Observação
Talvez você não consiga inserir casas decimais ou vírgulas no campo Price . Para
dar suporte à validação jQuery para localidades não inglesas que usam uma
vírgula ("") para um ponto decimal e formatos de data não US-English, você deve
tomar medidas para globalizar o aplicativo. Confira Problema 4076 do GitHub
para obter instruções sobre como adicionar casas decimais.
A Layout propriedade é definida no Pages/_ViewStart.cshtml arquivo:
CSHTML
@{
Layout = "_Layout";
}
A marcação anterior define o arquivo de layout como Pages/Shared/_Layout.cshtml para
todos os Razor arquivos na pasta Páginas . Veja Layout para obter mais informações.
O modelo Criar página
Examine o modelo de Pages/Movies/Create.cshtml.cs página:
C#
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using RazorPagesMovie.Models;
namespace RazorPagesMovie.Pages.Movies
{
public class CreateModel : PageModel
{
private readonly RazorPagesMovie.Data.RazorPagesMovieContext
_context;
public CreateModel(RazorPagesMovie.Data.RazorPagesMovieContext
context)
{
_context = context;
}
public IActionResult OnGet()
{
return Page();
}
[BindProperty]
public Movie Movie { get; set; } = default!;
// To protect from overposting attacks, see
https://aka.ms/RazorPagesCRUD
public async Task<IActionResult> OnPostAsync()
{
if (!ModelState.IsValid || _context.Movie == null || Movie ==
null)
{
return Page();
}
_context.Movie.Add(Movie);
await _context.SaveChangesAsync();
return RedirectToPage("./Index");
}
}
}
O método OnGet inicializa qualquer estado necessário para a página. A página Criar não
tem nenhum estado para inicializar, assim, Page é retornado. Apresentamos um
exemplo de inicialização de estado OnGet posteriormente no tutorial. O Page método
cria um PageResult objeto que renderiza a Create.cshtml página.
A Movie propriedade usa o atributo [BindProperty] para aceitar a associação de modelo.
Quando o formulário Criar posta os valores de formulário, o runtime do ASP.NET Core
associa os valores postados ao modelo Movie .
O método OnPostAsync é executado quando a página posta dados de formulário:
C#
public async Task<IActionResult> OnPostAsync()
{
if (!ModelState.IsValid)
{
return Page();
}
_context.Movie.Add(Movie);
await _context.SaveChangesAsync();
return RedirectToPage("./Index");
}
Se há algum erro de modelo, o formulário é reexibido juntamente com quaisquer dados
de formulário postados. A maioria dos erros de modelo podem ser capturados no lado
do cliente antes do formulário ser enviado. Um exemplo de um erro de modelo é
postar, para o campo de data, um valor que não pode ser convertido em uma data. A
validação do lado do cliente e a validação de modelo são abordadas mais adiante no
tutorial.
Se não houver erros de modelo:
Os dados são salvos.
O navegador é redirecionado para a página Índice.
A página Criar Razor
Examine o Pages/Movies/Create.cshtml Razor arquivo de página:
CSHTML
@page
@model RazorPagesMovie.Pages.Movies.CreateModel
@{
ViewData["Title"] = "Create";
}
<h1>Create</h1>
<h4>Movie</h4>
<hr />
<div class="row">
<div class="col-md-4">
<form method="post">
<div asp-validation-summary="ModelOnly" class="text-danger">
</div>
<div class="form-group">
<label asp-for="Movie.Title" class="control-label"></label>
<input asp-for="Movie.Title" class="form-control" />
<span asp-validation-for="Movie.Title" class="text-danger">
</span>
</div>
<div class="form-group">
<label asp-for="Movie.ReleaseDate" class="control-label">
</label>
<input asp-for="Movie.ReleaseDate" class="form-control" />
<span asp-validation-for="Movie.ReleaseDate" class="text-
danger"></span>
</div>
<div class="form-group">
<label asp-for="Movie.Genre" class="control-label"></label>
<input asp-for="Movie.Genre" class="form-control" />
<span asp-validation-for="Movie.Genre" class="text-danger">
</span>
</div>
<div class="form-group">
<label asp-for="Movie.Price" class="control-label"></label>
<input asp-for="Movie.Price" class="form-control" />
<span asp-validation-for="Movie.Price" class="text-danger">
</span>
</div>
<div class="form-group">
<input type="submit" value="Create" class="btn btn-primary"
/>
</div>
</form>
</div>
</div>
<div>
<a asp-page="Index">Back to List</a>
</div>
@section Scripts {
@{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}
Visual Studio
O Visual Studio exibe as marcas a seguir em uma fonte em negrito diferente usada
em auxiliares de marcações:
<form method="post">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<label asp-for="Movie.Title" class="control-label"></label>
<input asp-for="Movie.Title" class="form-control" />
<span asp-validation-for="Movie.Title" class="text-danger"></span>
O elemento <form method="post"> é um auxiliar de marcas de formulário. O auxiliar de
marcas de formulário inclui automaticamente um token antifalsificação.
O mecanismo de scaffolding cria Razor marcação para cada campo no modelo, exceto a
ID, semelhante à seguinte:
CSHTML
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="Movie.Title" class="control-label"></label>
<input asp-for="Movie.Title" class="form-control" />
<span asp-validation-for="Movie.Title" class="text-danger"></span>
</div>
Os Auxiliares de Marca de Validação ( <div asp-validation-summary e <span asp-
validation-for ) exibem erros de validação. A validação será abordada em mais detalhes
posteriormente nesta série.
O Auxiliar de Marca de Rótulo ( <label asp-for="Movie.Title" class="control-label">
</label> ) gera a legenda do rótulo e [for] o atributo para a Title propriedade .
O Auxiliar de Marca de Entrada ( <input asp-for="Movie.Title" class="form-control"> )
usa os atributos DataAnnotations e produz atributos HTML necessários para a Validação
de jQuery no lado do cliente.
Para obter mais informações sobre Auxiliares de Marcas, como <form method="post"> ,
confira Auxiliares de Marcas no ASP.NET Core.
Recursos adicionais
Anterior: Adicionar um modelo Avançar: Trabalhar com um banco de dados
Parte 4 da série de tutoriais em Razor
Páginas
Artigo • 03/12/2022 • 22 minutos para o fim da leitura
Por Joe Audette
O objeto RazorPagesMovieContext cuida da tarefa de se conectar ao banco de dados e
mapear objetos Movie para registros do banco de dados. O contexto do banco de
dados é registrado com o contêiner injeção de dependência em Program.cs :
Visual Studio
C#
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using RazorPagesMovie.Data;
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
builder.Services.AddRazorPages();
builder.Services.AddDbContext<RazorPagesMovieContext>(options =>
options.UseSqlServer(builder.Configuration.GetConnectionString("RazorPag
esMovieContext") ?? throw new InvalidOperationException("Connection
string 'RazorPagesMovieContext' not found.")));
var app = builder.Build();
O sistema de configuração de ASP.NET Core lê a ConnectionString chave. Para
desenvolvimento local, a configuração obtém a cadeia de conexão do appsettings.json
arquivo.
Visual Studio
A cadeia de conexão gerada é semelhante ao seguinte JSON:
JSON
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"AllowedHosts": "*",
"ConnectionStrings": {
"RazorPagesMovieContext": "Server=
(localdb)\\mssqllocaldb;Database=RazorPagesMovieContext-
bc;Trusted_Connection=True;MultipleActiveResultSets=true"
}
}
Quando o aplicativo é implantado em um servidor de teste ou produção, uma variável
de ambiente pode ser usada para definir a cadeia de conexão como um servidor de
banco de dados de teste ou de produção. Para obter mais informações, confira
Configuração.
Visual Studio
SQL Server Express LocalDB
O LocalDB é uma versão leve do mecanismo de banco de dados do SQL Server
Express direcionada para o desenvolvimento de programas. O LocalDB é iniciado
sob demanda e executado no modo de usuário e, portanto, não há nenhuma
configuração complexa. Por padrão, o banco de dados LocalDB cria arquivos *.mdf
no diretório C:\Users\<user>\ .
1. No menu Exibir, abra SSOX (Pesquisador de Objetos do SQL Server).
2. Clique com o botão direito do mouse na Movie tabela e selecione Designer
de Exibição:
Observe o ícone de chave ao lado de ID . Por padrão, o EF cria uma
propriedade chamada ID para a chave primária.
3. Clique com o botão direito do mouse na Movie tabela e selecione Exibir
Dados:
Propagar o banco de dados
Crie uma classe chamada SeedData na pasta Models com o seguinte código:
C#
using Microsoft.EntityFrameworkCore;
using RazorPagesMovie.Data;
namespace RazorPagesMovie.Models;
public static class SeedData
{
public static void Initialize(IServiceProvider serviceProvider)
{
using (var context = new RazorPagesMovieContext(
serviceProvider.GetRequiredService<
DbContextOptions<RazorPagesMovieContext>>()))
{
if (context == null || context.Movie == null)
{
throw new ArgumentNullException("Null
RazorPagesMovieContext");
}
// Look for any movies.
if (context.Movie.Any())
{
return; // DB has been seeded
}
context.Movie.AddRange(
new Movie
{
Title = "When Harry Met Sally",
ReleaseDate = DateTime.Parse("1989-2-12"),
Genre = "Romantic Comedy",
Price = 7.99M
},
new Movie
{
Title = "Ghostbusters ",
ReleaseDate = DateTime.Parse("1984-3-13"),
Genre = "Comedy",
Price = 8.99M
},
new Movie
{
Title = "Ghostbusters 2",
ReleaseDate = DateTime.Parse("1986-2-23"),
Genre = "Comedy",
Price = 9.99M
},
new Movie
{
Title = "Rio Bravo",
ReleaseDate = DateTime.Parse("1959-4-15"),
Genre = "Western",
Price = 3.99M
}
);
context.SaveChanges();
}
}
}
Se houver filmes no banco de dados, o inicializador de semente retornará e nenhum
filme será adicionado.
C#
if (context.Movie.Any())
{
return;
}
Adicionar o inicializador de semeadura
Atualize o Program.cs com o seguinte código realçado:
Visual Studio
C#
using Microsoft.EntityFrameworkCore;
using RazorPagesMovie.Data;
using RazorPagesMovie.Models;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages();
builder.Services.AddDbContext<RazorPagesMovieContext>(options =>
options.UseSqlServer(builder.Configuration.GetConnectionString("RazorPag
esMovieContext") ?? throw new InvalidOperationException("Connection
string 'RazorPagesMovieContext' not found.")));
var app = builder.Build();
using (var scope = app.Services.CreateScope())
{
var services = scope.ServiceProvider;
SeedData.Initialize(services);
}
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthorization();
app.MapRazorPages();
app.Run();
No código anterior, Program.cs foi modificado para fazer o seguinte:
Obtenha uma instância de contexto de banco de dados do contêiner de DI
(injeção de dependência).
Chame o seedData.Initialize método , passando para ele a instância de contexto
do banco de dados.
Descarte o contexto quando o método de semente for concluído. A instrução
using garante que o contexto seja descartado.
A seguinte exceção ocorre quando Update-Database não foi executada:
SqlException: Cannot open database "RazorPagesMovieContext-" requested by the
login. The login failed. Login failed for user 'user name'.
Testar o aplicativo
Exclua todos os registros no banco de dados para que o método de semente seja
executado. Interrompa e inicie o aplicativo para propagar o banco de dados. Se o banco
de dados não for propagado, coloque um ponto if (context.Movie.Any()) de
interrupção e percorra o código.
O aplicativo mostra os dados propagados:
Recursos adicionais
Anterior: Scaffolded Razor Páginas a seguir: Atualizar as páginas
Parte 5, atualize as páginas geradas em
um aplicativo ASP.NET Core
Artigo • 03/12/2022 • 15 minutos para o fim da leitura
O aplicativo de filme gerado por scaffolding tem um bom começo, mas a apresentação
não é ideal. ReleaseDate deve ser duas palavras, Data de Lançamento.
Atualizar o modelo
Atualize Models/Movie.cs com o seguinte código realçado:
C#
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace RazorPagesMovie.Models;
public class Movie
{
public int Id { get; set; }
public string Title { get; set; } = string.Empty;
[Display(Name = "Release Date")]
[DataType(DataType.Date)]
public DateTime ReleaseDate { get; set; }
public string Genre { get; set; } = string.Empty;
[Column(TypeName = "decimal(18, 2)")]
public decimal Price { get; set; }
}
No código anterior:
A anotação de dados [Column(TypeName = "decimal(18, 2)")] permite que o Entity
Framework Core mapeie o Price corretamente para a moeda no banco de dados.
Para obter mais informações, veja Tipos de Dados.
O atributo [Display] especifica o nome de exibição de um campo. No código
anterior, Release Date em vez de ReleaseDate .
O atributo [DataType] especifica o tipo dos dados ( Date ). As informações de
tempo armazenadas no campo não são exibidas.
DataAnnotations é abordado no próximo tutorial.
Navegue até Páginas/Filmes e passe o mouse sobre um link Editar para ver a URL de
destino.
Os links Editar, Detalhes e Excluir são gerados pelo Auxiliar de Marca de Âncora no
Pages/Movies/Index.cshtml arquivo.
CSHTML
@foreach (var item in Model.Movie) {
<tr>
<td>
@Html.DisplayFor(modelItem => item.Title)
</td>
<td>
@Html.DisplayFor(modelItem => item.ReleaseDate)
</td>
<td>
@Html.DisplayFor(modelItem => item.Genre)
</td>
<td>
@Html.DisplayFor(modelItem => item.Price)
</td>
<td>
<a asp-page="./Edit" asp-route-id="@item.ID">Edit</a> |
<a asp-page="./Details" asp-route-id="@item.ID">Details</a>
|
<a asp-page="./Delete" asp-route-id="@item.ID">Delete</a>
</td>
</tr>
}
</tbody>
</table>
Os Auxiliares de Marcação permitem que o código do servidor participe da criação e
renderização de elementos HTML em arquivos do Razor.
No código anterior, o Auxiliar de Marca de Âncora gera dinamicamente o valor do
atributo HTML href da Razor Página (a rota é relativa), o asp-page e o identificador de
rota (). asp-route-id Para obter mais informações, consulte Geração de URL para
Páginas.
Use Exibir Fonte de um navegador para examinar a marcação gerada. Uma parte do
HTML gerado é mostrada abaixo:
HTML
<td>
<a href="/Movies/Edit?id=1">Edit</a> |
<a href="/Movies/Details?id=1">Details</a> |
<a href="/Movies/Delete?id=1">Delete</a>
</td>
Os links gerados dinamicamente passam a ID do filme com uma cadeia de caracteres de
consulta . Por exemplo, o ?id=1 em https://localhost:5001/Movies/Details?id=1 .
Adicionar modelo de rota
Atualize as páginas Editar, Detalhes e Excluir Razor para usar o {id:int} modelo de
rota. Altere a diretiva de página de cada uma dessas páginas de @page para @page "
{id:int}" . Execute o aplicativo e, em seguida, exiba o código-fonte.
O HTML gerado adiciona a ID à parte do caminho da URL:
HTML
<td>
<a href="/Movies/Edit/1">Edit</a> |
<a href="/Movies/Details/1">Details</a> |
<a href="/Movies/Delete/1">Delete</a>
</td>
Uma solicitação para a página com o {id:int} modelo de rota que não inclui o inteiro
retorna um erro HTTP 404 (não encontrado). Por exemplo,
https://localhost:5001/Movies/Details retorna um erro 404. Para tornar a ID opcional,
acrescente ? à restrição de rota:
CSHTML
@page "{id:int?}"
Teste o comportamento de @page "{id:int?}" :
1. Defina a diretiva de página em como Pages/Movies/Details.cshtml @page "
{id:int?}" .
2. Defina um ponto de interrupção em public async Task<IActionResult>
OnGetAsync(int? id) , em Pages/Movies/Details.cshtml.cs .
3. Navegue até https://localhost:5001/Movies/Details/ .
Com a diretiva @page "{id:int}" , o ponto de interrupção nunca é atingido. O
mecanismo de roteamento retorna HTTP 404. Usando @page "{id:int?}" , o OnGetAsync
método retorna NotFound (HTTP 404):
C#
public async Task<IActionResult> OnGetAsync(int? id)
{
if (id == null)
{
return NotFound();
}
Movie = await _context.Movie.FirstOrDefaultAsync(m => m.ID == id);
if (Movie == null)
{
return NotFound();
}
return Page();
}
Examinar o tratamento de exceção de simultaneidade
Examine o OnPostAsync método no Pages/Movies/Edit.cshtml.cs arquivo:
C#
public async Task<IActionResult> OnPostAsync()
{
if (!ModelState.IsValid)
{
return Page();
}
_context.Attach(Movie).State = EntityState.Modified;
try
{
await _context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if (!MovieExists(Movie.Id))
{
return NotFound();
}
else
{
throw;
}
}
return RedirectToPage("./Index");
}
private bool MovieExists(int id)
{
return _context.Movie.Any(e => e.Id == id);
}
O código anterior detecta exceções de simultaneidade quando um cliente exclui o filme
e o outro cliente posta alterações no filme.
Para testar o bloco catch :
1. Defina um ponto de interrupção em catch (DbUpdateConcurrencyException)
2. Selecione Editar para um filme, faça alterações, mas não insira Salvar.
3. Em outra janela do navegador, selecione o link Excluir do mesmo filme e, em
seguida, exclua o filme.
4. Na janela do navegador anterior, poste as alterações no filme.
O código de produção talvez deseje detectar conflitos de simultaneidade. Confira Lidar
com conflitos de simultaneidade para obter mais informações.
Análise de postagem e associação
Examine o Pages/Movies/Edit.cshtml.cs arquivo:
C#
public class EditModel : PageModel
{
private readonly RazorPagesMovie.Data.RazorPagesMovieContext _context;
public EditModel(RazorPagesMovie.Data.RazorPagesMovieContext context)
{
_context = context;
}
[BindProperty]
public Movie Movie { get; set; } = default!;
public async Task<IActionResult> OnGetAsync(int? id)
{
if (id == null || _context.Movie == null)
{
return NotFound();
}
var movie = await _context.Movie.FirstOrDefaultAsync(m => m.Id ==
id);
if (movie == null)
{
return NotFound();
}
Movie = movie;
return Page();
}
// To protect from overposting attacks, enable the specific properties
you want to bind to.
// For more details, see https://aka.ms/RazorPagesCRUD.
public async Task<IActionResult> OnPostAsync()
{
if (!ModelState.IsValid)
{
return Page();
}
_context.Attach(Movie).State = EntityState.Modified;
try
{
await _context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if (!MovieExists(Movie.Id))
{
return NotFound();
}
else
{
throw;
}
}
return RedirectToPage("./Index");
}
private bool MovieExists(int id)
{
return _context.Movie.Any(e => e.Id == id);
}
Quando uma solicitação HTTP GET é feita na página Filmes/Editar, por exemplo,
https://localhost:5001/Movies/Edit/3 :
O método OnGetAsync busca o filme do banco de dados e retorna o método Page .
O Page método renderiza a Pages/Movies/Edit.cshtml Razor Página. O
Pages/Movies/Edit.cshtml arquivo contém a diretiva @model
RazorPagesMovie.Pages.Movies.EditModel de modelo , que disponibiliza o modelo
de filme na página.
O formulário Editar é exibido com os valores do filme.
Quando a página Movies/Edit é postada:
Os valores de formulário na página são associados à propriedade Movie . O
atributo [BindProperty] habilita o Model binding.
C#
[BindProperty]
public Movie Movie { get; set; }
Se houver erros no estado do modelo, por exemplo, ReleaseDate não poderão ser
convertidos em uma data, o formulário será reproduzido com os valores enviados.
Se não houver erros do modelo, o filme será salvo.
Os métodos HTTP GET nas páginas Index, Create e Delete Razor seguem um padrão
semelhante. O método HTTP POST OnPostAsync na página Criar Razor segue um padrão
semelhante ao OnPostAsync método na Página de Edição Razor .
Recursos adicionais
Anterior: Trabalhar com um banco de dados Avançar: Adicionar pesquisa
Parte 6, adicionar pesquisa ao ASP.NET
Core Razor Pages
Artigo • 10/01/2023 • 10 minutos para o fim da leitura
De Rick Anderson
Nas seções a seguir, a pesquisa de filmes por gênero ou nome é adicionada.
Adicione o código realçado a seguir a Pages/Movies/Index.cshtml.cs :
C#
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.EntityFrameworkCore;
using RazorPagesMovie.Models;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace RazorPagesMovie.Pages.Movies
{
public class IndexModel : PageModel
{
private readonly RazorPagesMovie.Data.RazorPagesMovieContext
_context;
public IndexModel(RazorPagesMovie.Data.RazorPagesMovieContext
context)
{
_context = context;
}
public IList<Movie> Movie { get;set; } = default!;
[BindProperty(SupportsGet = true)]
public string ? SearchString { get; set; }
public SelectList ? Genres { get; set; }
[BindProperty(SupportsGet = true)]
public string ? MovieGenre { get; set; }
No código anterior:
SearchString : contém o texto que os usuários inserem na caixa de texto de
pesquisa. SearchString tem o [BindProperty] atributo . [BindProperty] associa
valores de formulário e cadeias de consulta ao mesmo nome da propriedade.
[BindProperty(SupportsGet = true)] é necessário para associação em solicitações
HTTP GET.
Genres : contém a lista de gêneros. Genres permite que o usuário selecione um
gênero na lista. SelectList exige using Microsoft.AspNetCore.Mvc.Rendering;
MovieGenre : contém o gênero específico selecionado pelo usuário. Por exemplo,
"Western".
Genres e MovieGenre são abordados mais adiante neste tutorial.
2 Aviso
Por motivos de segurança, você deve aceitar associar os dados da solicitação GET
às propriedades do modelo de página. Verifique a entrada do usuário antes de
mapeá-la para as propriedades. Aceitar a associação de GET é útil ao lidar com
cenários que contam com a cadeia de caracteres de consulta ou com os valores de
rota.
Para associar uma propriedade a solicitações GET , defina a propriedade
SupportsGet do atributo [BindProperty] como true :
C#
[BindProperty(SupportsGet = true)]
Para obter mais informações, confira ASP.NET Core Community Standup: Bind on
GET discussion (YouTube) .
Atualize o método OnGetAsync da página de Índice pelo seguinte código:
C#
public async Task OnGetAsync()
{
var movies = from m in _context.Movie
select m;
if (!string.IsNullOrEmpty(SearchString))
{
movies = movies.Where(s => s.Title.Contains(SearchString));
}
Movie = await movies.ToListAsync();
}
A primeira linha do método OnGetAsync cria uma consulta LINQ para selecionar os
filmes:
C#
// using System.Linq;
var movies = from m in _context.Movie
select m;
A consulta só é definida neste ponto, não foi executada no banco de dados.
Se a propriedade SearchString não é nula nem vazia, a consulta de filmes é modificada
para filtrar a cadeia de pesquisa:
C#
if (!string.IsNullOrEmpty(SearchString))
{
movies = movies.Where(s => s.Title.Contains(SearchString));
}
O código s => s.Title.Contains() é uma Expressão Lambda. Lambdas são usados em
consultas LINQ baseadas em método como argumentos para métodos de operador de
consulta padrão, como o método Where ou Contains . As consultas LINQ não são
executadas quando são definidas ou quando são modificadas chamando um método,
como Where , Contains ou OrderBy . Em vez disso, a execução da consulta é adiada. A
avaliação de uma expressão é atrasada até que seu valor realizado seja iterado ou o
ToListAsync método seja chamado. Consulte Execução de consulta para obter mais
informações.
7 Observação
O Contains método é executado no banco de dados, não no código C#. A
diferenciação de maiúsculas e minúsculas na consulta depende do banco de dados
e da ordenação. No SQL Server, Contains é mapeado para SQL LIKE, que não
diferencia maiúsculas de minúsculas. SQLite com a ordenação padrão é uma
combinação de diferenciação de maiúsculas de minúsculas emaiúsculas de
minúsculas, dependendo da consulta. Para obter informações sobre como tornar as
consultas SQLite que não diferenciam maiúsculas de minúsculas, consulte o
seguinte:
Este problema do GitHub
Este problema do GitHub
Ordenações e diferenciação de maiúsculas e minúsculas
Navegue até a página Filmes e acrescente uma cadeia de caracteres de consulta, como
?searchString=Ghost à URL. Por exemplo, https://localhost:5001/Movies?
searchString=Ghost . Os filmes filtrados são exibidos.
Se o modelo de rota a seguir for adicionado à página Índice, a cadeia de caracteres de
pesquisa poderá ser passada como um segmento de URL. Por exemplo,
https://localhost:5001/Movies/Ghost .
CSHTML
@page "{searchString?}"
A restrição da rota anterior permite a pesquisa do título como dados de rota (um
segmento de URL), em vez de como um valor de cadeia de caracteres de consulta. O ?
em "{searchString?}" significa que esse é um parâmetro de rota opcional.
O runtime do ASP.NET Core usa o model binding para definir o valor da propriedade
SearchString na cadeia de consulta ( ?searchString=Ghost ) ou nos dados de rota
( https://localhost:5001/Movies/Ghost ). A associação de modelo não diferencia
maiúsculas de minúsculas.
No entanto, não é esperado que os usuários modifiquem a URL para pesquisar um
filme. Nesta etapa, a interface do usuário é adicionada para filtrar filmes. Se você
adicionou a restrição de rota "{searchString?}" , remova-a.
Abra o Pages/Movies/Index.cshtml arquivo e adicione a marcação realçada no seguinte
código:
CSHTML
@page
@model RazorPagesMovie.Pages.Movies.IndexModel
@{
ViewData["Title"] = "Index";
}
<h1>Index</h1>
<p>
<a asp-page="Create">Create New</a>
</p>
<form>
<p>
Title: <input type="text" asp-for="SearchString" />
<input type="submit" value="Filter" />
</p>
</form>
<table class="table">
@*Markup removed for brevity.*@
A marca <form> HTML usa os seguintes Auxiliares de Marcas:
Auxiliar de Marca de Formulário. Quando o formulário é enviado, a cadeia de
caracteres de filtro é enviada para a página Pages/Movies/Index por meio da cadeia
de consulta.
Auxiliar de marcação de entrada
Salve as alterações e teste o filtro.
Pesquisar por gênero
Atualize o método OnGetAsync da página de Índice pelo seguinte código:
C#
public async Task OnGetAsync()
{
// Use LINQ to get list of genres.
IQueryable<string> genreQuery = from m in _context.Movie
orderby m.Genre
select m.Genre;
var movies = from m in _context.Movie
select m;
if (!string.IsNullOrEmpty(SearchString))
{
movies = movies.Where(s => s.Title.Contains(SearchString));
}
if (!string.IsNullOrEmpty(MovieGenre))
{
movies = movies.Where(x => x.Genre == MovieGenre);
}
Genres = new SelectList(await genreQuery.Distinct().ToListAsync());
Movie = await movies.ToListAsync();
}
O código a seguir é uma consulta LINQ que recupera todos os gêneros do banco de
dados.
C#
// Use LINQ to get list of genres.
IQueryable<string> genreQuery = from m in _context.Movie
orderby m.Genre
select m.Genre;
O SelectList de gêneros é criado com a projeção dos gêneros distintos.
C#
Genres = new SelectList(await genreQuery.Distinct().ToListAsync());
Adicionar pesquisa por gênero à Razor Página
Atualize o Index.cshtml <form> elemento conforme realçado na seguinte marcação:
CSHTML
@page
@model RazorPagesMovie.Pages.Movies.IndexModel
@{
ViewData["Title"] = "Index";
}
<h1>Index</h1>
<p>
<a asp-page="Create">Create New</a>
</p>
<form>
<p>
<select asp-for="MovieGenre" asp-items="Model.Genres">
<option value="">All</option>
</select>
Title: <input type="text" asp-for="SearchString" />
<input type="submit" value="Filter" />
</p>
</form>
Teste o aplicativo pesquisando por gênero, título do filme e por ambos.
Anterior: Atualizar as páginas Avançar: Adicionar um novo campo
Parte 7, adicione um novo campo a uma
Razor Página no ASP.NET Core
Artigo • 02/12/2022 • 24 minutos para o fim da leitura
De Rick Anderson
Nesta seção, as Migrações do Entity Framework Code First são usadas para:
Adicionar um novo campo ao modelo.
Migrar a nova alteração de esquema de campo para o banco de dados.
Ao usar o EF Code First para criar e acompanhar automaticamente um banco de dados,
Code First:
Adiciona uma __EFMigrationsHistory tabela ao banco de dados para acompanhar
se o esquema do banco de dados está em sincronia com as classes de modelo das
quais ele foi gerado.
Gerará uma exceção se as classes de modelo não estiverem sincronizadas com o
banco de dados.
A verificação automática de que o esquema e o modelo estão em sincronia facilita a
localização de problemas de código de banco de dados inconsistentes.
Adicionando uma propriedade de classificação
ao modelo de filme
1. Abra o Models/Movie.cs arquivo e adicione uma Rating propriedade:
C#
public class Movie
{
public int Id { get; set; }
public string Title { get; set; } = string.Empty;
[Display(Name = "Release Date")]
[DataType(DataType.Date)]
public DateTime ReleaseDate { get; set; }
public string Genre { get; set; } = string.Empty;
[Column(TypeName = "decimal(18, 2)")]
public decimal Price { get; set; }
public string Rating { get; set; } = string.Empty;
}
2. Edite Pages/Movies/Index.cshtml e adicione um Rating campo:
CSHTML
@page
@model RazorPagesMovie.Pages.Movies.IndexModel
@{
ViewData["Title"] = "Index";
}
<h1>Index</h1>
<p>
<a asp-page="Create">Create New</a>
</p>
<form>
<p>
<select asp-for="MovieGenre" asp-items="Model.Genres">
<option value="">All</option>
</select>
Title: <input type="text" asp-for="SearchString" />
<input type="submit" value="Filter" />
</p>
</form>
<table class="table">
<thead>
<tr>
<th>
@Html.DisplayNameFor(model => model.Movie[0].Title)
</th>
<th>
@Html.DisplayNameFor(model =>
model.Movie[0].ReleaseDate)
</th>
<th>
@Html.DisplayNameFor(model => model.Movie[0].Genre)
</th>
<th>
@Html.DisplayNameFor(model => model.Movie[0].Price)
</th>
<th>
@Html.DisplayNameFor(model => model.Movie[0].Rating)
</th>
<th></th>
</tr>
</thead>
<tbody>
@foreach (var item in Model.Movie)
{
<tr>
<td>
@Html.DisplayFor(modelItem => item.Title)
</td>
<td>
@Html.DisplayFor(modelItem => item.ReleaseDate)
</td>
<td>
@Html.DisplayFor(modelItem => item.Genre)
</td>
<td>
@Html.DisplayFor(modelItem => item.Price)
</td>
<td>
@Html.DisplayFor(modelItem => item.Rating)
</td>
<td>
<a asp-page="./Edit" asp-route-
id="@item.Id">Edit</a> |
<a asp-page="./Details" asp-route-
id="@item.Id">Details</a> |
<a asp-page="./Delete" asp-route-
id="@item.Id">Delete</a>
</td>
</tr>
}
</tbody>
</table>
3. Atualize as seguintes páginas com um Rating campo:
Pages/Movies/Create.cshtml .
Pages/Movies/Delete.cshtml .
Pages/Movies/Details.cshtml .
Pages/Movies/Edit.cshtml .
O aplicativo não funcionará até que o banco de dados seja atualizado para incluir o
novo campo. A execução do aplicativo sem uma atualização no banco de dados lança
um SqlException :
SqlException: Invalid column name 'Rating'.
A SqlException exceção é causada pela classe de modelo Movie atualizada ser diferente
do esquema da tabela Movie do banco de dados. Não há nenhuma Rating coluna na
tabela do banco de dados.
Existem algumas abordagens para resolver o erro:
1. Faça com que o Entity Framework remova automaticamente e recrie o banco de
dados usando o novo esquema de classe de modelo. Essa abordagem é
conveniente no início do ciclo de desenvolvimento, ela permite que os
desenvolvedores evoluam rapidamente o modelo e o esquema de banco de dados
juntos. A desvantagem é que os dados existentes no banco de dados são perdidos.
Não use essa abordagem em um banco de dados de produção. Descartar o banco
de dados em alterações de esquema e usar um inicializador para propagar
automaticamente o banco de dados com dados de teste geralmente é uma
maneira produtiva de desenvolver um aplicativo.
2. Modifique explicitamente o esquema do banco de dados existente para que ele
corresponda às classes de modelo. A vantagem dessa abordagem é manter os
dados. Faça essa alteração manualmente ou criando um script de alteração de
banco de dados.
3. Use as Migrações do Code First para atualizar o esquema de banco de dados.
Para este tutorial, use as Migrações do Code First.
Atualize a classe SeedData para que ela forneça um valor para a nova coluna. Uma
alteração de exemplo é mostrada abaixo, mas faça essa alteração para cada new Movie
bloco.
C#
context.Movie.AddRange(
new Movie
{
Title = "When Harry Met Sally",
ReleaseDate = DateTime.Parse("1989-2-12"),
Genre = "Romantic Comedy",
Price = 7.99M,
Rating = "R"
},
Consulte o arquivo SeedData.cs concluído .
Compile a solução.
Visual Studio
Adicionar uma migração para o campo de classificação
1. No menu Ferramentas , selecione Console do Gerenciador de Pacotes do
Gerenciador de Pacotes > NuGet.
2. No PMC, insira os seguintes comandos:
PowerShell
Add-Migration Rating
Update-Database
O comando Add-Migration informa à estrutura:
Compare o Movie modelo com o esquema de Movie banco de dados.
Crie código para migrar o esquema de banco de dados para o novo modelo.
O nome “Classificação” é arbitrário e é usado para nomear o arquivo de migração. É
útil usar um nome significativo para o arquivo de migração.
O Update-Database comando informa à estrutura para aplicar as alterações de
esquema ao banco de dados e preservar os dados existentes.
Exclua todos os registros no banco de dados, o inicializador propagará o banco de
dados e incluirá o Rating campo . A exclusão pode ser feita com os links de
exclusão no navegador ou no Sql Server Pesquisador de Objetos (SSOX).
Outra opção é excluir o banco de dados e usar as migrações para recriar o banco
de dados. Para excluir o banco de dados no SSOX:
1. Selecione o banco de dados no SSOX.
2. Clique com o botão direito do mouse no banco de dados e selecione Excluir.
3. Marque Fechar conexões existentes.
4. Selecione OK.
5. No PMC, atualize o banco de dados:
PowerShell
Update-Database
Execute o aplicativo e verifique se você pode criar, editar e exibir filmes com um Rating
campo. Se o banco de dados não for propagado, defina um ponto de interrupção no
método SeedData.Initialize .
Recursos adicionais
Anterior: Adicionar Pesquisa Avançar: Adicionar Validação
Parte 8 da série de tutoriais no Razor
Pages
Artigo • 03/12/2022 • 31 minutos para o fim da leitura
De Rick Anderson
Nesta seção, a lógica de validação é adicionada para o modelo Movie . As regras de
validação são impostas sempre que um usuário cria ou edita um filme.
Validação
Um princípio-chave do desenvolvimento de software é chamado DRY (“Don't Repeat
Yourself”). Razor O Pages incentiva o desenvolvimento em que a funcionalidade é
especificada uma vez e é refletida em todo o aplicativo. O DRY pode ajudar a:
Reduzir a quantidade de código em um aplicativo.
Fazer com que o código seja menos propenso a erros e mais fácil de ser testado e
mantido.
O suporte à validação fornecido pelo Pages e pelo Razor Entity Framework é um bom
exemplo do princípio DRY:
As regras de validação são especificadas declarativamente em um só lugar, na
classe de modelo.
As regras são impostas em todos os lugares do aplicativo.
Adicionar regras de validação ao modelo de
filme
O System.ComponentModel.DataAnnotations namespace fornece:
Um conjunto de atributos de validação internos que são aplicados
declarativamente a uma classe ou propriedade.
A formatação de atributos como [DataType] esse ajuda na formatação e não
fornece nenhuma validação.
Atualize a classe Movie para aproveitar os atributos de validação [Required] ,
[StringLength] , [RegularExpression] e [Range] internos.
C#
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace RazorPagesMovie.Models;
public class Movie
{
public int Id { get; set; }
[StringLength(60, MinimumLength = 3)]
[Required]
public string Title { get; set; } = string.Empty;
// [Display(Name = "Release Date")]
[DataType(DataType.Date)]
public DateTime ReleaseDate { get; set; }
[Range(1, 100)]
[DataType(DataType.Currency)]
[Column(TypeName = "decimal(18, 2)")]
public decimal Price { get; set; }
[RegularExpression(@"^[A-Z]+[a-zA-Z\s]*$")]
[Required]
[StringLength(30)]
public string Genre { get; set; } = string.Empty;
[RegularExpression(@"^[A-Z]+[a-zA-Z0-9""'\s-]*$")]
[StringLength(5)]
[Required]
public string Rating { get; set; } = string.Empty;
}
Os atributos de validação especificam o comportamento a ser imposto nas
propriedades de modelo às quais eles são aplicados:
Os atributos [Required] e [MinimumLength] indicam que uma propriedade deve ter
um valor. Nada impede que um usuário insira espaço em branco para atender a
essa validação.
O atributo [RegularExpression] é usado para limitar quais caracteres podem ser
inseridos. No código anterior, Genre :
Deve usar apenas letras.
A primeira letra deve ser maiúscula. Espaços em branco são permitidos
enquanto números e caracteres especiais não são permitidos.
O RegularExpression Rating :
Exige que o primeiro caractere seja uma letra maiúscula.
Permite caracteres especiais e números nos espaços subsequentes. "PG-13" é
válido para uma classificação, mas falha para um Genre .
O atributo [Range] restringe um valor a um intervalo especificado.
O [StringLength] atributo pode definir um comprimento máximo de uma
propriedade de cadeia de caracteres e, opcionalmente, seu comprimento mínimo.
Tipos de valor, como decimal , int , float , DateTime , são inerentemente
necessários e não precisam do [Required] atributo .
As regras de validação anteriores são usadas para demonstração, elas não são ideais
para um sistema de produção. Por exemplo, o anterior impede a entrada de um filme
com apenas dois caracteres e não permite caracteres especiais em Genre .
Ter regras de validação automaticamente impostas pelo ASP.NET Core ajuda a:
Torne o aplicativo mais robusto.
Reduza as chances de salvar dados inválidos no banco de dados.
Interface do usuário do erro de validação em Razor
páginas
Execute o aplicativo e navegue para Pages/Movies.
Selecione o link Criar Novo . Preencha o formulário com alguns valores inválidos.
Quando a validação do lado do cliente do jQuery detecta o erro, ela exibe uma
mensagem de erro.
7 Observação
Talvez você não consiga inserir vírgulas decimais em campos decimais. Para dar
suporte à validação do jQuery para localidades de idiomas diferentes do inglês
que usam uma vírgula (“,”) para um ponto decimal e formatos de data diferentes
do inglês dos EUA, você deve tomar medidas para globalizar o aplicativo. Consulte
este comentário do GitHub 4076 para obter instruções sobre como adicionar
vírgula decimal.
Observe como o formulário renderizou automaticamente uma mensagem de erro de
validação em cada campo que contém um valor inválido. Os erros são impostos no lado
do cliente, usando JavaScript e jQuery e no lado do servidor, quando um usuário tem o
JavaScript desabilitado.
Um benefício significativo é que nenhuma alteração de código foi necessária nas
páginas Criar ou Editar. Depois que as anotações de dados foram aplicadas ao modelo,
a interface do usuário de validação foi habilitada. As Razor Páginas criadas neste tutorial
pegaram automaticamente as regras de validação usando atributos de validação nas
propriedades da Movie classe de modelo. Validação do teste usando a página Editar: a
mesma validação é aplicada.
Os dados de formulário não serão postados no servidor enquanto houver erros de
validação do lado do cliente. Verifique se os dados de formulário não são postados por
uma ou mais das seguintes abordagens:
Coloque um ponto de interrupção no método OnPostAsync . Envie o formulário
selecionando Criar ou Salvar. O ponto de interrupção nunca é atingido.
Use a ferramenta Fiddler .
Use as ferramentas do desenvolvedor do navegador para monitorar o tráfego de
rede.
Validação do servidor
Quando o JavaScript está desabilitado no navegador, o envio do formulário com erros
será postado no servidor.
(Opcional) Teste a validação do servidor:
1. Desabilite o JavaScript no navegador. O JavaScript pode ser desabilitado usando as
ferramentas de desenvolvedor do navegador. Se o JavaScript não puder ser
desabilitado no navegador, tente outro navegador.
2. Defina um ponto de interrupção no método OnPostAsync da página Criar ou Editar.
3. Envie um formulário com dados inválidos.
4. Verifique se o estado do modelo é inválido:
C#
if (!ModelState.IsValid)
{
return Page();
}
Como alternativa, desabilite a validação do lado do cliente no servidor.
O código a seguir mostra uma parte da Create.cshtml página estruturada
anteriormente no tutorial. Ele é usado pelas páginas Criar e Editar para:
Exiba o formulário inicial.
Reproduz o formulário em caso de erro.
CSHTML
<form method="post">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="Movie.Title" class="control-label"></label>
<input asp-for="Movie.Title" class="form-control" />
<span asp-validation-for="Movie.Title" class="text-danger"></span>
</div>
O Auxiliar de Marcação de Entrada usa os atributos de DataAnnotations e produz os
atributos HTML necessários para a Validação do jQuery no lado do cliente. O Auxiliar de
Marcação de Validação exibe erros de validação. Consulte Validação para obter mais
informações.
As páginas Criar e Editar não têm nenhuma regra de validação. As regras de validação e
as cadeias de caracteres de erro são especificadas somente na classe Movie . Essas regras
de validação são aplicadas automaticamente às Razor Páginas que editam o Movie
modelo.
Quando a lógica de validação precisa ser alterada, ela é feita apenas no modelo. A
validação é aplicada consistentemente em todo o aplicativo, a lógica de validação é
definida em um só lugar. A validação em um único lugar ajuda a manter o código limpo
e facilita sua manutenção e atualização.
Usar atributos DataType
Examine a classe Movie . O namespace System.ComponentModel.DataAnnotations fornece
atributos de formatação, além do conjunto interno de atributos de validação. O atributo
[DataType] é aplicado às propriedades ReleaseDate e Price .
C#
// [Display(Name = "Release Date")]
[DataType(DataType.Date)]
public DateTime ReleaseDate { get; set; }
[Range(1, 100)]
[DataType(DataType.Currency)]
[Column(TypeName = "decimal(18, 2)")]
public decimal Price { get; set; }
Os [DataType] atributos fornecem:
Dicas para o mecanismo de exibição formatar os dados.
Fornece atributos como <a> para URLs e <a href="mailto:EmailAddress.com">
para email.
Use o atributo [RegularExpression] para validar o formato dos dados. O atributo
[DataType] é usado para especificar um tipo de dados mais específico do que o tipo
intrínseco de banco de dados. [DataType] atributos não são atributos de validação. No
aplicativo de exemplo, somente a data é exibida, sem hora.
A DataType enumeração fornece muitos tipos de dados, como Date , Time , PhoneNumber ,
Currency , EmailAddress e muito mais.
Os [DataType] atributos:
Pode habilitar o aplicativo para fornecer automaticamente recursos específicos de
tipo. Por exemplo, um link mailto: pode ser criado para DataType.EmailAddress .
Pode fornecer um seletor DataType.Date de data em navegadores que dão suporte
a HTML5.
Emita HTML 5 data- , pronunciado "data dash", atributos que os navegadores
HTML 5 consomem.
Não forneça nenhuma validação.
DataType.Date não especifica o formato da data exibida. Por padrão, o campo de dados
é exibido de acordo com os formatos padrão com base nas CultureInfo do servidor.
A anotação de dados [Column(TypeName = "decimal(18, 2)")] é necessária para que o
Entity Framework Core possa mapear corretamente o Price para a moeda no banco de
dados. Para obter mais informações, veja Tipos de Dados.
O atributo [DisplayFormat] é usado para especificar explicitamente o formato de data:
C#
[DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode =
true)]
public DateTime ReleaseDate { get; set; }
A ApplyFormatInEditMode configuração especifica que a formatação será aplicada
quando o valor for exibido para edição. Esse comportamento pode não ser desejado
para alguns campos. Por exemplo, em valores de moeda, o símbolo de moeda
geralmente não é desejado na interface do usuário de edição.
O atributo [DisplayFormat] pode ser usado por si só, mas geralmente é uma boa ideia
usar o atributo [DataType] . O atributo [DataType] transmite a semântica dos dados em
vez de como renderizá-los em uma tela. O [DataType] atributo fornece os seguintes
benefícios que não estão disponíveis com [DisplayFormat] :
O navegador pode habilitar recursos HTML5, por exemplo, para mostrar um
controle de calendário, o símbolo de moeda apropriado à localidade, links de
email etc.
Por padrão, o navegador renderiza dados usando o formato correto com base em
sua localidade.
O atributo [DataType] pode permitir que a estrutura ASP.NET Core escolha o
modelo de campo correto para renderizar os dados. O DisplayFormat , se usado
por si só, usa o modelo de cadeia de caracteres.
Observação: a validação do jQuery não funciona com o [Range] atributo e DateTime .
Por exemplo, o seguinte código sempre exibirá um erro de validação do lado do cliente,
mesmo quando a data estiver no intervalo especificado:
C#
[Range(typeof(DateTime), "1/1/1966", "1/1/2020")]
É uma prática recomendada evitar a compilação de datas difíceis em modelos, portanto,
usar o [Range] atributo e DateTime não é recomendável. Use Configuração para
intervalos de datas e outros valores que estão sujeitos a alterações frequentes em vez
de especificá-la no código.
O seguinte código mostra como combinar atributos em uma linha:
C#
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace RazorPagesMovie.Models;
public class Movie
{
public int Id { get; set; }
[StringLength(60, MinimumLength = 3)]
public string Title { get; set; } = string.Empty;
[Display(Name = "Release Date"), DataType(DataType.Date)]
public DateTime ReleaseDate { get; set; }
[RegularExpression(@"^[A-Z]+[a-zA-Z\s]*$"), Required, StringLength(30)]
public string Genre { get; set; } = string.Empty;
[Range(1, 100), DataType(DataType.Currency)]
[Column(TypeName = "decimal(18, 2)")]
public decimal Price { get; set; }
[RegularExpression(@"^[A-Z]+[a-zA-Z0-9""'\s-]*$"), StringLength(5)]
public string Rating { get; set; } = string.Empty;
}
Introdução ao Razor Páginas e EF Core mostra operações avançadas EF Core com Razor
o Pages.
Aplicar migrações
As DataAnnotations aplicadas à classe alteram o esquema. Por exemplo, as
DataAnnotations aplicadas ao campo Title :
C#
[StringLength(60, MinimumLength = 3)]
[Required]
public string Title { get; set; } = string.Empty;
Limitam os caracteres a 60.
Não permitem um valor null .
Atualmente a tabela Movie tem o seguinte esquema:
SQL
CREATE TABLE [dbo].[Movie] (
[ID] INT IDENTITY (1, 1) NOT NULL,
[Title] NVARCHAR (MAX) NULL,
[ReleaseDate] DATETIME2 (7) NOT NULL,
[Genre] NVARCHAR (MAX) NULL,
[Price] DECIMAL (18, 2) NOT NULL,
[Rating] NVARCHAR (MAX) NULL,
CONSTRAINT [PK_Movie] PRIMARY KEY CLUSTERED ([ID] ASC)
);
As alterações do esquema anterior não fazem com que o EF lance uma exceção. No
entanto, crie uma migração de forma que o esquema seja consistente com o modelo.
Visual Studio
No menu Ferramentas , selecione Console do Gerenciador de Pacotes do
Gerenciador de Pacotes > NuGet. No PMC, insira os seguintes comandos:
PowerShell
Add-Migration New_DataAnnotations
Update-Database
Update-Database executa os métodos Up da classe New_DataAnnotations . Examine o
método Up :
C#
public partial class NewDataAnnotations : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AlterColumn<string>(
name: "Title",
table: "Movie",
type: "nvarchar(60)",
maxLength: 60,
nullable: false,
oldClrType: typeof(string),
oldType: "nvarchar(max)");
migrationBuilder.AlterColumn<string>(
name: "Rating",
table: "Movie",
type: "nvarchar(5)",
maxLength: 5,
nullable: false,
oldClrType: typeof(string),
oldType: "nvarchar(max)");
migrationBuilder.AlterColumn<string>(
name: "Genre",
table: "Movie",
type: "nvarchar(30)",
maxLength: 30,
nullable: false,
oldClrType: typeof(string),
oldType: "nvarchar(max)");
}
A tabela Movie atualizada tem o seguinte esquema:
SQL
CREATE TABLE [dbo].[Movie] (
[ID] INT IDENTITY (1, 1) NOT NULL,
[Title] NVARCHAR (60) NOT NULL,
[ReleaseDate] DATETIME2 (7) NOT NULL,
[Genre] NVARCHAR (30) NOT NULL,
[Price] DECIMAL (18, 2) NOT NULL,
[Rating] NVARCHAR (5) NOT NULL,
CONSTRAINT [PK_Movie] PRIMARY KEY CLUSTERED ([ID] ASC)
);
Publicar no Azure
Para obter informações sobre como implantar no Azure, confira Tutorial: Criar um
aplicativo ASP.NET Core no Azure com Banco de Dados SQL.
Obrigado por concluir esta introdução ao Razor Pages. Introdução ao Razor Pages e EF
Core é um excelente acompanhamento para este tutorial.
Recursos adicionais
Auxiliares de marcação em formulários no ASP.NET Core
Globalização e localização no ASP.NET Core
Auxiliares de Marca no ASP.NET Core
Auxiliares de marca de autor no ASP.NET Core
Anterior: adicionar um novo campo
Introdução ao ASP.NET Core MVC
Artigo • 15/11/2022 • 21 minutos para o fim da leitura
De Rick Anderson
Este tutorial ensina a usar o desenvolvimento Web do ASP.NET Core MVC com
controladores e exibições. Se você não estiver familiarizado com ASP.NET Core
desenvolvimento na Web, considere a Razor versão páginas deste tutorial, que fornece
um ponto de partida mais fácil. Consulte Escolher um ASP.NET Core interface do
usuário, que compara Razor Pages, MVC e Blazor para desenvolvimento de interface do
usuário.
Este é o primeiro tutorial de uma série que ensina ASP.NET Core desenvolvimento da
Web do MVC com controladores e exibições.
No final da série, você terá um aplicativo que gerencia e exibe dados de filme. Você
aprenderá como:
" Crie um aplicativo Web.
" Adicionar e gerar o scaffolding de um modelo.
" Trabalhar com um banco de dados.
" Adicionar pesquisa e validação.
Exibir ou baixar um código de exemplo (como baixar).
Pré-requisitos
Visual Studio
Versão prévia mais recente do Visual Studio 2022 com a carga de trabalho
de ASP.NET e desenvolvimento web .
Criar um aplicativo Web
Visual Studio
Inicie o Visual Studio e selecione Criar um projeto.
Na caixa de diálogo Criar um novo projeto, selecione ASP.NET Core
Aplicativo Web (Model-View-Controller)>Avançar.
Na caixa de diálogo Configurar seu novo projeto , insira MvcMovie para Nome
do projeto. É importante nomear o projeto MvcMovie. A capitalização precisa
corresponder a cada namespace um quando o código é copiado.
Selecione Avançar.
Na caixa de diálogo Informações adicionais:
Selecione .NET 7.0.
Verifique se Não usar instruções de nível superior está desmarcado .
Selecione Criar.
Para obter mais informações, incluindo abordagens alternativas para criar o projeto,
consulte Criar um novo projeto no Visual Studio.
O Visual Studio usa o modelo de projeto padrão para o projeto MVC criado. O
projeto criado:
É um aplicativo funcional.
É um projeto inicial básico.
Executar o aplicativo
Visual Studio
Selecione Ctrl+F5 para executar o aplicativo sem o depurador.
O Visual Studio exibe a seguinte caixa de diálogo quando um projeto ainda
não está configurado para usar o SSL:
Selecione Sim se você confia no certificado SSL do IIS Express.
A seguinte caixa de diálogo é exibida:
Selecione Sim se você concordar com confiar no certificado de
desenvolvimento.
Para obter informações sobre como confiar no navegador Firefox, consulte
Firefox SEC_ERROR_INADEQUATE_KEY_USAGE erro de certificado.
O Visual Studio executa o aplicativo e abre o navegador padrão.
A barra de endereços mostra localhost:<port#> e não algo como example.com . O
nome do host padrão para seu computador local é localhost . Uma porta aleatória
é usada para o servidor Web quando o Visual Studio cria um projeto Web.
Iniciar o aplicativo sem depuração selecionando Ctrl+F5 permite:
Realize alterações de código.
Salve o arquivo.
Atualize rapidamente o navegador e veja as alterações de código.
Você pode iniciar o aplicativo no modo de depuração ou não depuração no menu
Depurar :
Você pode depurar o aplicativo selecionando o botão https na barra de
ferramentas :
A imagem a seguir mostra o aplicativo:
Visual Studio
Ajuda do Visual Studio
Saiba como depurar código C# usando o Visual Studio
Introdução ao IDE do Visual Studio
No próximo tutorial desta série, você aprenderá sobre o MVC e começará a escrever
algum código.
Próximo: Adicionar um controlador
Parte 2, adicione um controlador a um
aplicativo MVC ASP.NET Core
Artigo • 02/12/2022 • 19 minutos para o fim da leitura
De Rick Anderson
O padrão de arquitetura MVC (Model-View-Controller) separa um aplicativo em três
componentes principais: Model, View e Controller. O padrão MVC ajuda a criar
aplicativos que são mais testáveis e fáceis de atualizar comparado aos aplicativos
monolíticos tradicionais.
Os aplicativos baseados no MVC contêm:
Models: classes que representam os dados do aplicativo. As classes de modelo
usam a lógica de validação para impor regras de negócio aos dados.
Normalmente, os objetos de modelo recuperam e armazenam o estado do
modelo em um banco de dados. Neste tutorial, um modelo Movie recupera dados
de filmes de um banco de dados, fornece-os para a exibição ou atualiza-os. O
dados atualizados são gravados em um banco de dados.
Views: exibições são os componentes que exibem a interface do usuário do
aplicativo. Em geral, essa interface do usuário exibe os dados de modelo.
Controladores C: classes que:
Lidar com solicitações de navegador.
Recuperar dados do modelo.
Modelos de exibição de chamada que retornam uma resposta.
Em um aplicativo MVC, a exibição exibe apenas informações. O controlador manipula e
responde à entrada e interação do usuário. Por exemplo, o controlador manipula
segmentos de URL e valores de cadeia de caracteres de consulta e passa esses valores
para o modelo. O modelo pode usar esses valores para consultar o banco de dados. Por
exemplo:
https://localhost:5001/Home/Privacy : especifica o Home controlador e a ação
Privacy .
https://localhost:5001/Movies/Edit/5 : é uma solicitação para editar o filme com
ID=5 usando o Movies controlador e a ação Edit , que são detalhados
posteriormente no tutorial.
Os dados de rota são explicados posteriormente no tutorial.
O padrão de arquitetura MVC separa um aplicativo em três grupos principais de
componentes: Modelos, Exibições e Controladores. Esse padrão ajuda a alcançar a
separação de preocupações: a lógica da interface do usuário pertence à exibição. A
lógica de entrada pertence ao controlador. A lógica de negócios pertence ao modelo.
Essa separação ajuda a gerenciar a complexidade ao criar um aplicativo, pois permite
trabalhar em um aspecto da implementação de cada vez sem afetar o código de outro.
Por exemplo, você pode trabalhar no código de exibição sem depender do código da
lógica de negócios.
Esses conceitos são introduzidos e demonstrados nesta série de tutoriais ao criar um
aplicativo de filme. O projeto MVC contém pastas para os Controladores e as Exibições.
Adicionar um controlador
Visual Studio
Em Gerenciador de Soluções, clique com o botão direito do mouse em
Controladores > Adicionar > Controlador.
Na caixa de diálogo Adicionar Novo Item Scaffolded, selecione Controlador MVC
– Adicionar Vazio>.
Na caixa de diálogo Adicionar Novo Item – MvcMovie , insira
HelloWorldController.cs e selecione Adicionar.
Substitua o conteúdo de Controllers/HelloWorldController.cs pelo seguinte código:
C#
using Microsoft.AspNetCore.Mvc;
using System.Text.Encodings.Web;
namespace MvcMovie.Controllers;
public class HelloWorldController : Controller
{
//
// GET: /HelloWorld/
public string Index()
{
return "This is my default action...";
}
//
// GET: /HelloWorld/Welcome/
public string Welcome()
{
return "This is the Welcome action method...";
}
}
Cada método public em um controlador pode ser chamado como um ponto de
extremidade HTTP. Na amostra acima, ambos os métodos retornam uma cadeia de
caracteres. Observe os comentários que precedem cada método.
Um ponto de extremidade HTTP:
É uma URL de destino no aplicativo Web, como
https://localhost:5001/HelloWorld .
Combina:
O protocolo usado: HTTPS .
O local de rede do servidor Web, incluindo a porta TCP: localhost:5001 .
O URI de destino: HelloWorld .
O primeiro comentário indica que este é um método HTTP GET invocado por meio do
acréscimo de /HelloWorld/ à URL base.
O primeiro comentário especifica um método HTTP GET invocado por meio do
acréscimo de /HelloWorld/Welcome/ à URL base. Posteriormente no tutorial, o
mecanismo de scaffolding é usado para gerar HTTP POST métodos, que atualizam os
dados.
Execute o aplicativo sem o depurador.
Acrescente "HelloWorld" ao caminho na barra de endereços. O método Index retorna
uma cadeia de caracteres.
O MVC invoca classes de controlador e os métodos de ação dentro delas, dependendo
da URL de entrada. A lógica de roteamento de URL padrão usada pelo MVC usa um
formato como este para determinar qual código invocar:
/[Controller]/[ActionName]/[Parameters]
O formato de roteamento é definido no Program.cs arquivo .
C#
app.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
Quando você navega até o aplicativo e não fornece segmentos de URL, ele usa como
padrão o controlador "Home" e o método "Index" especificado na linha de modelo
realçada acima. Nos segmentos de URL anteriores:
O primeiro segmento de URL determina a classe do controlador a ser executada.
Portanto, localhost:5001/HelloWorld mapeia para a classe Controlador
HelloWorld .
A segunda parte do segmento de URL determina o método de ação na classe.
Portanto, localhost:5001/HelloWorld/Index faz com que o Index método da
HelloWorldController classe seja executado. Observe que você precisou apenas
navegar para localhost:5001/HelloWorld e o método Index foi chamado por
padrão. Index é o método padrão que será chamado em um controlador se um
nome de método não for especificado explicitamente.
A terceira parte do segmento de URL ( id ) refere-se aos dados de rota. Os dados
de rota são explicados posteriormente no tutorial.
Navegue até: https://localhost:{PORT}/HelloWorld/Welcome . Substitua {PORT} pelo
número da porta.
O método Welcome é executado e retorna a cadeia de caracteres This is the Welcome
action method... . Para essa URL, o controlador é HelloWorld e Welcome é o método de
ação. Você ainda não usou a parte [Parameters] da URL.
Modifique o código para passar algumas informações de parâmetro da URL para o
controlador. Por exemplo, /HelloWorld/Welcome?name=Rick&numtimes=4 .
Altere o método Welcome para incluir dois parâmetros, conforme mostrado no código a
seguir.
C#
// GET: /HelloWorld/Welcome/
// Requires using System.Text.Encodings.Web;
public string Welcome(string name, int numTimes = 1)
{
return HtmlEncoder.Default.Encode($"Hello {name}, NumTimes is:
{numTimes}");
}
O código anterior:
Usa o recurso de parâmetro opcional do C# para indicar que o parâmetro
numTimes usa 1 como padrão se nenhum valor é passado para esse parâmetro.
Usa para proteger o aplicativo contra entradas HtmlEncoder.Default.Encode mal-
intencionadas, como por meio do JavaScript.
Usa Cadeias de caracteres interpoladas em $"Hello {name}, NumTimes is:
{numTimes}" .
Execute o aplicativo e navegue até: https://localhost:{PORT}/HelloWorld/Welcome?
name=Rick&numtimes=4 . Substitua {PORT} pelo número da porta.
Experimente valores diferentes para name e numtimes na URL. O sistema de associação
de modelo MVC mapeia automaticamente os parâmetros nomeados da cadeia de
caracteres de consulta para os parâmetros no método . Consulte Model binding para
obter mais informações.
Na imagem anterior:
O segmento Parameters de URL não é usado.
Os name parâmetros e numTimes são passados na cadeia de caracteres de
consulta .
O ? (ponto de interrogação) na URL acima é um separador e a cadeia de
caracteres de consulta segue.
O & caractere separa pares campo-valor.
Substitua o método Welcome pelo seguinte código:
C#
public string Welcome(string name, int ID = 1)
{
return HtmlEncoder.Default.Encode($"Hello {name}, ID: {ID}");
}
Execute o aplicativo e insira a seguinte URL: https://localhost:
{PORT}/HelloWorld/Welcome/3?name=Rick
Na URL anterior:
O terceiro segmento de URL correspondeu ao parâmetro id de rota .
O método Welcome contém um parâmetro id que correspondeu ao modelo de
URL no método MapControllerRoute .
O à direita inicia a cadeia de ? caracteres de consulta .
C#
app.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
No exemplo anterior:
O terceiro segmento de URL correspondeu ao parâmetro id de rota .
O método Welcome contém um parâmetro id que correspondeu ao modelo de
URL no método MapControllerRoute .
O ? à direita (em id? ) indica que o parâmetro id é opcional.
Anterior: Introdução ao Próximo: Adicionar um Modo de Exibição
Parte 3, adicionar uma exibição a um
aplicativo MVC ASP.NET Core
Artigo • 02/12/2022 • 25 minutos para o fim da leitura
De Rick Anderson
Nesta seção, você modificará a HelloWorldController classe para usar arquivos de
exibição Razor . Isso encapsula corretamente o processo de geração de respostas HTML
para um cliente.
Os modelos de exibição são criados usando Razor. RazorModelos de exibição baseados
em:
Ter uma .cshtml extensão de arquivo.
Forneça uma maneira elegante de criar uma saída HTML com C#.
Atualmente, o Index método retorna uma cadeia de caracteres com uma mensagem na
classe de controlador. Na classe HelloWorldController , substitua o método Index pelo
seguinte código:
C#
public IActionResult Index()
{
return View();
}
O código anterior:
Chama o método do View controlador.
Usa um modelo de exibição para gerar uma resposta HTML.
Métodos do controlador:
São chamados de métodos de ação. Por exemplo, o método de Index ação no
código anterior.
Geralmente, retorna um IActionResult ou uma classe derivada de ActionResult, não
um tipo como string .
Adicionar uma exibição
Visual Studio
Clique com o botão direito do mouse na pasta Exibições e em Adicionar > Nova
Pasta e nomeie a pasta HelloWorld.
Clique com o botão direito do mouse na pasta Views/HelloWorld e, em seguida, em
Adicionar > Novo Item.
Na caixa de diálogo Adicionar Novo Item – MvcMovie :
Na caixa de pesquisa no canto superior direito, insira exibição
Selecionar Razor Exibição – Vazio
Mantenha o valor da caixa Nome , Index.cshtml .
Selecione Adicionar
Substitua o conteúdo do arquivo de Views/HelloWorld/Index.cshtml Razor exibição pelo
seguinte:
CSHTML
@{
ViewData["Title"] = "Index";
}
<h2>Index</h2>
<p>Hello from our View Template!</p>
Acesse o diretório https://localhost:{PORT}/HelloWorld :
O Index método na HelloWorldController executou a instrução return View(); ,
que especificou que o método deve usar um arquivo de modelo de exibição para
renderizar uma resposta ao navegador.
Um nome de arquivo de modelo de exibição não foi especificado, portanto, o MVC
usa o arquivo de exibição padrão como padrão. Quando o nome do arquivo de
exibição não é especificado, o modo de exibição padrão é retornado. A exibição
padrão tem o mesmo nome que o método de ação, Index neste exemplo. O
modelo de exibição /Views/HelloWorld/Index.cshtml é usado.
A imagem a seguir mostra a cadeia de caracteres "Olá do nosso Modelo de
Exibição!" embutida em código no modo de exibição:
Alterar exibições e páginas de layout
Selecione os links de menu MvcMovie, Homee Privacy. Cada página mostra o mesmo
layout de menu. O layout do menu é implementado no Views/Shared/_Layout.cshtml
arquivo .
Abra o arquivo Views/Shared/_Layout.cshtml .
Os modelos de layout permitem:
Especificando o layout de contêiner HTML de um site em um só lugar.
Aplicando o layout do contêiner HTML em várias páginas no site.
Localize a linha @RenderBody() . RenderBody é um espaço reservado em que todas as
páginas específicas à exibição criadas são mostradas, encapsuladas na página de layout.
Por exemplo, se você selecionar o Privacy link, a exibição Views/Home/Privacy.cshtml
será renderizada dentro do RenderBody método .
Alterar o título, o rodapé e o link de menu no
arquivo de layout
Substitua o conteúdo do Views/Shared/_Layout.cshtml arquivo pela marcação a seguir.
As alterações são realçadas:
CSHTML
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>@ViewData["Title"] - Movie App</title>
<link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.css" />
<link rel="stylesheet" href="~/css/site.css" asp-append-version="true"
/>
</head>
<body>
<header>
<nav class="navbar navbar-expand-sm navbar-toggleable-sm navbar-
light bg-white border-bottom box-shadow mb-3">
<div class="container-fluid">
<a class="navbar-brand" asp-area="" asp-controller="Movies"
asp-action="Index">Movie App</a>
<button class="navbar-toggler" type="button" data-bs-
toggle="collapse" data-bs-target=".navbar-collapse" aria-
controls="navbarSupportedContent"
aria-expanded="false" aria-label="Toggle
navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="navbar-collapse collapse d-sm-inline-flex
justify-content-between">
<ul class="navbar-nav flex-grow-1">
<li class="nav-item">
<a class="nav-link text-dark" asp-area="" asp-
controller="Home" asp-action="Index">Home</a>
</li>
<li class="nav-item">
<a class="nav-link text-dark" asp-area="" asp-
controller="Home" asp-action="Privacy">Privacy</a>
</li>
</ul>
</div>
</div>
</nav>
</header>
<div class="container">
<main role="main" class="pb-3">
@RenderBody()
</main>
</div>
<footer class="border-top footer text-muted">
<div class="container">
© 2022 - Movie App - <a asp-area="" asp-controller="Home"
asp-action="Privacy">Privacy</a>
</div>
</footer>
<script src="~/lib/jquery/dist/jquery.js"></script>
<script src="~/lib/bootstrap/dist/js/bootstrap.js"></script>
<script src="~/js/site.js" asp-append-version="true"></script>
@await RenderSectionAsync("Scripts", required: false)
</body>
</html>
A marcação anterior fez as seguintes alterações:
Três ocorrências de MvcMovie para Movie App .
O elemento de âncora <a class="navbar-brand" asp-area="" asp-
controller="Home" asp-action="Index">MvcMovie</a> para <a class="navbar-brand"
asp-controller="Movies" asp-action="Index">Movie App</a> .
Na marcação anterior, o atributo auxiliar de marca de âncora e o asp-area="" valor do
atributo foram omitidos porque este aplicativo não está usando Áreas.
Observação: o Movies controlador não foi implementado. Neste ponto, o Movie App
link não é funcional.
Salve as alterações e selecione o Privacy link. Observe como o título na guia do
navegador exibe Privacy Política – Aplicativo de Filme em vez de Privacy Política –
MvcMovie
Selecione o link Home.
Observe que o título e o texto de âncora exibem o Aplicativo de Filme. As alterações
foram feitas uma vez no modelo de layout e todas as páginas no site refletem o novo
texto do link e o novo título.
Examine o Views/_ViewStart.cshtml arquivo:
CSHTML
@{
Layout = "_Layout";
}
O Views/_ViewStart.cshtml arquivo traz o Views/Shared/_Layout.cshtml arquivo para
cada exibição. A propriedade Layout pode ser usada para definir outra exibição de
layout ou defina-a como null para que nenhum arquivo de layout seja usado.
Abra o Views/HelloWorld/Index.cshtml arquivo de exibição.
Altere o título e <h2> o elemento conforme realçado no seguinte:
CSHTML
@{
ViewData["Title"] = "Movie List";
}
<h2>My Movie List</h2>
<p>Hello from our View Template!</p>
O título e <h2> o elemento são ligeiramente diferentes, portanto, fica claro qual parte
do código altera a exibição.
ViewData["Title"] = "Movie List"; no código acima define a propriedade Title do
dicionário ViewData como “Lista de Filmes”. A propriedade Title é usada no elemento
HTML <title> na página de layout:
CSHTML
<title>@ViewData["Title"] - Movie App</title>
Salve as alterações e navegue para https://localhost:{PORT}/HelloWorld .
Observe que os seguintes foram alterados:
Título do navegador.
Título primário.
Títulos secundários.
Se não houver alterações no navegador, poderá ser armazenado em cache o conteúdo
que está sendo exibido. Pressione Ctrl+F5 no navegador para forçar a resposta do
servidor a ser carregada. O título do navegador é criado com ViewData["Title"] o que
definimos no Index.cshtml modelo de exibição e o "- Aplicativo de Filme" adicional
adicionado no arquivo de layout.
O conteúdo no modelo de exibição Index.cshtml é mesclado com o modelo de
exibição Views/Shared/_Layout.cshtml . Uma única resposta HTML é enviada ao
navegador. Os modelos de layout facilitam a realização de alterações que se aplicam a
todas as páginas de um aplicativo. Para saber mais, confira Layout.
No entanto, o pequeno bit de "dados", a mensagem "Olá do nosso Modelo de
Exibição!", é embutido em código. O aplicativo MVC tem um "V" (exibição), um "C"
(controlador), mas nenhum "M" (modelo) ainda.
Passando dados do controlador para a exibição
As ações do controlador são invocadas em resposta a uma solicitação de URL de
entrada. Uma classe de controlador é o local em que o código é escrito e que manipula
as solicitações recebidas do navegador. O controlador recupera dados de uma fonte de
dados e decide qual tipo de resposta será enviada novamente para o navegador.
Modelos de exibição podem ser usados em um controlador para gerar e formatar uma
resposta HTML para o navegador.
Os controladores são responsáveis por fornecer os dados necessários para que um
modelo de exibição renderize uma resposta.
Os modelos de exibição não devem:
Fazer lógica de negócios
Interagir diretamente com um banco de dados.
Um modelo de exibição deve funcionar apenas com os dados fornecidos a ele pelo
controlador. Manter essa "separação de preocupações" ajuda a manter o código:
Limpo.
Testável.
Sustentável.
Atualmente, o Welcome método na classe usa um name parâmetro e ID e, em
HelloWorldController seguida, gera os valores diretamente para o navegador.
Em vez de fazer com que o controlador renderize a resposta como uma cadeia de
caracteres, altere o controlador para que ele use um modelo de exibição. O modelo de
exibição gera uma resposta dinâmica, o que significa que os dados apropriados devem
ser passados do controlador para a exibição para gerar a resposta. Faça isso fazendo
com que o controlador coloque os dados dinâmicos (parâmetros) de que o modelo de
exibição precisa em um ViewData dicionário. O modelo de exibição pode acessar os
dados dinâmicos.
Em HelloWorldController.cs , altere o Welcome método para adicionar um Message valor
e NumTimes ao ViewData dicionário.
O ViewData dicionário é um objeto dinâmico, o que significa que qualquer tipo pode ser
usado. O ViewData objeto não tem propriedades definidas até que algo seja adicionado.
O sistema de associação de modelo MVC mapeia automaticamente os parâmetros
nomeados e numTimes da cadeia de caracteres name de consulta para os parâmetros no
método . O completo HelloWorldController :
C#
using Microsoft.AspNetCore.Mvc;
using System.Text.Encodings.Web;
namespace MvcMovie.Controllers;
public class HelloWorldController : Controller
{
public IActionResult Index()
{
return View();
}
public IActionResult Welcome(string name, int numTimes = 1)
{
ViewData["Message"] = "Hello " + name;
ViewData["NumTimes"] = numTimes;
return View();
}
}
O objeto de dicionário ViewData contém dados que serão passados para a exibição.
Crie um modelo de exibição de boas-vindas chamado
Views/HelloWorld/Welcome.cshtml .
Você criará um loop no modelo de exibição Welcome.cshtml que exibe "Olá" NumTimes .
Substitua o conteúdo de Views/HelloWorld/Welcome.cshtml pelo seguinte:
CSHTML
@{
ViewData["Title"] = "Welcome";
}
<h2>Welcome</h2>
<ul>
@for (int i = 0; i < (int)ViewData["NumTimes"]!; i++)
{
<li>@ViewData["Message"]</li>
}
</ul>
Salve as alterações e navegue para a seguinte URL:
https://localhost:{PORT}/HelloWorld/Welcome?name=Rick&numtimes=4
Os dados são obtidos da URL e passados para o controlador usando o associador de
modelo MVC. O controlador empacota os dados em um dicionário ViewData e passa
esse objeto para a exibição. Em seguida, a exibição renderiza os dados como HTML para
o navegador.
No exemplo anterior, o ViewData dicionário foi usado para passar dados do controlador
para uma exibição. Mais adiante no tutorial, um modelo de exibição será usado para
passar dados de um controlador para uma exibição. A abordagem do modelo de
exibição para passar dados é preferencial em relação à abordagem de ViewData
dicionário.
No próximo tutorial, será criado um banco de dados de filmes.
Anterior: Adicionar um controlador em seguida: Adicionar um modelo
Parte 4, adicionar um modelo a um
aplicativo MVC ASP.NET Core
Artigo • 06/12/2022 • 60 minutos para o fim da leitura
Por Rick Anderson e Jon P Smith .
Neste tutorial, classes são adicionadas para gerenciar filmes em um banco de dados.
Essas classes são a parte "Model" do aplicativo de VC M.
Essas classes de modelo são usadas com o Entity Framework Core (EF Core) para
trabalhar com um banco de dados. EF Core é uma estrutura orm (mapeamento
relacional de objeto) que simplifica o código de acesso a dados que você precisa
escrever.
As classes de modelo criadas são conhecidas como classes POCO , de Plain Old CLR
Objects. As classes POCO não têm nenhuma dependência em EF Core. Eles definem
apenas as propriedades dos dados a serem armazenados no banco de dados.
Neste tutorial, as classes de modelo são criadas primeiro e EF Core criam o banco de
dados.
Adicionar uma classe de modelo de dados
Visual Studio
Clique com o botão direito do mouse na pasta >ModelosAdicionar>Classe. Atribua
um nome ao arquivo Movie.cs .
Atualize o Models/Movie.cs arquivo com o seguinte código:
C#
using System.ComponentModel.DataAnnotations;
namespace MvcMovie.Models;
public class Movie
{
public int Id { get; set; }
public string? Title { get; set; }
[DataType(DataType.Date)]
public DateTime ReleaseDate { get; set; }
public string? Genre { get; set; }
public decimal Price { get; set; }
}
A classe Movie contém um campo Id , que é exigido pelo banco de dados para a chave
primária.
O DataType atributo em ReleaseDate especifica o tipo dos dados ( Date ). Com esse
atributo:
O usuário não precisa inserir informações de hora no campo de data.
Somente a data é exibida, não as informações de tempo.
DataAnnotations são abordados em um tutorial posterior.
O ponto de interrogação após string indica que a propriedade é anulável. Para obter
mais informações, confira Tipos de referência anuláveis.
Adicionar pacotes NuGet
Visual Studio
No menu Ferramentas, selecione Gerenciador de Pacotes NuGet>Console do
Gerenciador de Pacotes (PMC).
No PMC, execute os seguintes comandos:
PowerShell
Install-Package Microsoft.VisualStudio.Web.CodeGeneration.Design
Install-Package Microsoft.EntityFrameworkCore.Design
Install-Package Microsoft.EntityFrameworkCore.SqlServer
Os comandos anteriores adicionam:
O EF Core provedor de SQL Server. O pacote do provedor instala o EF Core
pacote como uma dependência.
Os utilitários usados pelos pacotes instalados automaticamente na etapa de
scaffolding, posteriormente no tutorial.
Compile o projeto como uma verificação de erros do compilador.
Aplicar scaffold a páginas de filme
Use a ferramenta de scaffolding para produzir Create páginas CRUD (, Read Update , e
Delete ) para o modelo de filme.
Visual Studio
Em Gerenciador de Soluções, clique com o botão direito do mouse na pasta
Controladores e selecione Adicionar > Novo Item Com Scaffolded.
Na caixa de diálogo Adicionar Novo Item Scaffolded , selecione Controlador MVC
com exibições, usando Entity Framework > Add.
Conclua a caixa de diálogo Adicionar Controlador MVC com exibições usando o
Entity Framework :
Na lista suspensa Classe de modelo, selecione Filme (MvcMovie.Models).
Na linha Classe de contexto de dados, selecione o sinal de + (adição).
Na caixa de diálogo Adicionar Contexto de Dados , o nome da classe
MvcMovie.Data.MvcMovieContext é gerado.
Selecione Adicionar.
Exibições e Nome do controlador: mantenha o padrão.
Selecione Adicionar.
Se você receber uma mensagem de erro, selecione Adicionar uma segunda vez
para tentar novamente.
O scaffolding atualiza o seguinte:
Insere as referências de pacote necessárias no arquivo de MvcMovie.csproj
projeto.
Registra o contexto do banco de dados no Program.cs arquivo .
Adiciona uma cadeia de conexão de banco de dados ao appsettings.json
arquivo.
O scaffolding cria o seguinte:
Um controlador de filmes: Controllers/MoviesController.cs
Razor exibir arquivos para páginas Criar, Excluir, Detalhes, Editar e Índice :
Views/Movies/*.cshtml
Uma classe de contexto de banco de dados: Data/MvcMovieContext.cs
A criação automática desses arquivos e atualizações de arquivo é conhecida como
scaffolding.
As páginas com scaffolded ainda não podem ser usadas porque o banco de dados não
existe. Executar o aplicativo e selecionar o link aplicativo de filme resulta em um Não é
possível abrir o banco de dados ou nenhuma tabela desse tipo: Mensagem de erro de
filme.
Compile o aplicativo para verificar se não há erros.
Migração inicial
Use o EF Core recurso Migrações para criar o banco de dados. As migrações são um
conjunto de ferramentas que criam e atualizam um banco de dados para corresponder
ao modelo de dados.
Visual Studio
No menu Ferramentas, selecione NuGet Package ManagerPackage Manager>
Console .
No PMC (Console do Gerenciador de Pacotes), Insira os seguintes comandos:
PowerShell
Add-Migration InitialCreate
Update-Database
Add-Migration InitialCreate : gera um arquivo de
Migrations/{timestamp}_InitialCreate.cs migração. O argumento
InitialCreate é o nome da migração. Qualquer nome pode ser usado, mas,
por convenção, um nome que descreve a migração é selecionado. Como essa
é a primeira migração, a classe gerada contém o código para criar o esquema
de banco de dados. O esquema de banco de dados é baseado no modelo
especificado na classe MvcMovieContext .
Update-Database : Atualizações o banco de dados para a migração mais
recente, que o comando anterior criou. Esse comando executa o Up método
no Migrations/{time-stamp}_InitialCreate.cs arquivo , que cria o banco de
dados.
O Update-Database comando gera o seguinte aviso:
Nenhum tipo foi especificado para a coluna decimal 'Preço' no tipo de entidade
'Filme'. Isso fará com que valores sejam truncados silenciosamente se não
couberem na precisão e na escala padrão. Especifique explicitamente o tipo de
coluna do SQL Server que pode acomodar todos os valores usando
'HasColumnType()'.
Ignore o aviso anterior, corrigido em um tutorial posterior.
Para obter mais informações sobre as ferramentas pmc para EF Core, consulte EF
Core referência de ferramentas – PMC no Visual Studio.
Testar o aplicativo
Execute o aplicativo e selecione o link Aplicativo de Filme .
Se você receber uma exceção semelhante à seguinte, talvez tenha perdido o dotnet ef
database update comando na etapa de migrações:
Visual Studio
Console
SqlException: Cannot open database "MvcMovieContext-1" requested by the
login. The login failed.
7 Observação
Talvez você não consiga inserir casas decimais ou vírgulas no campo Price . Para
dar suporte à validação do jQuery para localidades com idiomas diferentes do
inglês que usam uma vírgula (",") para um ponto decimal e formatos de data
diferentes do inglês dos EUA, o aplicativo precisa ser globalizado. Para obter
instruções sobre a globalização, consulte esse problema no GitHub .
Examinar a classe de contexto e o registro de banco de
dados gerados
Com EF Coreo , o acesso a dados é executado usando um modelo. Um modelo é feito
de classes de entidade e um objeto de contexto que representa uma sessão com o
banco de dados. O objeto de contexto permite consultar e salvar dados. O contexto de
banco de dados é derivado de Microsoft. EntityFrameworkCore.DbContext e especifica
as entidades a serem incluídas no modelo de dados.
O scaffolding cria a classe de contexto do Data/MvcMovieContext.cs banco de dados:
C#
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using MvcMovie.Models;
namespace MvcMovie.Data
{
public class MvcMovieContext : DbContext
{
public MvcMovieContext (DbContextOptions<MvcMovieContext> options)
: base(options)
{
}
public DbSet<MvcMovie.Models.Movie> Movie { get; set; }
}
}
O código anterior cria uma propriedade DbSet<Movie> que representa os filmes no
banco de dados.
Injeção de dependência
O ASP.NET Core foi criado com a DI (injeção de dependência). Serviços, como o
contexto do banco de dados, são registrados com DI no Program.cs . Esses serviços são
fornecidos a componentes que os exigem por meio de parâmetros de construtor.
Controllers/MoviesController.cs No arquivo , o construtor usa Injeção de Dependência
para injetar o contexto do MvcMovieContext banco de dados no controlador. O contexto
de banco de dados é usado em cada um dos métodos CRUD no controlador.
O scaffolding gerou o seguinte código realçado em Program.cs :
Visual Studio
C#
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddDbContext<MvcMovieContext>(options =>
options.UseSqlServer(builder.Configuration.GetConnectionString("MvcMovie
Context")));
O sistema de configuração ASP.NET Core lê a cadeia de conexão de banco de dados
"MvcMovieContext".
Examinar a cadeia de conexão de banco de dados gerada
O scaffolding adicionou uma cadeia de conexão ao appsettings.json arquivo:
Visual Studio
JSON
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*",
"ConnectionStrings": {
"MvcMovieContext": "Server=
(localdb)\\mssqllocaldb;Database=MvcMovieContext-
7dc5;Trusted_Connection=True;MultipleActiveResultSets=true"
}
}
Para desenvolvimento local, o sistema de configuração ASP.NET Core lê a
ConnectionString chave do appsettings.json arquivo.
A classe InitialCreate
Examine o Migrations/{timestamp}_InitialCreate.cs arquivo de migração:
C#
using System;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace MvcMovie.Migrations
{
public partial class InitialCreate : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "Movie",
columns: table => new
{
Id = table.Column<int>(type: "int", nullable: false)
.Annotation("SqlServer:Identity", "1, 1"),
Title = table.Column<string>(type: "nvarchar(max)",
nullable: true),
ReleaseDate = table.Column<DateTime>(type: "datetime2",
nullable: false),
Genre = table.Column<string>(type: "nvarchar(max)",
nullable: true),
Price = table.Column<decimal>(type: "decimal(18,2)",
nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Movie", x => x.Id);
});
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "Movie");
}
}
}
No código anterior:
InitialCreate.Up cria a tabela Movie e configura Id como a chave primária.
InitialCreate.Down reverte as alterações de esquema feitas pela Up migração.
Injeção de dependência no controlador
Abra o Controllers/MoviesController.cs arquivo e examine o construtor:
C#
public class MoviesController : Controller
{
private readonly MvcMovieContext _context;
public MoviesController(MvcMovieContext context)
{
_context = context;
}
O construtor usa a Injeção de Dependência para injetar o contexto de banco de dados
( MvcMovieContext ) no controlador. O contexto de banco de dados é usado em cada um
dos métodos CRUD no controlador.
Teste a página Criar. Inserir e enviar dados.
Teste os links Editar, Detalhes e Excluir.
Modelos fortemente tipado e a @model diretiva
Anteriormente neste tutorial, você viu como um controlador pode passar dados ou
objetos para uma exibição usando o dicionário ViewData . O dicionário ViewData é um
objeto dinâmico que fornece uma maneira conveniente de associação tardia para passar
informações para uma exibição.
O MVC fornece a capacidade de passar objetos de modelo fortemente tipado para uma
exibição. Essa abordagem fortemente tipada permite a verificação de código em tempo
de compilação. O mecanismo de scaffolding passou um modelo fortemente tipado na
classe e nas MoviesController exibições.
Examine o método gerado Details no Controllers/MoviesController.cs arquivo:
C#
// GET: Movies/Details/5
public async Task<IActionResult> Details(int? id)
{
if (id == null)
{
return NotFound();
}
var movie = await _context.Movie
.FirstOrDefaultAsync(m => m.Id == id);
if (movie == null)
{
return NotFound();
}
return View(movie);
}
O parâmetro id geralmente é passado como dados de rota. Por exemplo,
https://localhost:5001/movies/details/1 define:
O controlador para o movies controlador, o primeiro segmento de URL.
A ação para details , o segundo segmento de URL.
O id para 1, o último segmento de URL.
O id pode ser passado com uma cadeia de caracteres de consulta, como no exemplo a
seguir:
https://localhost:5001/movies/details?id=1
O id parâmetro é definido como um tipo anulável ( int? ) nos casos em que o id valor
não é fornecido.
Uma expressão lambda é passada para o FirstOrDefaultAsync método para selecionar
entidades de filme que correspondem aos dados de rota ou ao valor da cadeia de
caracteres de consulta.
C#
var movie = await _context.Movie
.FirstOrDefaultAsync(m => m.Id == id);
Se for encontrado um filme, uma instância do modelo Movie será passada para a
exibição Details :
C#
return View(movie);
Examine o conteúdo do Views/Movies/Details.cshtml arquivo:
CSHTML
@model MvcMovie.Models.Movie
@{
ViewData["Title"] = "Details";
}
<h1>Details</h1>
<div>
<h4>Movie</h4>
<hr />
<dl class="row">
<dt class = "col-sm-2">
@Html.DisplayNameFor(model => model.Title)
</dt>
<dd class = "col-sm-10">
@Html.DisplayFor(model => model.Title)
</dd>
<dt class = "col-sm-2">
@Html.DisplayNameFor(model => model.ReleaseDate)
</dt>
<dd class = "col-sm-10">
@Html.DisplayFor(model => model.ReleaseDate)
</dd>
<dt class = "col-sm-2">
@Html.DisplayNameFor(model => model.Genre)
</dt>
<dd class = "col-sm-10">
@Html.DisplayFor(model => model.Genre)
</dd>
<dt class = "col-sm-2">
@Html.DisplayNameFor(model => model.Price)
</dt>
<dd class = "col-sm-10">
@Html.DisplayFor(model => model.Price)
</dd>
</dl>
</div>
<div>
<a asp-action="Edit" asp-route-id="@Model.Id">Edit</a> |
<a asp-action="Index">Back to List</a>
</div>
A instrução @model na parte superior do arquivo de exibição especifica o tipo de objeto
que a exibição espera. Quando o controlador de filme foi criado, a seguinte instrução
@model foi incluída:
CSHTML
@model MvcMovie.Models.Movie
Essa diretiva @model permite o acesso ao filme que o controlador passou para a
exibição. O objeto Model é fortemente tipado. Por exemplo, no modo de exibição
Details.cshtml , o código passa cada campo de filme para os DisplayNameFor Auxiliares
html e DisplayFor com o objeto fortemente tipado Model . Os métodos Create e Edit
e as exibições também passam um objeto de modelo Movie .
Examine a exibição Index.cshtml e o Index método no controlador Movies. Observe
como o código cria um objeto List quando ele chama o método View . O código passa
esta lista Movies do método de ação Index para a exibição:
C#
// GET: Movies
public async Task<IActionResult> Index(string searchString)
{
return _context.Movie != null ?
View(await _context.Movie.ToListAsync()) :
Problem("Entity set 'MvcMovieContext.Movie' is null.");
}
O código retornará detalhes do problema se a Movie propriedade do contexto de dados
for nula.
Quando o controlador de filmes foi criado, o scaffolding incluiu a seguinte @model
instrução na parte superior do Index.cshtml arquivo:
CSHTML
@model IEnumerable<MvcMovie.Models.Movie>
A @model diretiva permite acesso à lista de filmes que o controlador passou para a
exibição usando um Model objeto fortemente tipado. Por exemplo, no modo de
exibição Index.cshtml , o código percorre os filmes com uma foreach instrução sobre o
objeto fortemente tipado Model :
CSHTML
@model IEnumerable<MvcMovie.Models.Movie>
@{
ViewData["Title"] = "Index";
}
<h1>Index</h1>
<p>
<a asp-action="Create">Create New</a>
</p>
<table class="table">
<thead>
<tr>
<th>
@Html.DisplayNameFor(model => model.Title)
</th>
<th>
@Html.DisplayNameFor(model => model.ReleaseDate)
</th>
<th>
@Html.DisplayNameFor(model => model.Genre)
</th>
<th>
@Html.DisplayNameFor(model => model.Price)
</th>
<th></th>
</tr>
</thead>
<tbody>
@foreach (var item in Model) {
<tr>
<td>
@Html.DisplayFor(modelItem => item.Title)
</td>
<td>
@Html.DisplayFor(modelItem => item.ReleaseDate)
</td>
<td>
@Html.DisplayFor(modelItem => item.Genre)
</td>
<td>
@Html.DisplayFor(modelItem => item.Price)
</td>
<td>
<a asp-action="Edit" asp-route-id="@item.Id">Edit</a> |
<a asp-action="Details" asp-route-id="@item.Id">Details</a>
|
<a asp-action="Delete" asp-route-id="@item.Id">Delete</a>
</td>
</tr>
}
</tbody>
</table>
Como o Model objeto é fortemente tipado como um IEnumerable<Movie> objeto , cada
item no loop é digitado como Movie . Entre outros benefícios, o compilador valida os
tipos usados no código.
Recursos adicionais
Entity Framework Core para iniciantes
Auxiliares de Marcas
Globalização e localização
Anterior: adicionando uma exibição a seguir: trabalhando com SQL
Parte 5, trabalhe com um banco de
dados em um aplicativo MVC ASP.NET
Core
Artigo • 02/12/2022 • 15 minutos para o fim da leitura
Por Rick Anderson e Jon P Smith .
O objeto MvcMovieContext cuida da tarefa de se conectar ao banco de dados e mapear
objetos Movie para registros do banco de dados. O contexto do banco de dados é
registrado com o contêiner injeção de dependência no Program.cs arquivo:
Visual Studio
C#
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddDbContext<MvcMovieContext>(options =>
options.UseSqlServer(builder.Configuration.GetConnectionString("MvcMovie
Context")));
O sistema de configuração de ASP.NET Core lê a ConnectionString chave. Para
desenvolvimento local, ele obtém a cadeia de conexão do appsettings.json
arquivo:
JSON
"ConnectionStrings": {
"MvcMovieContext": "Server=
(localdb)\\mssqllocaldb;Database=MvcMovieContext-
7dc5;Trusted_Connection=True;MultipleActiveResultSets=true"
}
Quando o aplicativo é implantado em um servidor de teste ou de produção, uma
variável de ambiente pode ser usada para definir a cadeia de conexão como um SQL
Server de produção. Para obter mais informações, confira Configuração.
Visual Studio
SQL Server Express LocalDB
LocalDB:
É uma versão leve do Mecanismo de Banco de Dados SQL Server Express,
instalada por padrão com o Visual Studio.
Inicia sob demanda usando uma cadeia de conexão.
É direcionado para o desenvolvimento de programas. Ele é executado no
modo de usuário, portanto, não há configuração complexa.
Por padrão, cria arquivos .mdf no diretório C:/Users/{user} .
Propagar o banco de dados
Crie uma nova classe chamada SeedData na pasta Models. Substitua o código gerado
pelo seguinte:
C#
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using MvcMovie.Data;
using System;
using System.Linq;
namespace MvcMovie.Models;
public static class SeedData
{
public static void Initialize(IServiceProvider serviceProvider)
{
using (var context = new MvcMovieContext(
serviceProvider.GetRequiredService<
DbContextOptions<MvcMovieContext>>()))
{
// Look for any movies.
if (context.Movie.Any())
{
return; // DB has been seeded
}
context.Movie.AddRange(
new Movie
{
Title = "When Harry Met Sally",
ReleaseDate = DateTime.Parse("1989-2-12"),
Genre = "Romantic Comedy",
Price = 7.99M
},
new Movie
{
Title = "Ghostbusters ",
ReleaseDate = DateTime.Parse("1984-3-13"),
Genre = "Comedy",
Price = 8.99M
},
new Movie
{
Title = "Ghostbusters 2",
ReleaseDate = DateTime.Parse("1986-2-23"),
Genre = "Comedy",
Price = 9.99M
},
new Movie
{
Title = "Rio Bravo",
ReleaseDate = DateTime.Parse("1959-4-15"),
Genre = "Western",
Price = 3.99M
}
);
context.SaveChanges();
}
}
}
Se houver filmes no banco de dados, o inicializador de semente retornará e nenhum
filme será adicionado.
C#
if (context.Movie.Any())
{
return; // DB has been seeded.
}
Adicionar o inicializador de semeadura
Visual Studio
Substitua o conteúdo de Program.cs pelo seguinte código. O novo código está
realçado.
C#
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using MvcMovie.Data;
using MvcMovie.Models;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddDbContext<MvcMovieContext>(options =>
options.UseSqlServer(builder.Configuration.GetConnectionString("MvcMovie
Context")));
// Add services to the container.
builder.Services.AddControllersWithViews();
var app = builder.Build();
using (var scope = app.Services.CreateScope())
{
var services = scope.ServiceProvider;
SeedData.Initialize(services);
}
// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Home/Error");
// The default HSTS value is 30 days. You may want to change this
for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthorization();
app.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
app.Run();
Exclua todos os registros no banco de dados. Faça isso com os links Excluir no
navegador ou no SSOX.
Testar o aplicativo. Force o aplicativo a inicializar, chamando o código no
Program.cs arquivo para que o método de semente seja executado. Para forçar a
inicialização, feche a janela do prompt de comando que o Visual Studio abriu e
reinicie pressionando Ctrl+F5.
O aplicativo mostra os dados propagados.
Anterior: adicionando um modelo
Next: adicionando métodos e exibições do controlador
Parte 6, métodos de controlador e
exibições no ASP.NET Core
Artigo • 02/12/2022 • 27 minutos para o fim da leitura
De Rick Anderson
Temos um bom começo para o aplicativo de filme, mas a apresentação não é ideal. Por
exemplo, ReleaseDate deveria ser separado em duas palavras.
Abra o Models/Movie.cs arquivo e adicione as linhas realçadas mostradas abaixo:
C#
using System;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace MvcMovie.Models;
public class Movie
{
public int Id { get; set; }
public string? Title { get; set; }
[Display(Name = "Release Date")]
[DataType(DataType.Date)]
public DateTime ReleaseDate { get; set; }
public string? Genre { get; set; }
[Column(TypeName = "decimal(18, 2)")]
public decimal Price { get; set; }
}
DataAnnotations são explicados no próximo tutorial. O atributo Display especifica o que
deve ser exibido no nome de um campo (neste caso, “Release Date” em vez de
“ReleaseDate”). O atributo DataType especifica o tipo de dados (Data) e, portanto, as
informações de hora armazenadas no campo não são exibidas.
A anotação de dados [Column(TypeName = "decimal(18, 2)")] é necessária para que o
Entity Framework Core possa mapear corretamente o Price para a moeda no banco de
dados. Para obter mais informações, veja Tipos de Dados.
Procure o controlador Movies e mantenha o ponteiro do mouse pressionado sobre um
link Editar para ver a URL de destino.
Os links Editar, Detalhes e Excluir são gerados pelo Auxiliar de Marca de Âncora MVC
Principal no Views/Movies/Index.cshtml arquivo.
CSHTML
<a asp-action="Edit" asp-route-id="@item.Id">Edit</a> |
<a asp-action="Details" asp-route-id="@item.Id">Details</a> |
<a asp-action="Delete" asp-route-id="@item.Id">Delete</a>
</td>
</tr>
Os Auxiliares de Marcação permitem que o código do servidor participe da criação e
renderização de elementos HTML em arquivos do Razor. No código acima, o
AnchorTagHelper gera dinamicamente o valor do atributo HTML href do método de
ação do controlador e da ID de rota. Use Exibir Fonte do navegador favorito ou use as
ferramentas de desenvolvedor para examinar a marcação gerada. Uma parte do HTML
gerado é mostrada abaixo:
HTML
<td>
<a href="/Movies/Edit/4"> Edit </a> |
<a href="/Movies/Details/4"> Details </a> |
<a href="/Movies/Delete/4"> Delete </a>
</td>
Lembre-se do formato para o conjunto de roteamento no Program.cs arquivo:
C#
app.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
O ASP.NET Core converte https://localhost:5001/Movies/Edit/4 de uma solicitação no
método de ação Edit do controlador Movies com o parâmetro Id igual a 4. (Os
métodos do controlador também são conhecidos como métodos de ação.)
Os Auxiliares de Marcação são um dos novos recursos mais populares do ASP.NET Core.
Para obter mais informações, consulte Recursos adicionais.
Abra o controlador Movies e examine os dois métodos de ação Edit . O código a seguir
mostra o HTTP GET Edit método , que busca o filme e preenche o formulário de edição
gerado pelo Edit.cshtml Razor arquivo.
C#
// GET: Movies/Edit/5
public async Task<IActionResult> Edit(int? id)
{
if (id == null)
{
return NotFound();
}
var movie = await _context.Movie.FindAsync(id);
if (movie == null)
{
return NotFound();
}
return View(movie);
}
O código a seguir mostra o método HTTP POST Edit , que processa os valores de filmes
postados:
C#
// POST: Movies/Edit/5
// To protect from overposting attacks, enable the specific properties you
want to bind to.
// For more details, see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Edit(int id,
[Bind("Id,Title,ReleaseDate,Genre,Price,Rating")] Movie movie)
{
if (id != movie.Id)
{
return NotFound();
}
if (ModelState.IsValid)
{
try
{
_context.Update(movie);
await _context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if (!MovieExists(movie.Id))
{
return NotFound();
}
else
{
throw;
}
}
return RedirectToAction(nameof(Index));
}
return View(movie);
}
O atributo [Bind] é uma maneira de proteger contra o excesso de postagem. Você
somente deve incluir as propriedades do atributo [Bind] que deseja alterar. Para obter
mais informações, consulte Proteger o controlador contra o excesso de postagem.
ViewModels fornece uma abordagem alternativa para prevenir o excesso de
postagem.
Observe se o segundo método de ação Edit é precedido pelo atributo [HttpPost] .
C#
// POST: Movies/Edit/5
// To protect from overposting attacks, enable the specific properties you
want to bind to.
// For more details, see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Edit(int id,
[Bind("Id,Title,ReleaseDate,Genre,Price,Rating")] Movie movie)
{
if (id != movie.Id)
{
return NotFound();
}
if (ModelState.IsValid)
{
try
{
_context.Update(movie);
await _context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if (!MovieExists(movie.Id))
{
return NotFound();
}
else
{
throw;
}
}
return RedirectToAction(nameof(Index));
}
return View(movie);
}
O atributo HttpPost especifica que esse método Edit pode ser invocado somente para
solicitações POST . Você pode aplicar o atributo [HttpGet] ao primeiro método de
edição, mas isso não é necessário porque [HttpGet] é o padrão.
O ValidateAntiForgeryToken atributo é usado para impedir a falsificação de uma
solicitação e é emparelhado com um token anti-falsificação gerado no arquivo de
exibição de edição ( Views/Movies/Edit.cshtml ). O arquivo de exibição de edição gera o
token antifalsificação com o Auxiliar de Marcação de Formulário.
CSHTML
<form asp-action="Edit">
O Auxiliar de Marcação de Formulário gera um token antifalsificação oculto que deve
corresponder ao token antifalsificação gerado [ValidateAntiForgeryToken] no método
Edit do controlador Movies. Para obter mais informações, consulte Impedir ataques de
XSRF/CSRF (solicitação intersite forjada) no ASP.NET Core.
O método HttpGet Edit usa o parâmetro ID de filme, pesquisa o filme usando o
método FindAsync do Entity Framework e retorna o filme selecionado para a exibição
de Edição. Se um filme não for encontrado, NotFound (HTTP 404) será retornado.
C#
// GET: Movies/Edit/5
public async Task<IActionResult> Edit(int? id)
{
if (id == null)
{
return NotFound();
}
var movie = await _context.Movie.FindAsync(id);
if (movie == null)
{
return NotFound();
}
return View(movie);
}
Quando o sistema de scaffolding criou a exibição de Edição, ele examinou a classe
Movie e o código criado para renderizar os elementos <label> e <input> de cada
propriedade da classe. O seguinte exemplo mostra a exibição de Edição que foi gerada
pelo sistema de scaffolding do Visual Studio:
CSHTML
@model MvcMovie.Models.Movie
@{
ViewData["Title"] = "Edit";
}
<h1>Edit</h1>
<h4>Movie</h4>
<hr />
<div class="row">
<div class="col-md-4">
<form asp-action="Edit">
<div asp-validation-summary="ModelOnly" class="text-danger">
</div>
<input type="hidden" asp-for="Id" />
<div class="form-group">
<label asp-for="Title" class="control-label"></label>
<input asp-for="Title" class="form-control" />
<span asp-validation-for="Title" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="ReleaseDate" class="control-label"></label>
<input asp-for="ReleaseDate" class="form-control" />
<span asp-validation-for="ReleaseDate" class="text-danger">
</span>
</div>
<div class="form-group">
<label asp-for="Genre" class="control-label"></label>
<input asp-for="Genre" class="form-control" />
<span asp-validation-for="Genre" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Price" class="control-label"></label>
<input asp-for="Price" class="form-control" />
<span asp-validation-for="Price" class="text-danger"></span>
</div>
<div class="form-group">
<input type="submit" value="Save" class="btn btn-primary" />
</div>
</form>
</div>
</div>
<div>
<a asp-action="Index">Back to List</a>
</div>
@section Scripts {
@{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}
Observe como o modelo de exibição tem uma instrução @model MvcMovie.Models.Movie
na parte superior do arquivo. @model MvcMovie.Models.Movie especifica que a exibição
espera que o modelo de exibição seja do tipo Movie .
O código com scaffolding usa vários métodos de Auxiliares de Marcação para simplificar
a marcação HTML. O Auxiliar de Marca de Rótulo exibe o nome do campo ("Title",
"ReleaseDate", "Genre" ou "Price"). O Auxiliar de Marcação de Entrada renderiza um
elemento <input> HTML. O Auxiliar de Marcação de Validação exibe todas as
mensagens de validação associadas a essa propriedade.
Execute o aplicativo e navegue para a URL /Movies . Clique em um link Editar . No
navegador, exiba a origem da página. O HTML gerado para o elemento <form> é
mostrado abaixo.
HTML
<form action="/Movies/Edit/7" method="post">
<div class="form-horizontal">
<h4>Movie</h4>
<hr />
<div class="text-danger" />
<input type="hidden" data-val="true" data-val-required="The ID field
is required." id="ID" name="ID" value="7" />
<div class="form-group">
<label class="control-label col-md-2" for="Genre" />
<div class="col-md-10">
<input class="form-control" type="text" id="Genre"
name="Genre" value="Western" />
<span class="text-danger field-validation-valid" data-
valmsg-for="Genre" data-valmsg-replace="true"></span>
</div>
</div>
<div class="form-group">
<label class="control-label col-md-2" for="Price" />
<div class="col-md-10">
<input class="form-control" type="text" data-val="true"
data-val-number="The field Price must be a number." data-val-required="The
Price field is required." id="Price" name="Price" value="3.99" />
<span class="text-danger field-validation-valid" data-
valmsg-for="Price" data-valmsg-replace="true"></span>
</div>
</div>
<!-- Markup removed for brevity -->
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Save" class="btn btn-default" />
</div>
</div>
</div>
<input name="__RequestVerificationToken" type="hidden"
value="CfDJ8Inyxgp63fRFqUePGvuI5jGZsloJu1L7X9le1gy7NCIlSduCRx9jDQClrV9pOTTmq
UyXnJBXhmrjcUVDJyDUMm7-
MF_9rK8aAZdRdlOri7FmKVkRe_2v5LIHGKFcTjPrWPYnc9AdSbomkiOSaTEg7RU" />
</form>
Os elementos <input> estão em um elemento HTML <form> cujo atributo action está
definido para ser postado para a URL /Movies/Edit/id . Os dados de formulário serão
postados com o servidor quando o botão Save receber um clique. A última linha antes
do elemento </form> de fechamento mostra o token XSRF oculto gerado pelo Auxiliar
de Marcação de Formulário.
Processando a solicitação POST
A lista a seguir mostra a versão [HttpPost] do método de ação Edit .
C#
// POST: Movies/Edit/5
// To protect from overposting attacks, enable the specific properties you
want to bind to.
// For more details, see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Edit(int id,
[Bind("Id,Title,ReleaseDate,Genre,Price,Rating")] Movie movie)
{
if (id != movie.Id)
{
return NotFound();
}
if (ModelState.IsValid)
{
try
{
_context.Update(movie);
await _context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if (!MovieExists(movie.Id))
{
return NotFound();
}
else
{
throw;
}
}
return RedirectToAction(nameof(Index));
}
return View(movie);
}
O atributo [ValidateAntiForgeryToken] valida o token XSRF oculto gerado pelo gerador
de tokens antifalsificação no Auxiliar de Marcação de Formulário
O sistema de model binding usa os valores de formulário postados e cria um objeto
Movie que é passado como o parâmetro movie . A ModelState.IsValid propriedade
verifica se os dados enviados no formulário podem ser usados para modificar (editar ou
atualizar) um Movie objeto. Se os dados forem válidos, eles serão salvos. Os dados de
filmes atualizados (editados) são salvos no banco de dados chamando o método
SaveChangesAsync do contexto de banco de dados. Depois de salvar os dados, o código
redireciona o usuário para o método de ação Index da classe MoviesController , que
exibe a coleção de filmes, incluindo as alterações feitas recentemente.
Antes que o formulário seja postado no servidor, a validação do lado do cliente verifica
as regras de validação nos campos. Se houver erros de validação, será exibida uma
mensagem de erro e o formulário não será postado. Se o JavaScript estiver desabilitado,
você não terá a validação do lado do cliente, mas o servidor detectará os valores
postados que não forem válidos e os valores de formulário serão exibidos novamente
com mensagens de erro. Mais adiante no tutorial, examinamos a Validação de Modelos
mais detalhadamente. O Auxiliar de Marca de Validação no Views/Movies/Edit.cshtml
modelo de exibição cuida da exibição de mensagens de erro apropriadas.
Todos os métodos HttpGet no controlador de filme seguem um padrão semelhante.
Eles obtêm um objeto de filme (ou uma lista de objetos, no caso de Index ) e passam o
objeto (modelo) para a exibição. O método Create passa um objeto de filme vazio para
a exibição Create . Todos os métodos que criam, editam, excluem ou, de outro modo,
modificam dados fazem isso na sobrecarga [HttpPost] do método. A modificação de
dados em um método HTTP GET é um risco de segurança. A modificação de dados em
um HTTP GET método também viola as práticas recomendadas de HTTP e o padrão de
arquitetura REST , que especifica que as solicitações GET não devem alterar o estado
do aplicativo. Em outras palavras, a execução de uma operação GET deve ser uma
operação segura que não tem efeitos colaterais e não modifica os dados persistentes.
Recursos adicionais
Globalização e localização
Introdução aos auxiliares de marcação
Auxiliares de marca de autor
Impedir ataques XSRF/CSRF (solicitação entre sites) em ASP.NET Core
Proteger o controlador contra o excesso de postagem
ViewModels
Auxiliar de Marcação de formulário
Auxiliar de marcação de entrada
Auxiliar de marcação de rótulo
Auxiliar de Marcação de seleção
Auxiliar de marcação de validação
Anterior Avançar
Parte 7, adicionar pesquisa a um
aplicativo MVC ASP.NET Core
Artigo • 02/12/2022 • 23 minutos para o fim da leitura
De Rick Anderson
Nesta seção, você adiciona a funcionalidade de pesquisa ao método de ação Index que
permite pesquisar filmes por gênero ou nome.
Atualize o Index método encontrado dentro Controllers/MoviesController.cs com o
seguinte código:
C#
public async Task<IActionResult> Index(string searchString)
{
if (_context.Movie == null)
{
return Problem("Entity set 'MvcMovieContext.Movie' is null.");
}
var movies = from m in _context.Movie
select m;
if (!String.IsNullOrEmpty(searchString))
{
movies = movies.Where(s => s.Title!.Contains(searchString));
}
return View(await movies.ToListAsync());
}
A seguinte linha no método de Index ação cria uma consulta LINQ para selecionar os
filmes:
C#
var movies = from m in _context.Movie
select m;
A consulta só é definida neste ponto, ela não foi executada no banco de dados.
Se o parâmetro searchString contiver uma cadeia de caracteres, a consulta de filmes
será modificada para filtrar o valor da cadeia de caracteres de pesquisa:
C#
if (!String.IsNullOrEmpty(searchString))
{
movies = movies.Where(s => s.Title!.Contains(searchString));
}
O código s => s.Title!.Contains(searchString) acima é uma Expressão Lambda.
Lambdas são usados em consultas LINQ baseadas em método como argumentos para
métodos de operador de consulta padrão, como o Where método ou Contains (usado
no código acima). As consultas LINQ não são executadas quando são definidas ou no
momento em que são modificadas com uma chamada a um método, como Where ,
Contains ou OrderBy . Em vez disso, a execução da consulta é adiada. Isso significa que
a avaliação de uma expressão é atrasada até que seu valor realizado seja, de fato,
iterado ou o método ToListAsync seja chamado. Para obter mais informações sobre a
execução de consulta adiada, consulte Execução da consulta.
Observação: o Contains método é executado no banco de dados, não no código c#
mostrado acima. A diferenciação de maiúsculas e minúsculas na consulta depende do
banco de dados e da ordenação. No SQL Server, Contains é mapeado para SQL LIKE,
que não diferencia maiúsculas de minúsculas. No SQLite, com a ordenação padrão, ele
diferencia maiúsculas de minúsculas.
Navegue até /Movies/Index . Acrescente uma cadeia de consulta, como ?
searchString=Ghost , à URL. Os filmes filtrados são exibidos.
Se você alterar a assinatura do Index método para ter um parâmetro chamado id , o id
parâmetro corresponderá ao espaço reservado opcional {id} para as rotas padrão
definidas em Program.cs .
C#
app.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
Altere o parâmetro para id e altere todas as ocorrências de searchString para id .
O método Index anterior:
C#
public async Task<IActionResult> Index(string searchString)
{
if (_context.Movie == null)
{
return Problem("Entity set 'MvcMovieContext.Movie' is null.");
}
var movies = from m in _context.Movie
select m;
if (!String.IsNullOrEmpty(searchString))
{
movies = movies.Where(s => s.Title!.Contains(searchString));
}
return View(await movies.ToListAsync());
}
O método Index atualizado com o parâmetro id :
C#
public async Task<IActionResult> Index(string id)
{
if (_context.Movie == null)
{
return Problem("Entity set 'MvcMovieContext.Movie' is null.");
}
var movies = from m in _context.Movie
select m;
if (!String.IsNullOrEmpty(id))
{
movies = movies.Where(s => s.Title!.Contains(id));
}
return View(await movies.ToListAsync());
}
Agora você pode passar o título de pesquisa como dados de rota (um segmento de
URL), em vez de como um valor de cadeia de consulta.
No entanto, você não pode esperar que os usuários modifiquem a URL sempre que
desejarem pesquisar um filme. Agora você adicionará os elementos da interface do
usuário para ajudá-los a filtrar filmes. Se você tiver alterado a assinatura do método
Index para testar como passar o parâmetro ID associado à rota, altere-o novamente
para que ele use um parâmetro chamado searchString :
C#
public async Task<IActionResult> Index(string searchString)
{
if (_context.Movie == null)
{
return Problem("Entity set 'MvcMovieContext.Movie' is null.");
}
var movies = from m in _context.Movie
select m;
if (!String.IsNullOrEmpty(searchString))
{
movies = movies.Where(s => s.Title!.Contains(searchString));
}
return View(await movies.ToListAsync());
}
Abra o Views/Movies/Index.cshtml arquivo e adicione a <form> marcação realçada
abaixo:
CSHTML
@model IEnumerable<MvcMovie.Models.Movie>
@{
ViewData["Title"] = "Index";
}
<h2>Index</h2>
<p>
<a asp-action="Create">Create New</a>
</p>
<form asp-controller="Movies" asp-action="Index">
<p>
Title: <input type="text" name="SearchString" />
<input type="submit" value="Filter" />
</p>
</form>
A marcação <form> HTML usa o Auxiliar de Marcação de Formulário. Portanto, quando
você enviar o formulário, a cadeia de caracteres de filtro será enviada para a ação Index
do controlador de filmes. Salve as alterações e, em seguida, teste o filtro.
Não há nenhuma sobrecarga [HttpPost] do método Index que poderia ser esperada.
Isso não é necessário, porque o método não está alterando o estado do aplicativo,
apenas filtrando os dados.
Você poderá adicionar o método [HttpPost] Index a seguir.
C#
[HttpPost]
public string Index(string searchString, bool notUsed)
{
return "From [HttpPost]Index: filter on " + searchString;
}
O parâmetro notUsed é usado para criar uma sobrecarga para o método Index .
Falaremos sobre isso mais adiante no tutorial.
Se você adicionar esse método, o chamador de ação fará uma correspondência com o
método [HttpPost] Index e o método [HttpPost] Index será executado conforme
mostrado na imagem abaixo.
No entanto, mesmo se você adicionar esta versão [HttpPost] do método Index , haverá
uma limitação na forma de como isso tudo foi implementado. Imagine que você deseja
adicionar uma pesquisa específica como Favoritos ou enviar um link para seus amigos
para que eles possam clicar para ver a mesma lista filtrada de filmes. Observe que a URL
da solicitação HTTP POST é a mesma que a URL da solicitação GET (localhost:
{PORT}/Movies/Index) – não há nenhuma informação de pesquisa na URL. As
informações de cadeia de caracteres de pesquisa são enviadas ao servidor como um
valor de campo de formulário . Verifique isso com as ferramentas do Desenvolvedor
do navegador ou a excelente ferramenta Fiddler . A imagem abaixo mostra as
ferramentas do Desenvolvedor do navegador Chrome:
Veja o parâmetro de pesquisa e o token XSRF no corpo da solicitação. Observe,
conforme mencionado no tutorial anterior, que o Auxiliar de Marcação de Formulário
gera um token antifalsificação XSRF. Não modificaremos os dados e, portanto, não
precisamos validar o token no método do controlador.
Como o parâmetro de pesquisa está no corpo da solicitação e não na URL, não é
possível capturar essas informações de pesquisa para adicionar como Favoritos ou
compartilhar com outras pessoas. Corrija isso especificando que a solicitação deve ser
HTTP GET encontrada no Views/Movies/Index.cshtml arquivo .
CSHTML
@model IEnumerable<MvcMovie.Models.Movie>
@{
ViewData["Title"] = "Index";
}
<h1>Index</h1>
<p>
<a asp-action="Create">Create New</a>
</p>
<form asp-controller="Movies" asp-action="Index" method="get">
<p>
Title: <input type="text" name="SearchString" />
<input type="submit" value="Filter" />
</p>
</form>
<table class="table">
Agora, quando você enviar uma pesquisa, a URL conterá a cadeia de consulta da
pesquisa. A pesquisa também irá para o método de ação HttpGet Index , mesmo se
você tiver um método HttpPost Index .
A seguinte marcação mostra a alteração para a marcação form :
CSHTML
<form asp-controller="Movies" asp-action="Index" method="get">
Adicionar pesquisa por gênero
Adicione a seguinte classe MovieGenreViewModel à pasta Models:
C#
using Microsoft.AspNetCore.Mvc.Rendering;
using System.Collections.Generic;
namespace MvcMovie.Models;
public class MovieGenreViewModel
{
public List<Movie>? Movies { get; set; }
public SelectList? Genres { get; set; }
public string? MovieGenre { get; set; }
public string? SearchString { get; set; }
}
O modelo de exibição do gênero de filme conterá:
Uma lista de filmes.
Uma SelectList que contém a lista de gêneros. Isso permite que o usuário
selecione um gênero na lista.
MovieGenre , que contém o gênero selecionado.
SearchString , que contém o texto que os usuários inserem na caixa de texto de
pesquisa.
Substitua o método Index em MoviesController.cs pelo seguinte código:
C#
// GET: Movies
public async Task<IActionResult> Index(string movieGenre, string
searchString)
{
if (_context.Movie == null)
{
return Problem("Entity set 'MvcMovieContext.Movie' is null.");
}
// Use LINQ to get list of genres.
IQueryable<string> genreQuery = from m in _context.Movie
orderby m.Genre
select m.Genre;
var movies = from m in _context.Movie
select m;
if (!string.IsNullOrEmpty(searchString))
{
movies = movies.Where(s => s.Title!.Contains(searchString));
}
if (!string.IsNullOrEmpty(movieGenre))
{
movies = movies.Where(x => x.Genre == movieGenre);
}
var movieGenreVM = new MovieGenreViewModel
{
Genres = new SelectList(await genreQuery.Distinct().ToListAsync()),
Movies = await movies.ToListAsync()
};
return View(movieGenreVM);
}
O código a seguir é uma consulta LINQ que recupera todos os gêneros do banco de
dados.
C#
// Use LINQ to get list of genres.
IQueryable<string> genreQuery = from m in _context.Movie
orderby m.Genre
select m.Genre;
A SelectList de gêneros é criada com a projeção dos gêneros distintos (não desejamos
que nossa lista de seleção tenha gêneros duplicados).
Quando o usuário pesquisa o item, o valor de pesquisa é mantido na caixa de pesquisa.
Adicionar pesquisa por gênero à exibição
Índice
Atualize Index.cshtml , encontrado em Views/Movies/, da seguinte maneira:
CSHTML
@model MvcMovie.Models.MovieGenreViewModel
@{
ViewData["Title"] = "Index";
}
<h1>Index</h1>
<p>
<a asp-action="Create">Create New</a>
</p>
<form asp-controller="Movies" asp-action="Index" method="get">
<p>
<select asp-for="MovieGenre" asp-items="Model.Genres">
<option value="">All</option>
</select>
Title: <input type="text" asp-for="SearchString" />
<input type="submit" value="Filter" />
</p>
</form>
<table class="table">
<thead>
<tr>
<th>
@Html.DisplayNameFor(model => model.Movies![0].Title)
</th>
<th>
@Html.DisplayNameFor(model => model.Movies![0].ReleaseDate)
</th>
<th>
@Html.DisplayNameFor(model => model.Movies![0].Genre)
</th>
<th>
@Html.DisplayNameFor(model => model.Movies![0].Price)
</th>
<th></th>
</tr>
</thead>
<tbody>
@foreach (var item in Model.Movies!)
{
<tr>
<td>
@Html.DisplayFor(modelItem => item.Title)
</td>
<td>
@Html.DisplayFor(modelItem => item.ReleaseDate)
</td>
<td>
@Html.DisplayFor(modelItem => item.Genre)
</td>
<td>
@Html.DisplayFor(modelItem => item.Price)
</td>
<td>
<a asp-action="Edit" asp-route-id="@item.Id">Edit</a> |
<a asp-action="Details" asp-route-
id="@item.Id">Details</a> |
<a asp-action="Delete" asp-route-
id="@item.Id">Delete</a>
</td>
</tr>
}
</tbody>
</table>
Examine a expressão lambda usada no auxiliar HTML a seguir:
@Html.DisplayNameFor(model => model.Movies![0].Title)
No código anterior, o Auxiliar de HTML DisplayNameFor inspeciona a propriedade Title
referenciada na expressão lambda para determinar o nome de exibição. Como a
expressão lambda é inspecionada em vez de avaliada, você não recebe uma violação de
acesso quando model , model.Movies ou model.Movies[0] é null ou vazio. Quando a
expressão lambda é avaliada (por exemplo, @Html.DisplayFor(modelItem =>
item.Title) ), os valores da propriedade do modelo são avaliados. O ! após
model.Movies é o operador tolerante a nulo, que é usado para declarar que Movies não
é nulo.
Teste o aplicativo pesquisando por gênero, título do filme e por ambos:
Anterior Avançar
Parte 8, adicionar um novo campo a um
aplicativo MVC ASP.NET Core
Artigo • 02/12/2022 • 21 minutos para o fim da leitura
De Rick Anderson
Nesta seção, as Migrações do Entity Framework Code First são usadas para:
Adicionar um novo campo ao modelo.
Migrar o novo campo para o banco de dados.
Ao usar o Code First do EF para criar automaticamente um banco de dados, o Code
First:
Adiciona uma tabela ao banco de dados para acompanhar o esquema do banco
de dados.
Verifica se o banco de dados está em sincronia com as classes de modelo das
quais foi gerado. Se ele não estiver sincronizado, o EF gerará uma exceção. Isso
facilita a descoberta de problemas de código/banco de dados inconsistente.
Adicionar uma Propriedade de Classificação ao
Modelo de Filme
Adicione uma Rating propriedade a Models/Movie.cs :
C#
using System;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace MvcMovie.Models;
public class Movie
{
public int Id { get; set; }
public string? Title { get; set; }
[Display(Name = "Release Date")]
[DataType(DataType.Date)]
public DateTime ReleaseDate { get; set; }
public string? Genre { get; set; }
[Column(TypeName = "decimal(18, 2)")]
public decimal Price { get; set; }
public string? Rating { get; set; }
}
Compilar o aplicativo
Visual Studio
Ctrl+Shift+B
Como você adicionou um novo campo à Movie classe , é necessário atualizar a lista de
associação de propriedades para que essa nova propriedade seja incluída. No
MoviesController.cs , atualize o [Bind] atributo para os Create métodos de ação e
Edit para incluir a Rating propriedade :
C#
[Bind("Id,Title,ReleaseDate,Genre,Price,Rating")]
Atualize os modelos de exibição para exibir, criar e editar a nova propriedade Rating na
exibição do navegador.
Edite o /Views/Movies/Index.cshtml arquivo e adicione um Rating campo:
CSHTML
<table class="table">
<thead>
<tr>
<th>
@Html.DisplayNameFor(model => model.Movies[0].Title)
</th>
<th>
@Html.DisplayNameFor(model => model.Movies[0].ReleaseDate)
</th>
<th>
@Html.DisplayNameFor(model => model.Movies[0].Genre)
</th>
<th>
@Html.DisplayNameFor(model => model.Movies[0].Price)
</th>
<th>
@Html.DisplayNameFor(model => model.Movies[0].Rating)
</th>
<th></th>
</tr>
</thead>
<tbody>
@foreach (var item in Model.Movies)
{
<tr>
<td>
@Html.DisplayFor(modelItem => item.Title)
</td>
<td>
@Html.DisplayFor(modelItem => item.ReleaseDate)
</td>
<td>
@Html.DisplayFor(modelItem => item.Genre)
</td>
<td>
@Html.DisplayFor(modelItem => item.Price)
</td>
<td>
@Html.DisplayFor(modelItem => item.Rating)
</td>
<td>
<a asp-action="Edit" asp-route-id="@item.Id">Edit</a> |
<a asp-action="Details" asp-route-
id="@item.Id">Details</a> |
<a asp-action="Delete" asp-route-
id="@item.Id">Delete</a>
</td>
</tr>
}
</tbody>
</table>
Atualize o /Views/Movies/Create.cshtml com um Rating campo .
Visual Studio/Visual Studio para Mac
Copie/cole o “grupo de formulário” anterior e permita que o IntelliSense ajude você
a atualizar os campos. O IntelliSense funciona com os Auxiliares de Marcação.
Atualize os modelos restantes.
Atualize a classe SeedData para que ela forneça um valor para a nova coluna. Uma
alteração de amostra é mostrada abaixo, mas é recomendável fazer essa alteração em
cada new Movie .
C#
new Movie
{
Title = "When Harry Met Sally",
ReleaseDate = DateTime.Parse("1989-1-11"),
Genre = "Romantic Comedy",
Rating = "R",
Price = 7.99M
},
O aplicativo não funcionará até que o BD seja atualizado para incluir o novo campo. Se
ele tiver sido executado agora, o seguinte SqlException será gerado:
SqlException: Invalid column name 'Rating'.
Este erro ocorre porque a classe de modelo Movie atualizada é diferente do esquema
da tabela Movie do banco de dados existente. (Não há nenhuma coluna Rating na
tabela de banco de dados.)
Existem algumas abordagens para resolver o erro:
1. Faça com que o Entity Framework remova automaticamente e recrie o banco de
dados com base no novo esquema de classe de modelo. Essa abordagem é muito
conveniente no início do ciclo de desenvolvimento, quando você está fazendo o
desenvolvimento ativo em um banco de dados de teste. Ela permite que você
desenvolva rapidamente o modelo e o esquema de banco de dados juntos. No
entanto, a desvantagem é que você perde os dados existentes no banco de dados
– portanto, você não deseja usar essa abordagem em um banco de dados de
produção! Muitas vezes, o uso de um inicializador para propagar um banco de
dados com os dados de teste automaticamente é uma maneira produtiva de
desenvolver um aplicativo. Isso é uma boa abordagem para o desenvolvimento
inicial e ao usar o SQLite.
2. Modifique explicitamente o esquema do banco de dados existente para que ele
corresponda às classes de modelo. A vantagem dessa abordagem é que você
mantém os dados. Faça essa alteração manualmente ou criando um script de
alteração de banco de dados.
3. Use as Migrações do Code First para atualizar o esquema de banco de dados.
Para este tutorial, as Migrações do Code First são usadas.
Visual Studio
No menu Ferramentas , selecione Console do Gerenciador de Pacotes do
Gerenciador de Pacotes > NuGet.
No PMC, insira os seguintes comandos:
PowerShell
Add-Migration Rating
Update-Database
O comando Add-Migration informa a estrutura de migração para examinar o atual
modelo Movie com o atual esquema de BD Movie e criar o código necessário para
migrar o BD para o novo modelo.
O nome “Classificação” é arbitrário e é usado para nomear o arquivo de migração. É
útil usar um nome significativo para o arquivo de migração.
Se você excluir todos os registros do BD, o método de inicialização propagará o BD
e incluirá o campo Rating .
Execute o aplicativo e verifique se você pode criar, editar e exibir filmes com um Rating
campo.
Anterior Avançar
Parte 9, adicionar validação a um
aplicativo MVC ASP.NET Core
Artigo • 03/12/2022 • 30 minutos para o fim da leitura
De Rick Anderson
Nesta seção:
A lógica de validação é adicionada ao modelo Movie .
Você garante que as regras de validação sejam impostas sempre que um usuário
criar ou editar um filme.
Mantendo o processo DRY
Um dos princípios de design do MVC é o DRY (“Don't Repeat Yourself”). O ASP.NET
Core MVC incentiva você a especificar a funcionalidade ou o comportamento somente
uma vez e, em seguida, refleti-lo em qualquer lugar de um aplicativo. Isso reduz a
quantidade de código que você precisa escrever e faz com que o código escrito seja
menos propenso a erros e mais fácil de testar e manter.
O suporte de validação fornecido pelo MVC e pelo Entity Framework Core Code First é
um bom exemplo do princípio DRY em ação. Especifique as regras de validação de
forma declarativa em um único lugar (na classe de modelo) e as regras são impostas em
qualquer lugar no aplicativo.
Adicionar regras de validação ao modelo de
filme
O namespace DataAnnotations fornece um conjunto de atributos de validação internos
aplicados de forma declarativa a uma classe ou propriedade. DataAnnotations também
contém atributos de formatação como DataType , que ajudam com a formatação e não
fornecem validação.
Atualize a classe Movie para aproveitar os atributos de validação Required ,
StringLength , RegularExpression e Range internos.
C#
using System;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace MvcMovie.Models;
public class Movie
{
public int Id { get; set; }
[StringLength(60, MinimumLength = 3)]
[Required]
public string? Title { get; set; }
[Display(Name = "Release Date")]
[DataType(DataType.Date)]
public DateTime ReleaseDate { get; set; }
[Range(1, 100)]
[DataType(DataType.Currency)]
[Column(TypeName = "decimal(18, 2)")]
public decimal Price { get; set; }
[RegularExpression(@"^[A-Z]+[a-zA-Z\s]*$")]
[Required]
[StringLength(30)]
public string? Genre { get; set; }
[RegularExpression(@"^[A-Z]+[a-zA-Z0-9""'\s-]*$")]
[StringLength(5)]
[Required]
public string? Rating { get; set; }
}
Os atributos de validação especificam o comportamento que você deseja impor nas
propriedades de modelo às quais eles são aplicados:
Os atributos Required e MinimumLength indicam que uma propriedade deve ter um
valor; porém, nada impede que um usuário insira um espaço em branco para
atender a essa validação.
O atributo RegularExpression é usado para limitar quais caracteres podem ser
inseridos. No código anterior, "Gênero":
Deve usar apenas letras.
A primeira letra deve ser maiúscula. Espaços em branco são permitidos
enquanto números e caracteres especiais não são permitidos.
A "Classificação" RegularExpression :
Exige que o primeiro caractere seja uma letra maiúscula.
Permite caracteres especiais e números nos espaços subsequentes. "PG-13" é
válido para uma classificação, mas é um erro em "Gênero".
O atributo Range restringe um valor a um intervalo especificado.
O atributo StringLength permite definir o tamanho máximo de uma propriedade
de cadeia de caracteres e, opcionalmente, seu tamanho mínimo.
Os tipos de valor (como decimal , int , float , DateTime ) são inerentemente
necessários e não precisam do atributo [Required] .
Ter as regras de validação automaticamente impostas pelo ASP.NET Core ajuda a tornar
seu aplicativo mais robusto. Também garante que você não se esqueça de validar algo e
inadvertidamente permita dados incorretos no banco de dados.
Interface do usuário de erro de validação
Execute o aplicativo e navegue para o controlador Movies.
Selecione o link Criar Novo para adicionar um novo filme. Preencha o formulário com
alguns valores inválidos. Assim que a validação do lado do cliente do jQuery detecta o
erro, ela exibe uma mensagem de erro.
7 Observação
Talvez você não consiga inserir vírgulas decimais em campos decimais. Para dar
suporte à validação do jQuery para localidades de idiomas diferentes do inglês
que usam uma vírgula (“,”) para um ponto decimal e formatos de data diferentes
do inglês dos EUA, você deve tomar medidas para globalizar o aplicativo. Consulte
este comentário do GitHub 4076 para obter instruções sobre como adicionar
vírgula decimal.
Observe como o formulário renderizou automaticamente uma mensagem de erro de
validação apropriada em cada campo que contém um valor inválido. Os erros são
impostos no lado do cliente (usando o JavaScript e o jQuery) e no lado do servidor (caso
um usuário tenha o JavaScript desabilitado).
Um benefício significativo é que você não precisava alterar uma única linha de código
na MoviesController classe ou no Create.cshtml modo de exibição para habilitar essa
interface do usuário de validação. O controlador e as exibições criados anteriormente
neste tutorial selecionaram automaticamente as regras de validação especificadas com
atributos de validação nas propriedades da classe de modelo Movie . Teste a validação
usando o método de ação Edit e a mesma validação é aplicada.
Os dados de formulário não serão enviados para o servidor enquanto houver erros de
validação do lado do cliente. Verifique isso colocando um ponto de interrupção no
método HTTP Post usando a ferramenta Fiddler ou as ferramentas do Desenvolvedor
F12.
Como funciona a validação
Talvez você esteja se perguntando como a interface do usuário de validação foi gerada
sem atualizações do código no controlador ou nas exibições. O código a seguir mostra
os dois métodos Create .
C#
// GET: Movies/Create
public IActionResult Create()
{
return View();
}
// POST: Movies/Create
// To protect from overposting attacks, enable the specific properties you
want to bind to.
// For more details, see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult>
Create([Bind("Id,Title,ReleaseDate,Genre,Price,Rating")] Movie movie)
{
if (ModelState.IsValid)
{
_context.Add(movie);
await _context.SaveChangesAsync();
return RedirectToAction(nameof(Index));
}
return View(movie);
}
O primeiro método de ação (HTTP GET) Create exibe o formulário Criar inicial. A
segunda versão ( [HttpPost] ) manipula a postagem de formulário. O segundo método
Create (a versão [HttpPost] ) chama ModelState.IsValid para verificar se o filme tem
erros de validação. A chamada a esse método avalia os atributos de validação que
foram aplicados ao objeto. Se o objeto tiver erros de validação, o método Create
exibirá o formulário novamente. Se não houver erros, o método salvará o novo filme no
banco de dados. Em nosso exemplo de filme, o formulário não é postado no servidor
quando há erros de validação detectados no lado do cliente; o segundo método Create
nunca é chamado quando há erros de validação do lado do cliente. Se você desabilitar o
JavaScript no navegador, a validação do cliente será desabilitada e você poderá testar o
método Create HTTP POST ModelState.IsValid detectando erros de validação.
Defina um ponto de interrupção no método [HttpPost] Create e verifique se o método
nunca é chamado; a validação do lado do cliente não enviará os dados de formulário
quando forem detectados erros de validação. Se você desabilitar o JavaScript no
navegador e, em seguida, enviar o formulário com erros, o ponto de interrupção será
atingido. Você ainda pode obter uma validação completa sem o JavaScript.
A imagem a seguir mostra como desabilitar o JavaScript no navegador Firefox.
A imagem a seguir mostra como desabilitar o JavaScript no navegador Chrome.
Depois de desabilitar o JavaScript, poste os dados inválidos e execute o depurador em
etapas.
Uma parte do Create.cshtml modelo de exibição é mostrada na seguinte marcação:
HTML
<h4>Movie</h4>
<hr />
<div class="row">
<div class="col-md-4">
<form asp-action="Create">
<div asp-validation-summary="ModelOnly" class="text-danger">
</div>
<div class="form-group">
<label asp-for="Title" class="control-label"></label>
<input asp-for="Title" class="form-control" />
<span asp-validation-for="Title" class="text-danger"></span>
</div>
@*Markup removed for brevity.*@
a marcação anterior é usada pelos métodos de ação para exibir o formulário inicial e
exibi-lo novamente em caso de erro.
O Auxiliar de Marcação de Entrada usa os atributos de DataAnnotations e produz os
atributos HTML necessários para a Validação do jQuery no lado do cliente. O Auxiliar de
Marcação de Validação exibe erros de validação. Consulte Validação para obter mais
informações.
O que é realmente interessante nessa abordagem é que o controlador nem o modelo
de exibição Create sabem nada sobre as regras de validação reais que estão sendo
impostas ou as mensagens de erro específicas exibidas. As regras de validação e as
cadeias de caracteres de erro são especificadas somente na classe Movie . Essas mesmas
regras de validação são aplicadas automaticamente à exibição Edit e a outros modelos
de exibição que podem ser criados e que editam o modelo.
Quando você precisar alterar a lógica de validação, faça isso exatamente em um lugar,
adicionando atributos de validação ao modelo (neste exemplo, a classe Movie ). Você
não precisa se preocupar se diferentes partes do aplicativo estão inconsistentes com a
forma como as regras são impostas – toda a lógica de validação será definida em um
lugar e usada em todos os lugares. Isso mantém o código muito limpo e torna-o mais
fácil de manter e desenvolver. Além disso, isso significa que você respeitará totalmente
o princípio DRY.
Usando atributos DataType
Abra o Movie.cs arquivo e examine a Movie classe . O namespace
System.ComponentModel.DataAnnotations fornece atributos de formatação, além do
conjunto interno de atributos de validação. Já aplicamos um valor de enumeração
DataType à data de lançamento e aos campos de preço. O código a seguir mostra as
propriedades ReleaseDate e Price com o atributo DataType apropriado.
C#
[Display(Name = "Release Date")]
[DataType(DataType.Date)]
public DateTime ReleaseDate { get; set; }
[Range(1, 100)]
[DataType(DataType.Currency)]
[Column(TypeName = "decimal(18, 2)")]
public decimal Price { get; set; }
Os DataType atributos fornecem apenas dicas para o mecanismo de exibição formatar
os dados e fornece elementos/atributos, como <a> para URLs e para email <a
href="mailto:EmailAddress.com"> . Use o atributo RegularExpression para validar o
formato dos dados. O atributo DataType é usado para especificar um tipo de dados
mais específico do que o tipo intrínseco de banco de dados; eles não são atributos de
validação. Nesse caso, apenas desejamos acompanhar a data, não a hora. A Enumeração
DataType fornece muitos tipos de dados, como Date, Time, PhoneNumber, Currency,
EmailAddress e muito mais. O atributo DataType também pode permitir que o aplicativo
forneça automaticamente recursos específicos a um tipo. Por exemplo, um link mailto:
pode ser criado para DataType.EmailAddress e um seletor de data pode ser fornecido
para DataType.Date em navegadores que dão suporte a HTML5. Os atributos DataType
emitem atributos data- HTML 5 (ou "data dash") que são reconhecidos pelos
navegadores HTML 5. Os atributos DataType não fornecem nenhuma validação.
DataType.Date não especifica o formato da data exibida. Por padrão, o campo de dados
é exibido de acordo com os formatos padrão com base nas CultureInfo do servidor.
O atributo DisplayFormat é usado para especificar explicitamente o formato de data:
C#
[DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode =
true)]
public DateTime ReleaseDate { get; set; }
A configuração ApplyFormatInEditMode especifica que a formatação também deve ser
aplicada quando o valor é exibido em uma caixa de texto para edição. (Talvez você não
deseje isso em alguns campos – por exemplo, para valores de moeda, provavelmente,
você não deseja exibir o símbolo de moeda na caixa de texto para edição.)
Você pode usar o atributo DisplayFormat por si só, mas geralmente é uma boa ideia
usar o atributo DataType . O atributo DataType transmite a semântica dos dados, ao
invés de apresentar como renderizá-lo em uma tela e oferece os seguintes benefícios
que você não obtém com DisplayFormat:
O navegador pode habilitar os recursos do HTML5 (por exemplo, mostrar um
controle de calendário, o símbolo de moeda apropriado à localidade, links de
email, etc.)
Por padrão, o navegador renderizará os dados usando o formato correto de
acordo com a localidade.
O atributo DataType pode permitir que o MVC escolha o modelo de campo
correto para renderizar os dados (o DisplayFormat , se usado por si só, usa o
modelo de cadeia de caracteres).
7 Observação
A validação do jQuery não funciona com os atributos Range e DateTime . Por
exemplo, o seguinte código sempre exibirá um erro de validação do lado do
cliente, mesmo quando a data estiver no intervalo especificado:
[Range(typeof(DateTime), "1/1/1966", "1/1/2020")]
Você precisará desabilitar a validação de data do jQuery para usar o atributo Range com
DateTime . Geralmente, não é uma boa prática compilar datas rígidas nos modelos e,
portanto, o uso do atributo Range e de DateTime não é recomendado.
O seguinte código mostra como combinar atributos em uma linha:
C#
using System;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace MvcMovie.Models;
public class Movie
{
public int Id { get; set; }
[StringLength(60, MinimumLength = 3)]
public string Title { get; set; }
[Display(Name = "Release Date"), DataType(DataType.Date)]
public DateTime ReleaseDate { get; set; }
[RegularExpression(@"^[A-Z]+[a-zA-Z\s]*$"), Required, StringLength(30)]
public string Genre { get; set; }
[Range(1, 100), DataType(DataType.Currency)]
[Column(TypeName = "decimal(18, 2)")]
public decimal Price { get; set; }
[RegularExpression(@"^[A-Z]+[a-zA-Z0-9""'\s-]*$"), StringLength(5)]
public string Rating { get; set; }
}
Na próxima parte da série, examinaremos o aplicativo e faremos algumas melhorias nos
métodos Details e Delete gerados automaticamente.
Recursos adicionais
Trabalhar com formulários
Globalização e localização
Introdução aos auxiliares de marcação
Auxiliares de marca de autor
Anterior Avançar
Parte 10, examine os métodos Detalhes
e Excluir de um aplicativo ASP.NET Core
Artigo • 02/12/2022 • 9 minutos para o fim da leitura
De Rick Anderson
Abra o controlador Movie e examine o método Details :
C#
// GET: Movies/Details/5
public async Task<IActionResult> Details(int? id)
{
if (id == null)
{
return NotFound();
}
var movie = await _context.Movie
.FirstOrDefaultAsync(m => m.Id == id);
if (movie == null)
{
return NotFound();
}
return View(movie);
}
O mecanismo de scaffolding MVC que criou este método de ação adiciona um
comentário mostrando uma solicitação HTTP que invoca o método. Nesse caso, é uma
solicitação GET com três segmentos de URL, o controlador Movies , o método Details e
um valor id . Lembre-se de que esses segmentos são definidos em Program.cs .
C#
app.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
O EF facilita a pesquisa de dados usando o método FirstOrDefaultAsync . Um recurso
de segurança importante interno do método é que o código verifica se o método de
pesquisa encontrou um filme antes de tentar fazer algo com ele. Por exemplo, um
hacker pode introduzir erros no site alterando a URL criada pelos links de
http://localhost:{PORT}/Movies/Details/1 para algo como http://localhost:
{PORT}/Movies/Details/12345 (ou algum outro valor que não representa um filme real).
Se você não marcou um filme nulo, o aplicativo gerará uma exceção.
Examine os métodos Delete e DeleteConfirmed .
C#
// GET: Movies/Delete/5
public async Task<IActionResult> Delete(int? id)
{
if (id == null)
{
return NotFound();
}
var movie = await _context.Movie
.FirstOrDefaultAsync(m => m.Id == id);
if (movie == null)
{
return NotFound();
}
return View(movie);
}
// POST: Movies/Delete/5
[HttpPost, ActionName("Delete")]
[ValidateAntiForgeryToken]
public async Task<IActionResult> DeleteConfirmed(int id)
{
if (_context.Movie == null)
{
return Problem("Entity set 'MvcMovieContext.Movie' is null.");
}
var movie = await _context.Movie.FindAsync(id);
_context.Movie.Remove(movie);
await _context.SaveChangesAsync();
return RedirectToAction(nameof(Index));
}
Observe que o método HTTP GET Delete não exclui o filme especificado, mas retorna
uma exibição do filme em que você pode enviar (HttpPost) a exclusão. A execução de
uma operação de exclusão em resposta a uma solicitação GET (ou, de fato, a execução
de uma operação de edição, criação ou qualquer outra operação que altera dados) abre
uma falha de segurança.
O método [HttpPost] que exclui os dados é chamado DeleteConfirmed para fornecer
ao método HTTP POST um nome ou uma assinatura exclusiva. As duas assinaturas de
método são mostradas abaixo:
C#
// GET: Movies/Delete/5
public async Task<IActionResult> Delete(int? id)
{
C#
// POST: Movies/Delete/5
[HttpPost, ActionName("Delete")]
[ValidateAntiForgeryToken]
public async Task<IActionResult> DeleteConfirmed(int id)
{
O CLR (Common Language Runtime) exige que os métodos sobrecarregados tenham
uma assinatura de parâmetro exclusiva (mesmo nome de método, mas uma lista
diferente de parâmetros). No entanto, aqui você precisa de dois métodos Delete – um
para GET e outro para POST – que têm a mesma assinatura de parâmetro. (Ambos
precisam aceitar um único inteiro como parâmetro.)
Há duas abordagens para esse problema e uma delas é fornecer aos métodos nomes
diferentes. Foi isso o que o mecanismo de scaffolding fez no exemplo anterior. No
entanto, isso apresenta um pequeno problema: o ASP.NET mapeia os segmentos de
URL para os métodos de ação por nome e se você renomear um método, o roteamento
normalmente não conseguirá encontrar esse método. A solução é o que você vê no
exemplo, que é adicionar o atributo ActionName("Delete") ao método DeleteConfirmed .
Esse atributo executa o mapeamento para o sistema de roteamento, de modo que uma
URL que inclui /Delete/ para uma solicitação POST encontre o método DeleteConfirmed .
Outra solução alternativa comum para métodos que têm nomes e assinaturas idênticos
é alterar artificialmente a assinatura do método POST para incluir um parâmetro extra
(não utilizado). Foi isso o que fizemos em uma postagem anterior quando adicionamos
o parâmetro notUsed . Você pode fazer o mesmo aqui para o método [HttpPost]
Delete :
C#
// POST: Movies/Delete/6
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Delete(int id, bool notUsed)
Publicar no Azure
Para obter informações sobre como implantar no Azure, consulte Tutorial: Criar um
aplicativo ASP.NET Core e Banco de Dados SQL no Serviço de Aplicativo do Azure.
Anterior
Tutoriais de Blazor do ASP.NET Core
Artigo • 28/11/2022 • 2 minutos para o fim da leitura
Os seguintes tutoriais estão disponíveis sobre o Blazor no ASP.NET Core:
Criar seu primeiro aplicativo Blazor (Blazor Server)
Criar um aplicativo de lista de tarefas pendentes Blazor (Blazor Server ou Blazor
WebAssembly)
Usar ASP.NET Core SignalR com Blazor (Blazor Server ou Blazor WebAssembly)
Tutoriais do ASP.NET Core Blazor Hybrid
Módulos de aprendizagem
Para obter mais informações sobre os modelos de hospedagem Blazor, Blazor Server e
Blazor WebAssembly, consulte Modelos de hospedagem de Blazor do ASP.NET Core.
Tutorial: criar uma API Web com o
ASP.NET Core
Artigo • 10/01/2023 • 69 minutos para o fim da leitura
Por Rick Anderson e Kirk Larkin
Este tutorial ensina os conceitos básicos da criação de uma API Web usando um banco
de dados.
Visão geral
Este tutorial cria a seguinte API:
API Descrição Corpo da Corpo da resposta
solicitação
GET /api/todoitems Obter todos os itens de Nenhum Matriz de itens de
tarefas pendentes tarefas pendentes
GET Obter um item por ID Nenhum Item de tarefas
/api/todoitems/{id} pendentes
POST Adicionar um novo item Item de tarefas Item de tarefas
/api/todoitems pendentes pendentes
PUT Atualizar um item existente Item de tarefas Nenhum
/api/todoitems/{id} pendentes
DELETE Excluir um item Nenhum Nenhum
/api/todoitems/{id}
O diagrama a seguir mostra o design do aplicativo.
Pré-requisitos
Visual Studio
Visual Studio 2022 com a carga de trabalho de desenvolvimento Web e do
ASP.NET.
Criar um projeto Web
Visual Studio
No menu Arquivo, selecione Novo>Projeto.
Insira API Web na caixa de pesquisa.
Selecione o modelo de API Web ASP.NET Core e selecione Avançar.
Na caixa de diálogo Configurar seu novo projeto, nomeie o projeto TodoApi e
selecione Avançar.
Na caixa de diálogo Informações adicionais:
Confirme se o Framework é .NET 7.0 (ou posterior).
Confirme se a caixa de seleção para Usar controladores (desmarcar para
usar APIs mínimas) está marcada.
Selecione Criar.
7 Observação
Para obter diretrizes sobre como adicionar pacotes a aplicativos .NET, consulte os
artigos em Instalar e gerenciar pacotes no Fluxo de trabalho de consumo de
pacotes (documentação do NuGet). Confirme as versões corretas de pacote em
NuGet.org .
Testar o projeto
O modelo de projeto cria uma WeatherForecast API com suporte para Swagger.
Visual Studio
Pressione Ctrl + F5 para execução sem o depurador.
O Visual Studio exibe a seguinte caixa de diálogo quando um projeto ainda não
está configurado para usar o SSL:
Selecione Sim se você confia no certificado SSL do IIS Express.
A seguinte caixa de diálogo é exibida:
Selecione Sim se você concordar com confiar no certificado de desenvolvimento.
Para obter informações sobre como confiar no navegador Firefox, consulte Firefox
SEC_ERROR_INADEQUATE_KEY_USAGE erro de certificado.
O Visual Studio inicia o navegador padrão e navega para https://localhost:
<port>/swagger/index.html , onde <port> é um número de porta escolhido
aleatoriamente.
A página /swagger/index.html swagger é exibida. Selecione
OBTER>Experimente>Executar. A página exibe:
O comando Curl para testar a API WeatherForecast.
A URL para testar a API WeatherForecast.
O código de resposta, o corpo e os cabeçalhos.
Uma caixa de listagem suspensa com tipos de mídia e o valor e o esquema de
exemplo.
Se a página do Swagger não aparecer, consulte este problema do GitHub .
O Swagger é usado para gerar páginas úteis de documentação e ajuda para APIs Web.
Este tutorial se concentra na criação de uma API Web. Para obter mais informações
sobre o Swagger, consulte ASP.NET Core documentação da API Web com
Swagger/OpenAPI.
Copie e cole a URL de Solicitação no navegador: https://localhost:
<port>/weatherforecast
JSON semelhante ao exemplo a seguir é retornado:
JSON
[
{
"date": "2019-07-16T19:04:05.7257911-06:00",
"temperatureC": 52,
"temperatureF": 125,
"summary": "Mild"
},
{
"date": "2019-07-17T19:04:05.7258461-06:00",
"temperatureC": 36,
"temperatureF": 96,
"summary": "Warm"
},
{
"date": "2019-07-18T19:04:05.7258467-06:00",
"temperatureC": 39,
"temperatureF": 102,
"summary": "Cool"
},
{
"date": "2019-07-19T19:04:05.7258471-06:00",
"temperatureC": 10,
"temperatureF": 49,
"summary": "Bracing"
},
{
"date": "2019-07-20T19:04:05.7258474-06:00",
"temperatureC": -1,
"temperatureF": 31,
"summary": "Chilly"
}
]
Adicionar uma classe de modelo
Um modelo é um conjunto de classes que representam os dados gerenciados pelo
aplicativo. O modelo para este aplicativo é a TodoItem classe .
Visual Studio
Em Gerenciador de Soluções, clique com o botão direito do mouse no
projeto. Selecione Adicionar>Nova Pasta. Nomeie a pasta Models .
Clique com o botão direito do mouse na Models pasta e selecione
Adicionar>Classe. Dê à classe o nome TodoItem e selecione Adicionar.
Substitua o código do modelo pelo seguinte:
C#
namespace TodoApi.Models;
public class TodoItem
{
public long Id { get; set; }
public string? Name { get; set; }
public bool IsComplete { get; set; }
}
A propriedade Id funciona como a chave exclusiva em um banco de dados relacional.
As classes de modelo podem ir para qualquer lugar no projeto, mas a Models pasta é
usada por convenção.
Adicionar um contexto de banco de dados
O contexto de banco de dados é a classe principal que coordena a funcionalidade do
Entity Framework para um modelo de dados. Essa classe é criada derivando-a da classe
Microsoft.EntityFrameworkCore.DbContext.
Visual Studio
Adicionar pacotes NuGet
No menu Ferramentas , selecione Gerenciador de Pacotes > NuGet Gerenciar
Pacotes NuGet para solução.
Selecione a guia Procurar e, em seguida, insira
Microsoft.EntityFrameworkCore.InMemory na caixa de pesquisa.
Selecione Microsoft.EntityFrameworkCore.InMemory no painel esquerdo.
Marque a caixa de seleção Projeto no painel direito e selecione Instalar.
Adicione o contexto de banco de dados
TodoContext
Clique com o botão direito do mouse na Models pasta e selecione
Adicionar>Classe. Nomeie a classe como TodoContext e clique em Adicionar.
Insira o seguinte código:
C#
using Microsoft.EntityFrameworkCore;
namespace TodoApi.Models;
public class TodoContext : DbContext
{
public TodoContext(DbContextOptions<TodoContext> options)
: base(options)
{
}
public DbSet<TodoItem> TodoItems { get; set; } = null!;
}
Registrar o contexto do banco de dados
No ASP.NET Core, serviços como o contexto de BD precisam ser registrados no
contêiner de DI (injeção de dependência). O contêiner fornece o serviço aos
controladores.
Atualize Program.cs com o seguinte código realçado:
C#
using Microsoft.EntityFrameworkCore;
using TodoApi.Models;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers();
builder.Services.AddDbContext<TodoContext>(opt =>
opt.UseInMemoryDatabase("TodoList"));
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
var app = builder.Build();
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}
app.UseHttpsRedirection();
app.UseAuthorization();
app.MapControllers();
app.Run();
O código anterior:
Adiciona using diretivas.
Adiciona o contexto de banco de dados ao contêiner de DI.
Especifica que o contexto de banco de dados usará um banco de dados em
memória.
Faça scaffold de um controlador
Visual Studio
Clique com o botão direito do mouse na pasta Controllers.
Selecione Adicionar>Novo Item Scaffolded.
Selecione Controlador de API com ações, usando o Entity Framework e, em
seguida, selecione Adicionar.
Na caixa de diálogo Adicionar Controlador de API com ações, usando o
Entity Framework:
Selecione TodoItem (TodoApi.Models) na classe Modelo.
Selecione TodoContext (TodoApi.Models) na classe de contexto Dados.
Selecione Adicionar.
Se a operação de scaffolding falhar, selecione Adicionar para tentar realizar
scaffolding uma segunda vez.
O código gerado:
Marca a classe com o [ApiController] atributo . Esse atributo indica se o
controlador responde às solicitações da API Web. Para obter informações sobre
comportamentos específicos habilitados pelo atributo, consulte Criar APIs Web
com ASP.NET Core.
Usa a DI para injetar o contexto de banco de dados ( TodoContext ) no controlador.
O contexto de banco de dados é usado em cada um dos métodos CRUD no
controlador.
Os modelos de ASP.NET Core para:
Controladores com exibições incluem [action] no modelo de rota.
Os controladores de API não incluem [action] no modelo de rota.
Quando o [action] token não está no modelo de rota, o nome da ação (nome do
método) não é incluído no ponto de extremidade. Ou seja, o nome do método
associado da ação não é usado na rota correspondente.
Atualizar o método de criação PostTodoItem
Atualize a instrução return no PostTodoItem para usar o operador nameof :
C#
[HttpPost]
public async Task<ActionResult<TodoItem>> PostTodoItem(TodoItem todoItem)
{
_context.TodoItems.Add(todoItem);
await _context.SaveChangesAsync();
// return CreatedAtAction("GetTodoItem", new { id = todoItem.Id },
todoItem);
return CreatedAtAction(nameof(GetTodoItem), new { id = todoItem.Id },
todoItem);
}
O código anterior é um HTTP POST método, conforme indicado pelo [HttpPost] atributo .
O método obtém o valor do TodoItem do corpo da solicitação HTTP.
Para obter mais informações, confira Roteamento de atributo com atributos Http[Verb].
O método CreatedAtAction:
Retornará um código de status HTTP 201 se tiver êxito. HTTP 201 é a resposta
padrão para um HTTP POST método que cria um novo recurso no servidor.
Adiciona um cabeçalho de Local à resposta. O cabeçalho Location especifica o
URI do item de tarefas pendentes recém-criado. Para obter mais informações,
confira 10.2.2 201 Criado .
Faz referência à ação GetTodoItem para criar o URI de Location do cabeçalho. A
palavra-chave nameof do C# é usada para evitar o hard-coding do nome da ação,
na chamada CreatedAtAction .
Testar PostTodoItem
Pressione CTRL+F5 para executar o aplicativo.
Na janela do navegador Swagger, selecione POST /api/TodoItems e, em seguida,
selecione Experimentar.
Na janela Entrada do corpo da solicitação, atualize o JSativado. Por exemplo,
JSON
{
"name": "walk dog",
"isComplete": true
}
Selecione Executar
Testar o URI do cabeçalho de local
No POST anterior, a interface do usuário do Swagger mostra o cabeçalho de
localização em Cabeçalhos de resposta. Por exemplo, location:
https://localhost:7260/api/TodoItems/1 . O cabeçalho de local mostra o URI para o
recurso criado.
Para testar o cabeçalho de local:
Na janela do navegador Swagger, selecione GET /api/TodoItems/{id}e selecione
Experimentar.
Insira 1 na id caixa de entrada e selecione Executar.
Examine os métodos GET
Dois pontos de extremidade GET são implementados:
GET /api/todoitems
GET /api/todoitems/{id}
A seção anterior mostrou um exemplo da /api/todoitems/{id} rota.
Siga as instruções POST para adicionar outro item de tarefas pendentes e, em seguida,
teste a /api/todoitems rota usando o Swagger.
Este aplicativo usa um banco de dados em memória. Se o aplicativo for interrompido e
iniciado, a solicitação GET anterior não retornará nenhum dado. Se nenhum dado for
retornado, execute POST de dados no aplicativo.
Roteamento e caminhos de URL
O [HttpGet] atributo indica um método que responde a uma solicitação HTTP GET . O
caminho da URL de cada método é construído da seguinte maneira:
Comece com a cadeia de caracteres de modelo no atributo Route do controlador:
C#
[Route("api/[controller]")]
[ApiController]
public class TodoItemsController : ControllerBase
Substitua [controller] pelo nome do controlador, que é o nome de classe do
controlador menos o sufixo "Controlador" por convenção. Para esta amostra, o
nome da classe do controlador é TodoItemsController. Portanto, o nome do
controlador é "TodoItems". O roteamento do ASP.NET Core não diferencia
maiúsculas de minúsculas.
Se o atributo [HttpGet] tiver um modelo de rota (por exemplo,
[HttpGet("products")] ), acrescente isso ao caminho. Esta amostra não usa um
modelo. Para obter mais informações, confira Roteamento de atributo com
atributos Http[Verb].
No método GetTodoItem a seguir, "{id}" é uma variável de espaço reservado para o
identificador exclusivo do item pendente. Quando GetTodoItem é invocado, o valor de "
{id}" na URL é fornecido ao método em seu id parâmetro .
C#
[HttpGet("{id}")]
public async Task<ActionResult<TodoItem>> GetTodoItem(long id)
{
var todoItem = await _context.TodoItems.FindAsync(id);
if (todoItem == null)
{
return NotFound();
}
return todoItem;
}
Valores retornados
O tipo de retorno dos GetTodoItems métodos e GetTodoItem é o tipo ActionResult<T>.
ASP.NET Core serializa automaticamente o objeto para JSON e grava o JSON no
corpo da mensagem de resposta. O código de resposta para esse tipo de retorno é 200
OK , supondo que não haja exceções sem tratamento. As exceções sem tratamento
são convertidas em erros 5xx.
Os tipos de retorno ActionResult podem representar uma ampla variedade de códigos
de status HTTP. Por exemplo, GetTodoItem pode retornar dois valores de status
diferentes:
Se nenhum item corresponder à ID solicitada, o método retornará um código de
erro de status NotFound404 .
Caso contrário, o método retornará 200 com um JScorpo de resposta ON. item
Retornar resulta em uma HTTP 200 resposta.
O método PutTodoItem
Examine o método PutTodoItem :
C#
[HttpPut("{id}")]
public async Task<IActionResult> PutTodoItem(long id, TodoItem todoItem)
{
if (id != todoItem.Id)
{
return BadRequest();
}
_context.Entry(todoItem).State = EntityState.Modified;
try
{
await _context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if (!TodoItemExists(id))
{
return NotFound();
}
else
{
throw;
}
}
return NoContent();
}
PutTodoItem é semelhante a PostTodoItem , exceto que usa HTTP PUT . A resposta é 204
(sem conteúdo) . De acordo com a especificação HTTP, uma PUT solicitação exige que
o cliente envie toda a entidade atualizada, não apenas as alterações. Para dar suporte a
atualizações parciais, use HTTP PATCH.
Testar o método PutTodoItem
Este exemplo usa um banco de dados na memória que deve ser inicializado sempre que
o aplicativo é iniciado. Deverá haver um item no banco de dados antes de você fazer
uma chamada PUT. Chame GET para garantir que haja um item no banco de dados
antes de fazer uma chamada PUT.
Usando a interface do usuário do Swagger, use o botão PUT para atualizar o que tem id
TodoItem = 1 e defina seu nome como "feed fish" . Observe que a resposta é HTTP 204
No Content .
O método DeleteTodoItem
Examine o método DeleteTodoItem :
C#
[HttpDelete("{id}")]
public async Task<IActionResult> DeleteTodoItem(long id)
{
var todoItem = await _context.TodoItems.FindAsync(id);
if (todoItem == null)
{
return NotFound();
}
_context.TodoItems.Remove(todoItem);
await _context.SaveChangesAsync();
return NoContent();
}
Testar o método DeleteTodoItem
Use a interface do usuário do Swagger para excluir o que tem id TodoItem = 1. Observe
que a resposta é HTTP 204 No Content .
Testar com http-repl, Postman ou curl
http-repl, Postman e curl geralmente são usados para testar as APIs. O Swagger usa
curl e mostra o curl comando enviado.
Para obter instruções sobre essas ferramentas, consulte os seguintes links:
Testar APIs com o Postman
Instalar e testar APIs com http-repl
Para obter mais informações sobre http-repl , consulte Testar APIs Web com o
HttpRepl.
Impedir o excesso de postagem
Atualmente, o aplicativo de exemplo expõe todo TodoItem o objeto. Os aplicativos de
produção normalmente limitam os dados que são inseridos e retornados usando um
subconjunto do modelo. Há várias razões por trás disso, e a segurança é uma das
principais. O subconjunto de um modelo geralmente é chamado de DTO (Objeto de
Transferência de Dados), modelo de entrada ou modelo de exibição. O DTO é usado
neste tutorial.
Um DTO pode ser usado para:
Impedir o excesso de postagem.
Oculte as propriedades que os clientes não devem exibir.
Omita algumas propriedades para reduzir o tamanho do conteúdo.
Nivele grafos de objeto que contêm objetos aninhados. Grafos de objeto
mesclados podem ser mais convenientes para clientes.
Para demonstrar a abordagem DTO, atualize a TodoItem classe para incluir um campo
secreto:
C#
namespace TodoApi.Models
{
public class TodoItem
{
public long Id { get; set; }
public string? Name { get; set; }
public bool IsComplete { get; set; }
public string? Secret { get; set; }
}
}
O campo secreto precisa estar oculto deste aplicativo, mas um aplicativo administrativo
pode optar por expô-lo.
Verifique se você pode postar e obter o campo de segredo.
Criar um modelo de DTO:
C#
namespace TodoApi.Models;
public class TodoItemDTO
{
public long Id { get; set; }
public string? Name { get; set; }
public bool IsComplete { get; set; }
}
Atualize o TodoItemsController para usar TodoItemDTO :
C#
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using TodoApi.Models;
namespace TodoApi.Controllers;
[Route("api/[controller]")]
[ApiController]
public class TodoItemsController : ControllerBase
{
private readonly TodoContext _context;
public TodoItemsController(TodoContext context)
{
_context = context;
}
// GET: api/TodoItems
[HttpGet]
public async Task<ActionResult<IEnumerable<TodoItemDTO>>> GetTodoItems()
{
return await _context.TodoItems
.Select(x => ItemToDTO(x))
.ToListAsync();
}
// GET: api/TodoItems/5
// <snippet_GetByID>
[HttpGet("{id}")]
public async Task<ActionResult<TodoItemDTO>> GetTodoItem(long id)
{
var todoItem = await _context.TodoItems.FindAsync(id);
if (todoItem == null)
{
return NotFound();
}
return ItemToDTO(todoItem);
}
// </snippet_GetByID>
// PUT: api/TodoItems/5
// To protect from overposting attacks, see
https://go.microsoft.com/fwlink/?linkid=2123754
// <snippet_Update>
[HttpPut("{id}")]
public async Task<IActionResult> PutTodoItem(long id, TodoItemDTO
todoDTO)
{
if (id != todoDTO.Id)
{
return BadRequest();
}
var todoItem = await _context.TodoItems.FindAsync(id);
if (todoItem == null)
{
return NotFound();
}
todoItem.Name = todoDTO.Name;
todoItem.IsComplete = todoDTO.IsComplete;
try
{
await _context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException) when (!TodoItemExists(id))
{
return NotFound();
}
return NoContent();
}
// </snippet_Update>
// POST: api/TodoItems
// To protect from overposting attacks, see
https://go.microsoft.com/fwlink/?linkid=2123754
// <snippet_Create>
[HttpPost]
public async Task<ActionResult<TodoItemDTO>> PostTodoItem(TodoItemDTO
todoDTO)
{
var todoItem = new TodoItem
{
IsComplete = todoDTO.IsComplete,
Name = todoDTO.Name
};
_context.TodoItems.Add(todoItem);
await _context.SaveChangesAsync();
return CreatedAtAction(
nameof(GetTodoItem),
new { id = todoItem.Id },
ItemToDTO(todoItem));
}
// </snippet_Create>
// DELETE: api/TodoItems/5
[HttpDelete("{id}")]
public async Task<IActionResult> DeleteTodoItem(long id)
{
var todoItem = await _context.TodoItems.FindAsync(id);
if (todoItem == null)
{
return NotFound();
}
_context.TodoItems.Remove(todoItem);
await _context.SaveChangesAsync();
return NoContent();
}
private bool TodoItemExists(long id)
{
return _context.TodoItems.Any(e => e.Id == id);
}
private static TodoItemDTO ItemToDTO(TodoItem todoItem) =>
new TodoItemDTO
{
Id = todoItem.Id,
Name = todoItem.Name,
IsComplete = todoItem.IsComplete
};
}
Verifique se você não pode postar ou obter o campo de segredo.
Chamar a API Web com o JavaScript
Consulte Tutorial: Chamar uma API Web ASP.NET Core com JavaScript.
Série de vídeos da API Web
Confira Vídeo: Série do Iniciante para: APIs Web.
Adicionar suporte de autenticação a uma API
Web
Identity ASP.NET Core adiciona a funcionalidade de logon da interface do usuário para
ASP.NET Core aplicativos Web. Para proteger APIs Web e SPAs, use um dos seguintes:
Azure Active Directory
Azure Active Directory B2C (Azure AD B2C)
Servidor Duende Identity
O Duende Identity Server é uma estrutura do OpenID Connect e do OAuth 2.0 para
ASP.NET Core. O Servidor Duende Identity habilita os seguintes recursos de segurança:
AaaS (autenticação como serviço)
SSO (logon único) em vários tipos de aplicativo
Controle de acesso para APIs
Gateway de Federação
) Importante
O Software Duende pode exigir que você pague uma taxa de licença pelo uso de
produção do Duende Identity Server. Para obter mais informações, consulte Migrar
do ASP.NET Core 5.0 para o 6.0.
Para obter mais informações, consulte a documentação do Servidor Duende Identity
(site do Duende Software) .
Publicar no Azure
Para obter informações sobre como implantar no Azure, consulte Início Rápido:
Implantar um aplicativo Web ASP.NET.
Recursos adicionais
Exibir ou baixar o código de exemplo para este tutorial . Consulte como baixar.
Para saber mais, consulte os recursos a seguir:
Criar APIs Web com o ASP.NET Core
Tutorial: Criar uma API Web mínima com ASP.NET Core
Documentação da API Web ASP.NET Core com o Swagger/OpenAPI
RazorPáginas com o Entity Framework Core em ASP.NET Core – Tutorial 1 de 8
Roteamento para ações do controlador no ASP.NET Core
Tipos de retorno de ação do controlador na API Web do ASP.NET Core
Implantar aplicativos ASP.NET Core no Serviço de Aplicativo do Azure
Hospedar e implantar o ASP.NET Core
Criar uma API Web com o ASP.NET Core
Tutorial: Criar uma API Web mínima
com ASP.NET Core
Artigo • 10/01/2023 • 33 minutos para o fim da leitura
Por Rick Anderson e Tom Dykstra
APIs mínimas são arquitetas para criar APIs HTTP com dependências mínimas. Eles são
ideais para microsserviços e aplicativos que desejam incluir apenas os arquivos mínimos,
recursos e dependências em ASP.NET Core.
Este tutorial ensina os conceitos básicos da criação de uma API Web mínima com
ASP.NET Core. Para obter um tutorial sobre como criar um projeto de API Web com
base em controladores que contêm mais recursos, consulte Criar uma API Web. Para
obter uma comparação, consulte Diferenças entre APIs mínimas e APIs com
controladores mais adiante neste tutorial.
Visão geral
Este tutorial cria a seguinte API:
API Descrição Corpo da Corpo da resposta
solicitação
GET /todoitems Obter todos os itens de Nenhum Matriz de itens de
tarefas pendentes tarefas pendentes
GET Obter itens pendentes Nenhum Matriz de itens de
/todoitems/complete concluídos tarefas pendentes
GET Obter um item por ID Nenhum Item de tarefas
/todoitems/{id} pendentes
POST /todoitems Adicionar um novo item Item de tarefas Item de tarefas
pendentes pendentes
PUT Atualizar um item existente Item de tarefas Nenhum
/todoitems/{id} pendentes
DELETE Excluir um item Nenhum Nenhum
/todoitems/{id}
Pré-requisitos
Visual Studio
Visual Studio 2022 com a carga de trabalho de desenvolvimento Web e do
ASP.NET.
Criar um projeto de API Web
Visual Studio
Inicie o Visual Studio 2022 e selecione Criar um novo projeto.
Na caixa de diálogo Criar um novo projeto :
Insira Empty na caixa de pesquisa Pesquisar modelos .
Selecione o modelo ASP.NET Core Vazio e selecione Avançar.
Nomeie o projeto ComoApi e selecione Avançar.
Na caixa de diálogo Informações adicionais:
Selecione .NET 7.0
Desmarcar Não usar instruções de nível superior
Escolha Criar
Examinar o código
O Program.cs arquivo contém o seguinte código:
C#
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.MapGet("/", () => "Hello World!");
app.Run();
O código anterior:
Cria um WebApplicationBuilder e um WebApplication com padrões pré-
configurados.
Cria um ponto de extremidade / HTTP GET que retorna Hello World! :
Executar o aplicativo
Visual Studio
Pressione Ctrl + F5 para execução sem o depurador.
O Visual Studio exibe a caixa de diálogo a seguir:
Selecione Sim se você confia no certificado SSL do IIS Express.
A seguinte caixa de diálogo é exibida:
Selecione Sim se você concordar com confiar no certificado de desenvolvimento.
Para obter informações sobre como confiar no navegador Firefox, consulte Firefox
SEC_ERROR_INADEQUATE_KEY_USAGE erro de certificado.
O Visual Studio inicia o Kestrel servidor Web e abre uma janela do navegador.
Hello World! é exibido no navegador. O Program.cs arquivo contém um aplicativo
mínimo, mas completo.
Adicionar pacotes NuGet
Os pacotes NuGet devem ser adicionados para dar suporte ao banco de dados e ao
diagnóstico usados neste tutorial.
Visual Studio
No menu Ferramentas , selecione Gerenciador de Pacotes > NuGet Gerenciar
Pacotes NuGet para solução.
Selecione a guia Procurar.
Insira Microsoft.EntityFrameworkCore.InMemory na caixa de pesquisa e
selecione Microsoft.EntityFrameworkCore.InMemory .
Marque a caixa de seleção Projeto no painel direito e selecione Instalar.
Siga as instruções anteriores para adicionar o
Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore pacote.
As classes de contexto de modelo e banco de
dados
Na pasta do projeto, crie um arquivo chamado Todo.cs com o seguinte código:
C#
class Todo
{
public int Id { get; set; }
public string? Name { get; set; }
public bool IsComplete { get; set; }
}
O código anterior cria o modelo para este aplicativo. Um modelo é uma classe que
representa os dados que o aplicativo gerencia.
Crie um arquivo chamado TodoDb.cs com o seguinte código:
C#
using Microsoft.EntityFrameworkCore;
class TodoDb : DbContext
{
public TodoDb(DbContextOptions<TodoDb> options)
: base(options) { }
public DbSet<Todo> Todos => Set<Todo>();
}
O código anterior define o contexto do banco de dados, que é a classe principal que
coordena a funcionalidade do Entity Framework para um modelo de dados. Essa classe
deriva da Microsoft.EntityFrameworkCore.DbContext classe .
Adicionar o código de API
Substitua o conteúdo do arquivo Program.cs pelo seguinte código:
C#
using Microsoft.EntityFrameworkCore;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddDbContext<TodoDb>(opt =>
opt.UseInMemoryDatabase("TodoList"));
builder.Services.AddDatabaseDeveloperPageExceptionFilter();
var app = builder.Build();
app.MapGet("/todoitems", async (TodoDb db) =>
await db.Todos.ToListAsync());
app.MapGet("/todoitems/complete", async (TodoDb db) =>
await db.Todos.Where(t => t.IsComplete).ToListAsync());
app.MapGet("/todoitems/{id}", async (int id, TodoDb db) =>
await db.Todos.FindAsync(id)
is Todo todo
? Results.Ok(todo)
: Results.NotFound());
app.MapPost("/todoitems", async (Todo todo, TodoDb db) =>
{
db.Todos.Add(todo);
await db.SaveChangesAsync();
return Results.Created($"/todoitems/{todo.Id}", todo);
});
app.MapPut("/todoitems/{id}", async (int id, Todo inputTodo, TodoDb db) =>
{
var todo = await db.Todos.FindAsync(id);
if (todo is null) return Results.NotFound();
todo.Name = inputTodo.Name;
todo.IsComplete = inputTodo.IsComplete;
await db.SaveChangesAsync();
return Results.NoContent();
});
app.MapDelete("/todoitems/{id}", async (int id, TodoDb db) =>
{
if (await db.Todos.FindAsync(id) is Todo todo)
{
db.Todos.Remove(todo);
await db.SaveChangesAsync();
return Results.Ok(todo);
}
return Results.NotFound();
});
app.Run();
O código realçado a seguir adiciona o contexto do banco de dados ao contêiner de DI
(injeção de dependência) e permite exibir exceções relacionadas ao banco de dados:
C#
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddDbContext<TodoDb>(opt =>
opt.UseInMemoryDatabase("TodoList"));
builder.Services.AddDatabaseDeveloperPageExceptionFilter();
var app = builder.Build();
O contêiner de DI fornece acesso ao contexto do banco de dados e a outros serviços.
Instalar o Postman para testar o aplicativo
Este tutorial usa o Postman para testar a API.
Instalar o Postman
Inicie o aplicativo Web.
Inicie o Postman.
Desabilite a Verificação do certificado SSL
Para o Postman para Windows, selecioneConfigurações de Arquivo> (guia
Geral), desabilite a verificação do certificado SSL.
Para o Postman para macOS, selecionePreferências do Postman> (guia Geral),
desabilite a verificação do certificado SSL.
2 Aviso
Habilite novamente a verificação de certificado SSL depois de testar o
aplicativo de exemplo.
Dados de postagem de teste
O código a seguir em Program.cs cria um ponto /todoitems de extremidade HTTP POST
que adiciona dados ao banco de dados na memória:
C#
app.MapPost("/todoitems", async (Todo todo, TodoDb db) =>
{
db.Todos.Add(todo);
await db.SaveChangesAsync();
return Results.Created($"/todoitems/{todo.Id}", todo);
});
Execute o aplicativo. O navegador exibe um erro 404 porque não há mais um / ponto
de extremidade.
Use o ponto de extremidade POST para adicionar dados ao aplicativo:
Crie uma nova solicitação HTTP.
Defina o método HTTP como POST .
Defina o URI como https://localhost:<port>/todoitems . Por exemplo:
https://localhost:5001/todoitems
Selecione a guia Corpo.
Selecione bruto.
Defina o tipo como JSON.
No corpo da solicitação, insira JSON para um item pendente:
JSON
{
"name":"walk dog",
"isComplete":true
}
Selecione Enviar.
Examinar os pontos de extremidade GET
O aplicativo de exemplo implementa vários pontos de extremidade GET chamando
MapGet :
API Descrição Corpo da Corpo da resposta
solicitação
GET /todoitems Obter todos os itens de Nenhum Matriz de itens de tarefas
tarefas pendentes pendentes
GET Obter todos os itens Nenhum Matriz de itens de tarefas
/todoitems/complete pendentes concluídos pendentes
GET Obter um item por ID Nenhum Item de tarefas
/todoitems/{id} pendentes
C#
app.MapGet("/todoitems", async (TodoDb db) =>
await db.Todos.ToListAsync());
app.MapGet("/todoitems/complete", async (TodoDb db) =>
await db.Todos.Where(t => t.IsComplete).ToListAsync());
app.MapGet("/todoitems/{id}", async (int id, TodoDb db) =>
await db.Todos.FindAsync(id)
is Todo todo
? Results.Ok(todo)
: Results.NotFound());
Testar os pontos de extremidade GET
Teste o aplicativo chamando os pontos de extremidade de um navegador ou postman.
As etapas a seguir são para o Postman.
Crie uma nova solicitação HTTP.
Defina o método HTTP como GET.
Defina o URI de solicitação como https://localhost:<port>/todoitems . Por
exemplo, https://localhost:5001/todoitems .
Selecione Enviar.
A chamada para GET /todoitems produz uma resposta semelhante à seguinte:
JSON
[
{
"id": 1,
"name": "walk dog",
"isComplete": false
}
]
Defina o URI de solicitação como https://localhost:<port>/todoitems/1 . Por
exemplo, https://localhost:5001/todoitems/1 .
Selecione Enviar.
A resposta é semelhante ao seguinte:
JSON
{
"id": 1,
"name": "walk dog",
"isComplete": false
}
Este aplicativo usa um banco de dados em memória. Se o aplicativo for reiniciado, a
solicitação GET não retornará nenhum dado. Se nenhum dado for retornado, os dados
POST serão retornados para o aplicativo e tentem a solicitação GET novamente.
Valores retornados
ASP.NET Core serializa automaticamente o objeto para JSON e grava o JSON no
corpo da mensagem de resposta. O código de resposta para esse tipo de retorno é 200
OK , supondo que não haja exceções sem tratamento. As exceções sem tratamento
são convertidas em erros 5xx.
Os tipos de retorno podem representar uma ampla gama de códigos de status HTTP.
Por exemplo, GET /todoitems/{id} pode retornar dois valores de status diferentes:
Se nenhum item corresponder à ID solicitada, o método retornará um código de
erro de status NotFound404 .
Caso contrário, o método retorna 200 com um JScorpo de resposta ON. Retornar
item resulta em uma resposta HTTP 200.
Examinar o ponto de extremidade PUT
O aplicativo de exemplo implementa um único ponto de extremidade PUT usando
MapPut :
C#
app.MapPut("/todoitems/{id}", async (int id, Todo inputTodo, TodoDb db) =>
{
var todo = await db.Todos.FindAsync(id);
if (todo is null) return Results.NotFound();
todo.Name = inputTodo.Name;
todo.IsComplete = inputTodo.IsComplete;
await db.SaveChangesAsync();
return Results.NoContent();
});
Esse método é semelhante ao MapPost método , exceto que ele usa HTTP PUT. Uma
resposta bem-sucedida retorna 204 (sem conteúdo) . De acordo com a especificação
de HTTP, uma solicitação PUT exige que o cliente envie a entidade inteira atualizada,
não apenas as alterações. Para dar suporte a atualizações parciais, use HTTP PATCH.
Testar o ponto de extremidade PUT
Este exemplo usa um banco de dados na memória que deve ser inicializado sempre que
o aplicativo é iniciado. Deverá haver um item no banco de dados antes de você fazer
uma chamada PUT. Chame GET para garantir que haja um item no banco de dados
antes de fazer uma chamada PUT.
Atualize o item de tarefas pendentes que tem ID = 1 e defina seu nome como "feed
fish" :
JSON
{
"id": 1,
"name": "feed fish",
"isComplete": false
}
Examinar e testar o ponto de extremidade
DELETE
O aplicativo de exemplo implementa um único ponto de extremidade DELETE usando
MapDelete :
C#
app.MapDelete("/todoitems/{id}", async (int id, TodoDb db) =>
{
if (await db.Todos.FindAsync(id) is Todo todo)
{
db.Todos.Remove(todo);
await db.SaveChangesAsync();
return Results.Ok(todo);
}
return Results.NotFound();
});
Use o Postman para excluir um item pendente:
Defina o método como DELETE .
Defina o URI do objeto para excluir (por exemplo
https://localhost:5001/todoitems/1 , ).
Selecione Enviar.
Usar a API do MapGroup
O código do aplicativo de exemplo repete o prefixo de todoitems URL sempre que
configura um ponto de extremidade. As APIs Web geralmente têm grupos de pontos de
extremidade com um prefixo de URL comum e o MapGroup método está disponível
para ajudar a organizar esses grupos. Ele reduz o código repetitivo e permite
personalizar grupos inteiros de pontos de extremidade com uma única chamada para
métodos como RequireAuthorization e WithMetadata.
Substitua o conteúdo de Program.cs pelo seguinte código:
C#
using Microsoft.EntityFrameworkCore;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddDbContext<TodoDb>(opt =>
opt.UseInMemoryDatabase("TodoList"));
builder.Services.AddDatabaseDeveloperPageExceptionFilter();
var app = builder.Build();
var todoItems = app.MapGroup("/todoitems");
todoItems.MapGet("/", async (TodoDb db) =>
await db.Todos.ToListAsync());
todoItems.MapGet("/complete", async (TodoDb db) =>
await db.Todos.Where(t => t.IsComplete).ToListAsync());
todoItems.MapGet("/{id}", async (int id, TodoDb db) =>
await db.Todos.FindAsync(id)
is Todo todo
? Results.Ok(todo)
: Results.NotFound());
todoItems.MapPost("/", async (Todo todo, TodoDb db) =>
{
db.Todos.Add(todo);
await db.SaveChangesAsync();
return Results.Created($"/todoitems/{todo.Id}", todo);
});
todoItems.MapPut("/{id}", async (int id, Todo inputTodo, TodoDb db) =>
{
var todo = await db.Todos.FindAsync(id);
if (todo is null) return Results.NotFound();
todo.Name = inputTodo.Name;
todo.IsComplete = inputTodo.IsComplete;
await db.SaveChangesAsync();
return Results.NoContent();
});
todoItems.MapDelete("/{id}", async (int id, TodoDb db) =>
{
if (await db.Todos.FindAsync(id) is Todo todo)
{
db.Todos.Remove(todo);
await db.SaveChangesAsync();
return Results.Ok(todo);
}
return Results.NotFound();
});
app.Run();
O código anterior tem as seguintes alterações:
Adiciona var todoItems = app.MapGroup("/todoitems"); para configurar o grupo
usando o prefixo /todoitems de URL .
Altera todos os app.Map<HttpVerb> métodos para todoItems.Map<HttpVerb> .
Remove o prefixo /todoitems de URL das chamadas de Map<HttpVerb> método.
Teste os pontos de extremidade para verificar se eles funcionam da mesma forma.
Usar a API TypedResults
Os Map<HttpVerb> métodos podem chamar métodos de manipulador de rotas em vez
de usar lambdas. Para ver um exemplo, atualize Program.cs com o seguinte código:
C#
using Microsoft.EntityFrameworkCore;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddDbContext<TodoDb>(opt =>
opt.UseInMemoryDatabase("TodoList"));
builder.Services.AddDatabaseDeveloperPageExceptionFilter();
var app = builder.Build();
var todoItems = app.MapGroup("/todoitems");
todoItems.MapGet("/", GetAllTodos);
todoItems.MapGet("/complete", GetCompleteTodos);
todoItems.MapGet("/{id}", GetTodo);
todoItems.MapPost("/", CreateTodo);
todoItems.MapPut("/{id}", UpdateTodo);
todoItems.MapDelete("/{id}", DeleteTodo);
app.Run();
static async Task<IResult> GetAllTodos(TodoDb db)
{
return TypedResults.Ok(await db.Todos.ToArrayAsync());
}
static async Task<IResult> GetCompleteTodos(TodoDb db)
{
return TypedResults.Ok(await db.Todos.Where(t =>
t.IsComplete).ToListAsync());
}
static async Task<IResult> GetTodo(int id, TodoDb db)
{
return await db.Todos.FindAsync(id)
is Todo todo
? TypedResults.Ok(todo)
: TypedResults.NotFound();
}
static async Task<IResult> CreateTodo(Todo todo, TodoDb db)
{
db.Todos.Add(todo);
await db.SaveChangesAsync();
return TypedResults.Created($"/todoitems/{todo.Id}", todo);
}
static async Task<IResult> UpdateTodo(int id, Todo inputTodo, TodoDb db)
{
var todo = await db.Todos.FindAsync(id);
if (todo is null) return TypedResults.NotFound();
todo.Name = inputTodo.Name;
todo.IsComplete = inputTodo.IsComplete;
await db.SaveChangesAsync();
return TypedResults.NoContent();
}
static async Task<IResult> DeleteTodo(int id, TodoDb db)
{
if (await db.Todos.FindAsync(id) is Todo todo)
{
db.Todos.Remove(todo);
await db.SaveChangesAsync();
return TypedResults.Ok(todo);
}
return TypedResults.NotFound();
}
O Map<HttpVerb> código agora chama métodos em vez de lambdas:
C#
var todoItems = app.MapGroup("/todoitems");
todoItems.MapGet("/", GetAllTodos);
todoItems.MapGet("/complete", GetCompleteTodos);
todoItems.MapGet("/{id}", GetTodo);
todoItems.MapPost("/", CreateTodo);
todoItems.MapPut("/{id}", UpdateTodo);
todoItems.MapDelete("/{id}", DeleteTodo);
Esses métodos retornam objetos que implementam IResult e são definidos por
TypedResults:
C#
static async Task<IResult> GetAllTodos(TodoDb db)
{
return TypedResults.Ok(await db.Todos.ToArrayAsync());
}
static async Task<IResult> GetCompleteTodos(TodoDb db)
{
return TypedResults.Ok(await db.Todos.Where(t =>
t.IsComplete).ToListAsync());
}
static async Task<IResult> GetTodo(int id, TodoDb db)
{
return await db.Todos.FindAsync(id)
is Todo todo
? TypedResults.Ok(todo)
: TypedResults.NotFound();
}
static async Task<IResult> CreateTodo(Todo todo, TodoDb db)
{
db.Todos.Add(todo);
await db.SaveChangesAsync();
return TypedResults.Created($"/todoitems/{todo.Id}", todo);
}
static async Task<IResult> UpdateTodo(int id, Todo inputTodo, TodoDb db)
{
var todo = await db.Todos.FindAsync(id);
if (todo is null) return TypedResults.NotFound();
todo.Name = inputTodo.Name;
todo.IsComplete = inputTodo.IsComplete;
await db.SaveChangesAsync();
return TypedResults.NoContent();
}
static async Task<IResult> DeleteTodo(int id, TodoDb db)
{
if (await db.Todos.FindAsync(id) is Todo todo)
{
db.Todos.Remove(todo);
await db.SaveChangesAsync();
return TypedResults.Ok(todo);
}
return TypedResults.NotFound();
}
Os testes de unidade podem chamar esses métodos e testar se eles retornam o tipo
correto. Por exemplo, se o método for GetAllTodos :
C#
static async Task<IResult> GetAllTodos(TodoDb db)
{
return TypedResults.Ok(await db.Todos.ToArrayAsync());
}
O código de teste de unidade pode verificar se um objeto do tipo Ok<Todo[]> é
retornado do método de manipulador. Por exemplo:
C#
public async Task GetAllTodos_ReturnsOkOfTodosResult()
{
// Arrange
var db = CreateDbContext();
// Act
var result = await TodosApi.GetAllTodos(db);
// Assert: Check for the correct returned type
Assert.IsType<Ok<Todo[]>>(result);
}
Impedir o excesso de postagem
Atualmente, o aplicativo de exemplo expõe todo Todo o objeto. Normalmente, os
aplicativos de produção limitam os dados que são de entrada e retornados usando um
subconjunto do modelo. Há várias razões por trás disso e a segurança é uma das
principais. O subconjunto de um modelo geralmente é chamado de DTO (Objeto de
Transferência de Dados), modelo de entrada ou modelo de exibição. O DTO é usado
neste artigo.
Um DTO pode ser usado para:
Impedir o excesso de postagem.
Ocultar propriedades que os clientes não devem exibir.
Omita algumas propriedades para reduzir o tamanho da carga.
Nivelar grafos de objeto que contêm objetos aninhados. Grafos de objeto
mesclados podem ser mais convenientes para os clientes.
Para demonstrar a abordagem de DTO, atualize a Todo classe para incluir um campo
secreto:
C#
public class Todo
{
public int Id { get; set; }
public string? Name { get; set; }
public bool IsComplete { get; set; }
public string? Secret { get; set; }
}
O campo de segredo precisa estar oculto deste aplicativo, mas um aplicativo
administrativo pode optar por expô-lo.
Verifique se você pode postar e obter o campo de segredo.
Crie um arquivo chamado TodoItemDTO.cs com o seguinte código:
C#
public class TodoItemDTO
{
public int Id { get; set; }
public string? Name { get; set; }
public bool IsComplete { get; set; }
public TodoItemDTO() { }
public TodoItemDTO(Todo todoItem) =>
(Id, Name, IsComplete) = (todoItem.Id, todoItem.Name,
todoItem.IsComplete);
}
Atualize o código em Program.cs para usar este modelo de DTO:
C#
using Microsoft.EntityFrameworkCore;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddDbContext<TodoDb>(opt =>
opt.UseInMemoryDatabase("TodoList"));
builder.Services.AddDatabaseDeveloperPageExceptionFilter();
var app = builder.Build();
RouteGroupBuilder todoItems = app.MapGroup("/todoitems");
todoItems.MapGet("/", GetAllTodos);
todoItems.MapGet("/{id}", GetTodo);
todoItems.MapPost("/", CreateTodo);
todoItems.MapPut("/{id}", UpdateTodo);
todoItems.MapDelete("/{id}", DeleteTodo);
app.Run();
static async Task<IResult> GetAllTodos(TodoDb db)
{
return TypedResults.Ok(await db.Todos.Select(x => new
TodoItemDTO(x)).ToArrayAsync());
}
static async Task<IResult> GetTodo(int id, TodoDb db)
{
return await db.Todos.FindAsync(id)
is Todo todo
? TypedResults.Ok(new TodoItemDTO(todo))
: TypedResults.NotFound();
}
static async Task<IResult> CreateTodo(TodoItemDTO todoItemDTO, TodoDb db)
{
var todoItem = new Todo
{
IsComplete = todoItemDTO.IsComplete,
Name = todoItemDTO.Name
};
db.Todos.Add(todoItem);
await db.SaveChangesAsync();
return TypedResults.Created($"/todoitems/{todoItem.Id}", todoItemDTO);
}
static async Task<IResult> UpdateTodo(int id, TodoItemDTO todoItemDTO,
TodoDb db)
{
var todo = await db.Todos.FindAsync(id);
if (todo is null) return TypedResults.NotFound();
todo.Name = todoItemDTO.Name;
todo.IsComplete = todoItemDTO.IsComplete;
await db.SaveChangesAsync();
return TypedResults.NoContent();
}
static async Task<IResult> DeleteTodo(int id, TodoDb db)
{
if (await db.Todos.FindAsync(id) is Todo todo)
{
db.Todos.Remove(todo);
await db.SaveChangesAsync();
return TypedResults.Ok(todo);
}
return TypedResults.NotFound();
}
Verifique se você pode postar e obter todos os campos, exceto o campo de segredo.
Diferenças entre APIs mínimas e APIs com
controladores
APIs mínimas têm:
Suporte diferente para filtros. Para obter mais informações, consulte Filtros em
aplicativos de API mínimos
Não há suporte para associação de modelo, por exemplo: IModelBinderProvider,
IModelBinder. O suporte pode ser adicionado com um shim de associação
personalizado.
Não há suporte para associação de formulários, exceto para IFormFile. Para
obter mais informações, consulte Uploads de arquivo usando IFormFile e
IFormFileCollection.
Não há suporte interno para validação, ou seja, IModelValidator
Não há suporte para partes de aplicativo ou o modelo de aplicativo. Não há como
aplicar ou criar suas próprias convenções.
Sem suporte interno de renderização de exibição. É recomendável usar Razor o
Pages para renderizar exibições.
Sem suporte para JsonPatch
Sem suporte para OData
Próximas etapas
Configurar JSopções de serialização ON
Para obter informações sobre como configurar JSa serialização ON em seus aplicativos
de API Mínima, consulte Configurar JSopções de serialização ON.
Lidar com erros e exceções
A página de exceção do desenvolvedor é habilitada por padrão no ambiente de
desenvolvimento para aplicativos mínimos de API. Para obter informações sobre como
lidar com erros e exceções, consulte Manipular erros em ASP.NET Core APIs Web.
Testar aplicativos mínimos de API
Para obter um exemplo de teste de um aplicativo de API mínimo, consulte este exemplo
do GitHub .
Usar OpenAPI (Swagger)
Para obter informações sobre como usar o OpenAPI com aplicativos de API mínimos,
consulte Suporte a OpenAPI em APIs mínimas.
Publicar no Azure
Para obter informações sobre como implantar no Azure, consulte Início Rápido:
Implantar um aplicativo Web ASP.NET.
Saiba mais
Para obter mais informações sobre aplicativos mínimos de API, consulte Referência
rápida de APIs mínimas.
Criar uma API Web com o ASP.NET Core
e o MongoDB
Artigo • 10/01/2023 • 23 minutos para o fim da leitura
Por Pratik Khandelwal e Scott Addie
Este tutorial cria uma API Web que executa operações CRUD (Criar, Ler, Atualizar e
Excluir) em um banco de dados NoSQL do MongoDB .
Neste tutorial, você aprenderá como:
" Configurar o MongoDB
" Criar um banco de dados do MongoDB
" Definir uma coleção e um esquema do MongoDB
" Executar operações CRUD do MongoDB a partir de uma API Web
" Personalizar JSa serialização ON
Pré-requisitos
MongoDB
MongoDB Shell
Visual Studio
Visual Studio 2022 com a carga de trabalho de desenvolvimento Web e do
ASP.NET.
Configurar o MongoDB
No Windows, o MongoDB é instalado em C:\Arquivos de Programas\MongoDB por
padrão. Adicione C:\Program Files\MongoDB\Server\<version_number>\bin à variável de
Path ambiente. Essa alteração possibilita o acesso ao MongoDB a partir de qualquer
lugar em seu computador de desenvolvimento.
Use o Shell do MongoDB instalado anteriormente nas etapas a seguir para criar um
banco de dados, criar coleções e armazenar documentos. Para obter mais informações
sobre comandos do Shell do MongoDB, consulte mongosh .
1. Escolha um diretório no seu computador de desenvolvimento para armazenar os
dados. Por exemplo, C:\BooksData no Windows. Crie o diretório se não houver um.
O Shell do mongo não cria novos diretórios.
2. Abra um shell de comando. Execute o comando a seguir para se conectar ao
MongoDB na porta padrão 27017. Lembre-se de substituir <data_directory_path>
pelo diretório escolhido na etapa anterior.
Console
mongod --dbpath <data_directory_path>
3. Abra outra instância do shell de comando. Conecte-se ao banco de dados de
testes padrão executando o seguinte comando:
Console
mongosh
4. Execute o seguinte comando em um shell de comando:
Console
use BookStore
Um banco de dados chamado BookStore será criado se ele ainda não existir. Se o
banco de dados existir, a conexão dele será aberta para transações.
5. Crie uma coleção Books usando o seguinte comando:
Console
db.createCollection('Books')
O seguinte resultado é exibido:
Console
{ "ok" : 1 }
6. Defina um esquema para a coleção Books e insira dois documentos usando o
seguinte comando:
Console
db.Books.insertMany([{ "Name": "Design Patterns", "Price": 54.93,
"Category": "Computers", "Author": "Ralph Johnson" }, { "Name": "Clean
Code", "Price": 43.15, "Category": "Computers","Author": "Robert C.
Martin" }])
Um resultado semelhante ao seguinte é exibido:
Console
{
"acknowledged" : true,
"insertedIds" : [
ObjectId("61a6058e6c43f32854e51f51"),
ObjectId("61a6058e6c43f32854e51f52")
]
}
7 Observação
Os ObjectId s mostrados no resultado anterior não corresponderão aos
mostrados no shell de comando.
7. Visualize os documentos no banco de dados usando o seguinte comando:
Console
db.Books.find().pretty()
Um resultado semelhante ao seguinte é exibido:
Console
{
"_id" : ObjectId("61a6058e6c43f32854e51f51"),
"Name" : "Design Patterns",
"Price" : 54.93,
"Category" : "Computers",
"Author" : "Ralph Johnson"
}
{
"_id" : ObjectId("61a6058e6c43f32854e51f52"),
"Name" : "Clean Code",
"Price" : 43.15,
"Category" : "Computers",
"Author" : "Robert C. Martin"
}
O esquema adiciona uma propriedade _id gerada automaticamente do tipo
ObjectId para cada documento.
Criar o projeto da API Web do ASP.NET Core
Visual Studio
1. Vá para Arquivo>Novo>Projeto.
2. Selecione o tipo de projeto ASP.NET Core API Web e selecione Avançar.
3. Nomeie o projeto BookStoreApi e selecione Avançar.
4. Selecione a estrutura .NET 6.0 (suporte a longo prazo) e selecione Criar.
5. Na janela Console do Gerenciador de Pacotes, navegue até a raiz do projeto.
Execute o seguinte comando para instalar o driver .NET para MongoDB:
PowerShell
Install-Package MongoDB.Driver
Adicionar um modelo de entidade
1. Adicione um diretório Modelos à raiz do projeto.
2. Adicione uma classe Book ao diretório Modelos com o seguinte código:
C#
using MongoDB.Bson;
using MongoDB.Bson.Serialization.Attributes;
namespace BookStoreApi.Models;
public class Book
{
[BsonId]
[BsonRepresentation(BsonType.ObjectId)]
public string? Id { get; set; }
[BsonElement("Name")]
public string BookName { get; set; } = null!;
public decimal Price { get; set; }
public string Category { get; set; } = null!;
public string Author { get; set; } = null!;
}
Na classe anterior, a Id propriedade é:
Necessário para mapear o objeto CLR (Common Language Runtime) para a
coleção MongoDB.
Anotado com [BsonId] para tornar essa propriedade a chave primária do
documento.
Anotado com [BsonRepresentation(BsonType.ObjectId)] para permitir a
passagem do parâmetro como tipo string em vez de uma estrutura
ObjectId . O Mongo processa a conversão de string para ObjectId .
A BookName propriedade é anotada com o [BsonElement] atributo . O valor do
atributo de Name representa o nome da propriedade da coleção do MongoDB.
Adicionar um modelo de configuração
1. Adicione os seguintes valores de configuração de banco de dados a
appsettings.json :
JSON
{
"BookStoreDatabase": {
"ConnectionString": "mongodb://localhost:27017",
"DatabaseName": "BookStore",
"BooksCollectionName": "Books"
},
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*"
}
2. Adicione uma classe BookStoreDatabaseSettings ao diretório Modelos com o
seguinte código:
C#
namespace BookStoreApi.Models;
public class BookStoreDatabaseSettings
{
public string ConnectionString { get; set; } = null!;
public string DatabaseName { get; set; } = null!;
public string BooksCollectionName { get; set; } = null!;
}
A classe anterior BookStoreDatabaseSettings é usada para armazenar os
appsettings.json valores de propriedade do BookStoreDatabase arquivo. Os
JSnomes das propriedades ON e C# são nomeados de forma idêntica para facilitar
o processo de mapeamento.
3. Adicione o código realçado a seguir a Program.cs :
C#
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
builder.Services.Configure<BookStoreDatabaseSettings>(
builder.Configuration.GetSection("BookStoreDatabase"));
No código anterior, a instância de configuração à qual a appsettings.json seção
do BookStoreDatabase arquivo é associada é registrada no contêiner DI (Injeção de
Dependência). Por exemplo, a BookStoreDatabaseSettings propriedade do
ConnectionString objeto é preenchida com a BookStoreDatabase:ConnectionString
propriedade em appsettings.json .
4. Adicione o seguinte código à parte superior de Program.cs para resolver a
BookStoreDatabaseSettings referência:
C#
using BookStoreApi.Models;
Adicionar um serviço de operações CRUD
1. Adicione um diretório Serviços à raiz do projeto.
2. Adicione uma classe BooksService ao diretório Serviços com o seguinte código:
C#
using BookStoreApi.Models;
using Microsoft.Extensions.Options;
using MongoDB.Driver;
namespace BookStoreApi.Services;
public class BooksService
{
private readonly IMongoCollection<Book> _booksCollection;
public BooksService(
IOptions<BookStoreDatabaseSettings> bookStoreDatabaseSettings)
{
var mongoClient = new MongoClient(
bookStoreDatabaseSettings.Value.ConnectionString);
var mongoDatabase = mongoClient.GetDatabase(
bookStoreDatabaseSettings.Value.DatabaseName);
_booksCollection = mongoDatabase.GetCollection<Book>(
bookStoreDatabaseSettings.Value.BooksCollectionName);
}
public async Task<List<Book>> GetAsync() =>
await _booksCollection.Find(_ => true).ToListAsync();
public async Task<Book?> GetAsync(string id) =>
await _booksCollection.Find(x => x.Id ==
id).FirstOrDefaultAsync();
public async Task CreateAsync(Book newBook) =>
await _booksCollection.InsertOneAsync(newBook);
public async Task UpdateAsync(string id, Book updatedBook) =>
await _booksCollection.ReplaceOneAsync(x => x.Id == id,
updatedBook);
public async Task RemoveAsync(string id) =>
await _booksCollection.DeleteOneAsync(x => x.Id == id);
}
No código anterior, uma BookStoreDatabaseSettings instância é recuperada do DI
por meio de injeção de construtor. Essa técnica fornece acesso aos
appsettings.json valores de configuração que foram adicionados na seção
Adicionar um modelo de configuração .
3. Adicione o código realçado a seguir a Program.cs :
C#
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
builder.Services.Configure<BookStoreDatabaseSettings>(
builder.Configuration.GetSection("BookStoreDatabase"));
builder.Services.AddSingleton<BooksService>();
No código anterior, a classe BooksService é registrada com a DI para dar suporte à
injeção de construtor nas classes consumidoras. O tempo de vida do serviço
singleton é mais apropriado porque BooksService usa uma dependência direta de
MongoClient . De acordo com as diretrizes oficiais de reutilização do Cliente
Mongo , MongoClient deve ser registrado na DI com um tempo de vida de
serviço singleton.
4. Adicione o seguinte código à parte superior de Program.cs para resolver a
BooksService referência:
C#
using BookStoreApi.Services;
A BooksService classe usa os seguintes MongoDB.Driver membros para executar
operações CRUD no banco de dados:
MongoClient : lê a instância do servidor para executar operações de banco de
dados. O construtor dessa classe é fornecido na cadeia de conexão do MongoDB:
C#
public BooksService(
IOptions<BookStoreDatabaseSettings> bookStoreDatabaseSettings)
{
var mongoClient = new MongoClient(
bookStoreDatabaseSettings.Value.ConnectionString);
var mongoDatabase = mongoClient.GetDatabase(
bookStoreDatabaseSettings.Value.DatabaseName);
_booksCollection = mongoDatabase.GetCollection<Book>(
bookStoreDatabaseSettings.Value.BooksCollectionName);
}
IMongoDatabase : representa o banco de dados Mongo para executar
operações. Este tutorial usa o método genérico GetCollection<TDocument>
(collection) na interface para obter acesso aos dados em uma coleção específica.
Execute operações CRUD na coleção depois que esse método for chamado. Na
chamada de método GetCollection<TDocument>(collection) :
collection representa o nome da coleção.
TDocument representa o tipo de objeto CLR armazenado na coleção.
GetCollection<TDocument>(collection) retorna um objeto MongoCollection que
representa a coleção. Neste tutorial, os seguintes métodos são invocados na coleção:
DeleteOneAsync : exclui um único documento que corresponde aos critérios de
pesquisa fornecidos.
Encontrar< TDocument> : retorna todos os documentos na coleção que
correspondem aos critérios de pesquisa fornecidos.
InsertOneAsync : insere o objeto fornecido como um novo documento na
coleção.
ReplaceOneAsync : substitui o único documento que corresponde aos critérios
de pesquisa fornecidos pelo objeto fornecido.
Adicionar um controlador
Adicione uma classe BooksController ao diretório Controladores com o seguinte código:
C#
using BookStoreApi.Models;
using BookStoreApi.Services;
using Microsoft.AspNetCore.Mvc;
namespace BookStoreApi.Controllers;
[ApiController]
[Route("api/[controller]")]
public class BooksController : ControllerBase
{
private readonly BooksService _booksService;
public BooksController(BooksService booksService) =>
_booksService = booksService;
[HttpGet]
public async Task<List<Book>> Get() =>
await _booksService.GetAsync();
[HttpGet("{id:length(24)}")]
public async Task<ActionResult<Book>> Get(string id)
{
var book = await _booksService.GetAsync(id);
if (book is null)
{
return NotFound();
}
return book;
}
[HttpPost]
public async Task<IActionResult> Post(Book newBook)
{
await _booksService.CreateAsync(newBook);
return CreatedAtAction(nameof(Get), new { id = newBook.Id },
newBook);
}
[HttpPut("{id:length(24)}")]
public async Task<IActionResult> Update(string id, Book updatedBook)
{
var book = await _booksService.GetAsync(id);
if (book is null)
{
return NotFound();
}
updatedBook.Id = book.Id;
await _booksService.UpdateAsync(id, updatedBook);
return NoContent();
}
[HttpDelete("{id:length(24)}")]
public async Task<IActionResult> Delete(string id)
{
var book = await _booksService.GetAsync(id);
if (book is null)
{
return NotFound();
}
await _booksService.RemoveAsync(id);
return NoContent();
}
}
O controlador da API Web anterior:
Usa a BooksService classe para executar operações CRUD.
Contém métodos de ação para dar suporte a solicitações GET, POST, PUT e DELETE
HTTP.
Chama o CreatedAtAction no método de ação Create para retornar uma resposta
HTTP 201 . O código de status 201 é a resposta padrão para um método HTTP
POST que cria um recurso no servidor. CreatedAtAction também adiciona um
cabeçalho Location à resposta. O cabeçalho Location especifica o URI do livro
recém-criado.
Testar a API Web
1. Compile e execute o aplicativo.
2. Navegue até https://localhost:<port>/api/books , em que <port> é o número da
porta atribuído automaticamente para o aplicativo, para testar o método de ação
sem Get parâmetros do controlador. Uma JSresposta ON semelhante à seguinte é
exibida:
JSON
[
{
"id": "61a6058e6c43f32854e51f51",
"bookName": "Design Patterns",
"price": 54.93,
"category": "Computers",
"author": "Ralph Johnson"
},
{
"id": "61a6058e6c43f32854e51f52",
"bookName": "Clean Code",
"price": 43.15,
"category": "Computers",
"author": "Robert C. Martin"
}
]
3. Navegue até https://localhost:<port>/api/books/{id here} para testar o método
de ação Get sobrecarregado do controlador. Uma JSresposta ON semelhante à
seguinte é exibida:
JSON
{
"id": "61a6058e6c43f32854e51f52",
"bookName": "Clean Code",
"price": 43.15,
"category": "Computers",
"author": "Robert C. Martin"
}
Configurar JSopções de serialização ON
Há dois detalhes a serem alterados sobre as JSrespostas ON retornadas na seção Testar
a API Web :
O uso de maiúsculas e minúsculas padrão dos nomes da propriedade deve ser
alterado para corresponder ao uso de maiúsculas e minúsculas Pascal dos nomes
de propriedade do objeto CLR.
A propriedade bookName deve ser retornada como Name .
Para cumprir os requisitos anteriores, faça as seguintes alterações:
1. Em Program.cs , encadeie o seguinte código realçado para a chamada de método
AddControllers :
C#
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
builder.Services.Configure<BookStoreDatabaseSettings>(
builder.Configuration.GetSection("BookStoreDatabase"));
builder.Services.AddSingleton<BooksService>();
builder.Services.AddControllers()
.AddJsonOptions(
options => options.JsonSerializerOptions.PropertyNamingPolicy =
null);
Com a alteração anterior, os nomes de propriedade na resposta ON serializada
JSda API Web correspondem aos nomes de propriedade correspondentes no tipo
de objeto CLR. Por exemplo, a Book propriedade da Author classe serializa como
Author em vez de author .
2. Em Models/Book.cs , anote a BookName propriedade com o [JsonPropertyName]
atributo :
C#
[BsonElement("Name")]
[JsonPropertyName("Name")]
public string BookName { get; set; } = null!;
O [JsonPropertyName] valor do atributo de Name representa o nome da
propriedade na resposta ON serializada JSda API Web.
3. Adicione o seguinte código à parte superior de Models/Book.cs para resolver a
referência de [JsonProperty] atributo:
C#
using System.Text.Json.Serialization;
4. Repita as etapas definidas na seção Testar a API Web. Observe a diferença nos
JSnomes de propriedade ON.
Adicionar suporte de autenticação a uma API
Web
Identity ASP.NET Core adiciona a funcionalidade de logon da interface do usuário para
ASP.NET Core aplicativos Web. Para proteger APIs Web e SPAs, use um dos seguintes:
Azure Active Directory
Azure Active Directory B2C (Azure AD B2C)
Servidor duende Identity
O Servidor Duende Identity é uma estrutura OpenID Connect e OAuth 2.0 para ASP.NET
Core. O Servidor Duende Identity habilita os seguintes recursos de segurança:
Autenticação como serviço (AaaS)
SSO (logon único) em vários tipos de aplicativo
Controle de acesso para APIs
Gateway de Federação
) Importante
O Software Duende pode exigir que você pague uma taxa de licença pelo uso de
produção do Duende Identity Server. Para obter mais informações, consulte Migrar
do ASP.NET Core 5.0 para o 6.0.
Para obter mais informações, consulte a documentação do Duende Identity Server (site
do Duende Software) .
Recursos adicionais
Exibir ou baixar código de exemplo (como baixar)