ASP.NET Core: O Guia Completo
Autoria (Autoria Discente)
Este material foi produzido como parte integrante da Atividade de Extensão do Curso Superior de Tecnologia em Análise e Desenvolvimento de Sistemas da UNIP.
Autores :
GUILHERME BORGES (G03IHI3)
IGOR VIEIRA MAGALHÃES (G0610I3)
KELWIN ALEXANDRE ASSENCIO MANGINI (G9936J5)
LEONARDO MONTEIRO MARQUES (R1885B9)
MIGUEL DOS SANTOS GALVÃO (R110IF1)
RAFAEL ARLES SOUZA DANTAS (R0796I0)
YGOR MOREIRA RIBAS (G9048H0)
DIEGO YUGI UEHARA(G9936G0)
Prefácio do Projeto de Extensão
1. Justificativa e Motivação
Este e-book justifica-se pela crescente demanda por desenvolvedores back-end qualificados no ecossistema.NET. Em um mercado de tecnologia que continua a se expandir, o ASP.NET Core se consolida como uma plataforma robusta, multiplataforma e de altíssima performance, essencial para a construção de aplicações corporativas, APIs escaláveis e microsserviços. Apesar de sua relevância, muitos iniciantes podem achar o ecossistema.NET complexo. Este projeto de extensão é motivado pela necessidade de um recurso educacional em português que desmistifique o ASP.NET Core para iniciantes. O objetivo é servir como uma ponte entre o conhecimento acadêmico e as exigências do mercado de trabalho de 2025, que busca profissionais com habilidades em arquiteturas modernas, seguras e eficientes.
2. Objetivos
do Projeto
● Objetivo Geral: Capacitar a comunidade em desenvolvimento web back-end usando o framework ASP.NET Core, fornecendo um guia completo e prático que fomente a autonomia no aprendizado e aumente a qualificação profissional.
● Objetivos Específicos:
○ Sintetizar os conceitos fundamentais do ecossistema.NET e da CLI.
○ Explicar e demonstrar os principais padrões de arquitetura (MVC, Razor Pages, Web API).
○ Introduzir o acesso a dados de forma prática com o Entity Framework Core.
○ Disponibilizar publicamente este e-book como uma ferramenta de consulta para a comunidade externa.
3. Público-Alvo
Este e-book destina-se a qualquer membro da comunidade externa à universidade interessado
em ingressar na área de desenvolvimento de software, com foco em:
● Indivíduos em transição de carreira que buscam uma especialização em back-end com alta demanda corporativa.
● Estudantes de cursos de tecnologia que desejam um material de apoio estruturado sobre o ecossistema.NET.
● Membros da comunidade local que desejam adquirir novas habilidades digitais para aumentar sua empregabilidade em um setor tecnológico de ponta.
Sobre Este Livro
Bem-vindo ao "ASP.NET Core: O Guia Completo". Este livro foi projetado para ser sua jornada definitiva no mundo do desenvolvimento web com a mais poderosa e moderna plataforma da Microsoft.
Seja você um desenvolvedor iniciante curioso sobre.NET ou um profissional experiente vindo de outras tecnologias, este guia fornecerá o conhecimento necessário para construir aplicações web robustas, performáticas e escaláveis.
Começaremos com os fundamentos do ecossistema.NET, desmistificando a CLI e a estrutura de um projeto. Em seguida, mergulharemos fundo nos principais padrões de arquitetura, como MVC e Razor Pages, e aprenderemos a construir APIs RESTful de alta qualidade.
Exploraremos o acesso a dados com o Entity Framework Core, a autenticação de usuários com ASP.NET Identity e os padrões de projeto essenciais, como Injeção de Dependência. Ao final desta jornada, você não apenas entenderá a teoria, mas terá aplicado todos os conceitos em um projeto final prático: a construção de um blog completo. Prepare-se para dominar o ASP.NET Core e elevar suas habilidades de desenvolvimento a um novo patamar.
Sumário
● Capítulo 1: Introdução ao Ecossistema.NET e ASP.NET Core
● Capítulo 2: Arquitetura MVC (Model-View-Controller)
● Capítulo 3: Razor Pages: Uma Abordagem Simplificada
● Capítulo 4: Construindo Web APIs com ASP.NET Core
● Capítulo 5: Acesso a Dados com Entity Framework Core
● Capítulo 6: Views, Layouts e a Sintaxe Razor
● Capítulo 7: Validação e Model Binding
● Capítulo 8: Autenticação e Autorização com ASP.NET Identity
● Capítulo 9: Injeção de Dependência (DI)
● Capítulo 10: O Pipeline de Middleware
● Capítulo 11: Configuração e Gerenciamento de Segredos
● Capítulo 12: Projeto Final: Criando um Blog Simples
● Glossário
Capítulo 1: Introdução ao Ecossistema.NET e ASP.NET Core
O que é a plataforma.NET?
.NET (pronuncia-se "dot net") é uma plataforma de desenvolvimento de software gratuita, de código aberto e multiplataforma, mantida pela Microsoft. Ela permite que desenvolvedores
criem diversos tipos de aplicações, como aplicações web, serviços de backend (APIs), aplicações desktop, aplicações móveis, jogos, soluções de Internet das Coisas (IoT) e muito mais.
O coração do.NET é o seu runtime (conhecido como Common Language Runtime - CLR), que gerencia a execução do código, e uma vasta biblioteca de classes base (Base Class LibraryBCL) que oferece milhares de funcionalidades prontas para uso, desde manipulação de arquivos e redes até estruturas de dados complexas.
####.NET Core /.NET 5+ vs..NET Framework
Por muitos anos, a principal implementação do.NET foi o.NET Framework. Ele era poderoso, mas tinha uma grande limitação: era exclusivo para o sistema operacional Windows. Para atender às demandas do desenvolvimento moderno (nuvem, contêineres, microsserviços), a Microsoft reconstruiu o.NET do zero, criando o.NET Core. As principais características do.NET Core eram:
● Multiplataforma: Roda em Windows, macOS e Linux.
● Código Aberto: Desenvolvido em colaboração com a comunidade no GitHub.
● Alta Performance: Otimizado para ser um dos frameworks mais rápidos do mercado.
● Modular: Projetado para ser leve e permitir que você use apenas os componentes necessários.
A partir da versão 5, a Microsoft unificou as plataformas. O ".NET Core" se tornou simplesmente ".NET" (ex:.NET 5,.NET 6,.NET 8, etc.). Hoje, quando falamos de desenvolvimento.NET moderno, estamos nos referindo a esta nova plataforma unificada. O.NET Framework está em modo de manutenção e não recebe novas funcionalidades.
O que é ASP.NET Core e suas vantagens
ASP.NET Core é o framework dentro da plataforma.NET para a construção de aplicações web. Ele é o sucessor moderno do antigo ASP.NET (que rodava sobre o.NET Framework). Com ele, podemos criar desde sites dinâmicos com interfaces ricas até APIs RESTful robustas para alimentar aplicações mobile e front-ends JavaScript.
Suas principais vantagens são:
● Performance Excepcional: ASP.NET Core é consistentemente classificado como um dos frameworks web mais rápidos do mundo, superando Node.js, Java (Spring) e outros em muitos benchmarks. Isso significa menos custos com servidores e uma melhor experiência para o usuário.
● Multiplataforma: Desenvolva em seu sistema operacional preferido (Windows, macOS ou Linux) e faça o deploy em qualquer um deles, incluindo contêineres Docker.
● Arquitetura Flexível: Suporta vários padrões de desenvolvimento, como MVC (ModelView-Controller), Razor Pages e a construção de APIs (Web API), permitindo que você escolha a abordagem certa para cada projeto.
● Ferramentas Modernas: Integra-se perfeitamente com IDEs poderosas como o Visual Studio e o Visual Studio Code, e possui uma rica ferramenta de linha de comando (CLI) para automação e produtividade.
Instalando o SDK do.NET e ferramentas
Para começar, você precisa do SDK do.NET (Software Development Kit). O SDK inclui tudo o que é necessário para desenvolver, construir e executar aplicações.NET: o compilador, o runtime e a CLI.
1. Acesse o site oficial do.NET: dotnet.microsoft.com/download
2. Baixe o instalador do SDK para a versão LTS (Long-Term Support) mais recente. A versão LTS é recomendada para a maioria dos projetos por ter um período de suporte
mais longo.
3. Siga as instruções de instalação para o seu sistema operacional. Para verificar se a instalação foi bem-sucedida, abra um terminal (Prompt de Comando, PowerShell ou Terminal) e digite: dotnet --version Você deverá ver a versão do SDK que acabou de instalar. Como editor de código, recomendamos o Visual Studio 2022 (Community Edition é gratuita) para Windows ou o Visual Studio Code (gratuito e multiplataforma) com a extensão C# Dev Kit da Microsoft.
Usando a CLI do.NET
A CLI (Command-Line Interface) do.NET é uma ferramenta poderosa para gerenciar seus projetos. Aqui estão os comandos mais básicos:
● dotnet new [template]: Cria um novo projeto a partir de um template. Por exemplo, dotnet new webapp cria uma aplicação com Razor Pages.
● dotnet build: Compila o projeto no diretório atual.
● dotnet run: Compila e executa o projeto.
● dotnet add package [nome-do-pacote]: Adiciona uma dependência (pacote NuGet) ao projeto.
● dotnet restore: Restaura as dependências do projeto.
Exercício: Crie e execute seu primeiro projeto "Hello World" em ASP.NET Core
Vamos colocar a mão na massa! Siga os passos abaixo no seu terminal.
1. Crie uma nova pasta para o projeto e entre nela: mkdir MeuPrimeiroApp cd MeuPrimeiroApp
2. Crie um novo projeto ASP.NET Core vazio usando o template "web": dotnet new web
3. Restaure as dependências (geralmente é feito automaticamente, mas é uma boa prática): dotnet restore
4. Execute a aplicação: dotnet run
5. O terminal mostrará uma mensagem indicando que o servidor está rodando, geralmente em http://localhost:5000 ou https://localhost:5001. Abra essa URL no seu navegador. Você deverá ver a mensagem "Hello World!". Parabéns, você acaba de criar e executar sua primeira aplicação ASP.NET Core!
Capítulo 2: Arquitetura MVC (Model-View-Controller)
Entendendo o padrão de projeto MVC
O padrão de projeto Model-View-Controller (MVC) é uma das arquiteturas mais populares para a construção de aplicações web. Seu objetivo principal é a separação de responsabilidades, dividindo a aplicação em três componentes interconectados, cada um com uma função específica.
● Model (Modelo): Responsável pelos dados e pela lógica de negócio da aplicação. Ele não sabe nada sobre a interface do usuário. Pense nele como o cérebro e a memória da aplicação.
● View (Visão): Responsável pela apresentação dos dados ao usuário. É a interface do
usuário (UI), geralmente composta por arquivos HTML. A View deve ser "burra", apenas exibindo os dados que recebe.
● Controller (Controlador): Atua como o intermediário entre o Model e a View. Ele recebe as requisições do usuário, interage com o Model para buscar ou manipular dados, e então seleciona a View apropriada para exibir o resultado. Essa separação torna o código mais organizado, fácil de manter, testar e evoluir, pois cada parte pode ser trabalhada de forma independente.
Models: Representando os dados da aplicação
No ASP.NET Core, um Model é tipicamente uma classe C# simples (também conhecida como POCO - Plain Old CLR Object). Ela representa as entidades do seu domínio de negócio. Por exemplo, em uma aplicação de e-commerce, você teria models como Produto, Cliente e Pedido.
public class Produto { public int Id { get; set; } public string Nome { get; set; } public decimal Preco { get; set; } public string Descricao { get; set; } }
Views: A camada de apresentação (HTML com Razor)
A View é a parte que o usuário final vê e interage. No ASP.NET Core, as Views são criadas usando a sintaxe Razor, que permite mesclar código C# diretamente em arquivos HTML. Arquivos Razor têm a extensão .cshtml.
A View recebe um Model do Controller e usa a sintaxe Razor para exibir dinamicamente os dados desse model. Por exemplo, para exibir os detalhes de um produto: @model MeuApp.Models.Produto
<h1>Detalhes do Produto</h1>
<div> <h4>@Model.Nome</h4> <p>Preço: @Model.Preco.ToString("C")</p> <p>@Model.Descricao</p> </div>
Controllers: Orquestrando as requisições
O Controller é uma classe C# que herda de Microsoft.AspNetCore.Mvc.Controller. Seus métodos públicos são chamados de Actions, e cada Action corresponde a uma URL que pode ser acessada pelo usuário.
A responsabilidade da Action é processar a requisição, interagir com os Models (por exemplo, buscar um produto no banco de dados) e, por fim, retornar um resultado, que geralmente é uma View com os dados necessários.
public class ProdutosController : Controller
{
// Action para exibir os detalhes de um produto public IActionResult Detalhes(int id)
{
// 1. Interage com o Model (aqui, simulamos a busca de dados) Produto produto = BuscarProdutoPorId(id);
if (produto == null)
{ return NotFound(); // Retorna um erro 404 se o produto não for encontrado }
// 2. Retorna a View, passando o objeto 'produto' como Model return View(produto); }
private Produto BuscarProdutoPorId(int id)
{ // Em um cenário real, aqui seria a lógica para buscar no banco de dados
return new Produto { Id = id, Nome = "Notebook Gamer", Preco = 7500.00m, Descricao = "Ótimo para jogos e trabalho." }; } }
O ciclo de vida de uma requisição em ASP.NET Core MVC
1. O usuário digita uma URL no navegador (ex: /Produtos/Detalhes/1).
2. O sistema de roteamento do ASP.NET Core analisa a URL e determina que a requisição deve ser tratada pelo Controller ProdutosController e pela Action Detalhes, passando 1 como o parâmetro id.
3. A Action Detalhes é executada.
4. A Action interage com a camada de Model para obter os dados do produto com ID 1.
5. A Action chama o método View() e passa o objeto do produto como argumento.
6. O ASP.NET Core localiza o arquivo da View correspondente (por convenção, /Views/Produtos/Detalhes.cshtml).
7. O motor Razor processa a View, substituindo o código C# (@Model.Nome) pelos valores do objeto do produto, gerando um HTML puro.
8. O HTML gerado é enviado de volta como resposta ao navegador do usuário, que o renderiza.
Convenção sobre Configuração
O ASP.NET Core MVC utiliza fortemente o princípio de "Convenção sobre Configuração". Isso significa que o framework assume certos padrões para reduzir a quantidade de configuração explícita que você precisa fazer. Por exemplo:
● Um Controller chamado ProdutosController está associado à rota /Produtos.
● Uma Action chamada Detalhes está associada à rota .../Detalhes.
● O framework procura pela View da Action Detalhes do ProdutosController no caminho Views/Produtos/Detalhes.cshtml.
Seguir essas convenções torna o desenvolvimento muito mais rápido e o código mais previsível.
Exercício: Crie um Controller simples que passe dados para uma View
Vamos criar uma página que exibe uma mensagem de boas-vindas personalizada.
1. Crie um novo projeto MVC: dotnet new mvc -n AppMvc.
2. Navegue até a pasta Controllers e crie um novo arquivo chamado SaudacaoController.cs.
3. Adicione o seguinte código ao controller: using Microsoft.AspNetCore.Mvc;
public class SaudacaoController : Controller { public IActionResult Index(string nome = "Visitante") { // ViewData é uma forma simples de passar dados para a View ViewData["Mensagem"] = $"Olá, {nome}! Bem-vindo ao nosso site."; return View(); } }
4. Na pasta Views, crie uma nova pasta chamada Saudacao.
5. Dentro de Views/Saudacao, crie um arquivo chamado Index.cshtml.
6. Adicione o seguinte código à View: @{
ViewData = "Boas-vindas"; }
<h1>Página de Saudação</h1> <p>@ViewData["Mensagem"]</p>
7. Execute a aplicação (dotnet run) e acesse as URLs no seu navegador: /Saudacao e /Saudacao?nome=Ygor. Observe como a mensagem muda!
Capítulo 3: Razor Pages: Uma Abordagem Simplificada
O que são Razor Pages e quando usá-las
Razor Pages é um modelo de programação alternativo ao MVC, também construído sobre o ASP.NET Core. Ele oferece uma abordagem mais simples e focada em páginas (page-centric) para a construção de aplicações web. Enquanto o MVC é excelente para aplicações complexas com lógicas de negócio ricas, Razor Pages brilha em cenários onde a aplicação é organizada em torno de páginas individuais, como formulários, painéis administrativos e a maioria dos sites baseados em conteúdo.
A principal diferença é que, em Razor Pages, a lógica do Controller e o markup da View são mantidos juntos, em dois arquivos acoplados: um arquivo .cshtml (a View) e um arquivo .cshtml.cs (o "code-behind", chamado de PageModel).
Use Razor Pages quando:
● Sua aplicação é baseada em formulários e operações CRUD (Create, Read, Update, Delete) simples.
● Você prefere uma separação de responsabilidades mais vertical (tudo relacionado a uma página está em um só lugar).
● O fluxo da aplicação é mais linear e menos complexo.
● Você está começando com ASP.NET Core e quer uma curva de aprendizado mais suave.
A classe PageModel e a separação de interesses
O arquivo .cshtml.cs contém uma classe que herda de PageModel. Esta classe é análoga a um Controller no MVC, mas está diretamente ligada a uma única página Razor. É nela que você coloca as propriedades para os dados da página e os métodos (chamados de handlers) para lidar com as requisições HTTP. // Exemplo de um PageModel (Index.cshtml.cs) using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.RazorPages;
public class IndexModel : PageModel {
// Propriedade para ser acessada na página Razor public string Mensagem { get; private set; }
// Handler para requisições GET public void OnGet() { Mensagem = "Bem-vindo ao mundo das Razor Pages!"; } }
Essa estrutura mantém uma clara separação de interesses: o PageModel cuida da lógica e dos dados, enquanto o arquivo .cshtml cuida exclusivamente da apresentação.
Sintaxe Razor: @page, @model
O arquivo .cshtml em Razor Pages tem algumas diretivas importantes:
● @page: Esta é a diretiva mais crucial. Ela deve estar na primeira linha do arquivo e indica ao ASP.NET Core que este arquivo é uma Razor Page e pode ser acessado diretamente via roteamento.
● @model: Especifica o tipo da classe PageModel associada a esta página. Isso permite que você acesse as propriedades e métodos do PageModel de forma fortemente tipada. @page @model IndexModel @{
ViewData = "Página Inicial"; }
<h1>Razor Pages</h1> <p>@Model.Mensagem</p>
No exemplo acima, @Model.Mensagem acessa a propriedade Mensagem que definimos na classe IndexModel.
Handlers de página (OnGet, OnPost)
Os métodos no PageModel que respondem a verbos HTTP são chamados de handlers. Eles seguem a convenção de nomenclatura On[VerboHttp]Async.
● OnGet() ou OnGetAsync(): Executado quando a página é solicitada via HTTP GET. Ideal para carregar os dados iniciais da página.
● OnPost() ou OnPostAsync(): Executado quando um formulário na página é submetido via HTTP POST. Ideal para processar os dados do formulário.
Data binding com `` e asp-for
Um dos recursos mais poderosos do Razor é o "data binding". Em Razor Pages, você pode decorar uma propriedade no seu PageModel com o atributo ``. Isso instrui o ASP.NET Core a automaticamente vincular os dados de um formulário enviado a essa propriedade. Na View, você usa o Tag Helper asp-for para conectar um elemento de formulário (como um <input>) a uma propriedade do seu modelo. Isso gera automaticamente o id, name e value corretos.
Exercício: Crie um formulário de contato simples com Razor Pages
Vamos criar uma página de contato que recebe nome, e-mail e mensagem.
1. Crie um novo projeto Razor Pages: dotnet new webapp -n AppRazor. Entre na pasta AppRazor.
2. Na pasta Pages, crie um novo arquivo chamado Contato.cshtml com o seguinte conteúdo: @page @model ContatoModel @{ ViewData = "Contato"; }
<h1>Entre em Contato</h1>
@if (!string.IsNullOrEmpty(Model.MensagemFeedback)) { <div class="alert alert-success">@Model.MensagemFeedback</div> }
<form method="post">
<div class="form-group mb-3"> <label asp-for="Input.Nome"></label> <input asp-for="Input.Nome" class="form-control" />
</div>
<div class="form-group mb-3">
<label asp-for="Input.Email"></label> <input asp-for="Input.Email" class="form-control" /> </div>
<div class="form-group mb-3">
<label asp-for="Input.Mensagem"></label> <textarea asp-for="Input.Mensagem" class="form-control" rows="5"></textarea>
</div> <button type="submit" class="btn btn-primary">Enviar</button> </form>
3. Crie o arquivo code-behind Contato.cshtml.cs na mesma pasta: using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.RazorPages;
public class ContatoModel : PageModel {
public InputModel Input { get; set; }
public string MensagemFeedback { get; set; }
public void OnGet()
{ // Página carregada pela primeira vez }
public IActionResult OnPost()
{ // Lógica para processar o formulário aqui (ex: enviar email)
// Por enquanto, apenas exibiremos uma mensagem de sucesso.
MensagemFeedback = $"Obrigado, {Input.Nome}! Sua mensagem foi recebida."; return Page();
} // Classe interna para organizar os dados do formulário public class InputModel
{ public string Nome { get; set; } public string Email { get; set; } public string Mensagem { get; set; } } }
4. Execute a aplicação (dotnet run) e acesse /Contato. Preencha o formulário e envie. Observe a mensagem de feedback aparecer!
Capítulo 4: Construindo Web APIs com ASP.NET Core
O que é uma API RESTful?
Uma API (Application Programming Interface) é um conjunto de regras que permite que diferentes sistemas de software se comuniquem. Uma Web API é uma API acessível pela web, geralmente através do protocolo HTTP.
REST (Representational State Transfer) é um estilo arquitetural para a construção de Web APIs. Uma API que segue os princípios do REST é chamada de RESTful. As principais características são:
● Stateless (Sem Estado): Cada requisição do cliente deve conter toda a informação necessária para o servidor entendê-la. O servidor não armazena o estado da sessão.
● Interface Uniforme: Utiliza os verbos HTTP (GET, POST, PUT, DELETE) e os códigos de status HTTP para representar ações e resultados. Os dados são trocados em formatos padrão como JSON.
Web APIs são a espinha dorsal da web moderna, usadas para conectar aplicações front-end (React, Angular, Vue), aplicativos móveis e outros serviços.
Criando Controllers de API com [ApiController]
Em ASP.NET Core, criar uma API é semelhante a criar um Controller MVC. A principal diferença é que a classe herda de ControllerBase (em vez de Controller, que inclui suporte a Views) e é decorada com o atributo [ApiController].
O atributo [ApiController] habilita vários comportamentos úteis para APIs, como a validação automática de modelo (retornando um erro 400 Bad Request se a requisição for inválida) e a inferência de fonte de binding.
Verbos
HTTP: GET, POST, PUT, DELETE
Mapeamos os verbos HTTP para as operações CRUD (Create, Read, Update, Delete):
● GET: Usado para ler/recuperar dados. (Ex: GET /api/tarefas/5)
● POST: Usado para criar um novo recurso. (Ex: POST /api/tarefas)
● PUT: Usado para atualizar/substituir um recurso existente. (Ex: PUT /api/tarefas/5)
● DELETE: Usado para remover um recurso. (Ex: DELETE /api/tarefas/5)
Em ASP.NET Core, associamos esses verbos às nossas actions usando atributos como [HttpGet], [HttpPost], [HttpPut] e ``.
Retornando dados (JSON) e códigos de status HTTP
APIs não retornam HTML. Elas retornam dados brutos, geralmente no formato JSON. O ASP.NET Core automaticamente serializa (converte) seus objetos C# em JSON. É fundamental retornar o código de status HTTP correto para indicar o resultado da operação. A classe ControllerBase oferece métodos auxiliares para isso:
● Ok(object): Retorna 200 OK
● CreatedAtAction(...): Retorna 201 Created.
● NoContent(): Retorna 204 No Content
● BadRequest(): Retorna 400 Bad Request
● NotFound(): Retorna 404 Not Found
Exercício: Crie uma API para gerenciar uma lista de tarefas (To-Do list)
Vamos criar uma API CRUD completa para gerenciar tarefas, usando uma lista em memória.
1. Crie um novo projeto de Web API: dotnet new webapi -n TodoApi.
2. Crie uma pasta Models e dentro dela um arquivo TodoItem.cs: public class TodoItem {
public long Id { get; set; } public string? Nome { get; set; } public bool IsCompleta { get; set; } }
3. Na pasta Controllers, crie um arquivo TodoItemsController.cs: using Microsoft.AspNetCore.Mvc; using TodoApi.Models; // Adicione o using para seu modelo [ApiController]
")] public class TodoItemsController : ControllerBase { // Usando uma lista estática para simular um banco de dados em memória private static readonly List<TodoItem> _items = new(); private static long _nextId = 1; [HttpGet] public ActionResult<IEnumerable<TodoItem>> GetAll() { return Ok(_items); } [HttpGet("{id}")] public ActionResult<TodoItem> GetById(long id) { var item = _items.Find(i => i.Id == id); if (item == null) { return NotFound(); } return Ok(item); } [HttpPost] public ActionResult<TodoItem> Create(TodoItem newItem) { newItem.Id = _nextId++; _items.Add(newItem); return CreatedAtAction(nameof(GetById), new { id = newItem.Id }, newItem); } [HttpPut("{id}")] public IActionResult Update(long id, TodoItem updatedItem) { var index = _items.FindIndex(i => i.Id == id); if (index == -1) { return NotFound(); } updatedItem.Id = id; // Garante que o ID não seja alterado _items[index] = updatedItem; return NoContent(); } public IActionResult Delete(long id) { var item = _items.Find(i => i.Id == id); if (item == null) { return NotFound(); } _items.Remove(item); return NoContent(); } } ``` 4. Execute a aplicação (dotnet run). O template de Web API já vem com o Swagger UI, uma interface gráfica para testar sua API. Acesse a URL fornecida (geralmente /swagger) no seu navegador e teste todos os endpoints.
Capítulo 5: Acesso a Dados com Entity Framework Core
O que é um ORM (Object-Relational Mapper)?
A maioria das aplicações precisa persistir dados em um banco de dados (como SQL Server, PostgreSQL ou SQLite). Um Object-Relational Mapper (ORM) é uma biblioteca que automatiza essa tarefa, permitindo que você interaja com o banco de dados usando objetos C# em vez de escrever SQL manualmente.
O ORM faz o "mapeamento" entre seus Models (classes C#) e as tabelas do banco de dados. Entity Framework Core (EF Core) é o ORM oficial, moderno, de código aberto e multiplataforma da Microsoft para a plataforma.NET.
Configurando o DbContext
A classe principal no EF Core é o DbContext. Ela representa uma sessão com o banco de dados. Você cria uma classe que herda de DbContext e define propriedades do tipo DbSet<T> para cada entidade que deseja mapear para uma tabela. using Microsoft.EntityFrameworkCore;
public class TodoContext : DbContext { public TodoContext(DbContextOptions<TodoContext> options) : base(options) { }
// Cada DbSet será mapeado para uma tabela no banco de dados public DbSet<TodoItem> TodoItems { get; set; } }
A configuração do DbContext, incluindo a string de conexão, é feita no arquivo Program.cs usando Injeção de Dependência.
Abordagem Code-First
O EF Core suporta a abordagem Code-First, onde o banco de dados é gerado a partir do seu código C#. Suas classes C# (seus Models) são a "fonte da verdade". O EF Core analisa essas classes e, através de um processo chamado Migrations, gera o esquema do banco de dados (tabelas, colunas, etc.).
Migrations: Gerenciando as mudanças no schema
Conforme sua aplicação evolui, seus modelos de dados mudarão. As Migrations são a forma como o EF Core gerencia e aplica essas mudanças ao banco de dados.
Você usa as ferramentas de linha de comando do EF Core para gerenciar as migrations. Primeiro, instale a ferramenta: dotnet tool install --global dotnet-ef Os comandos principais são:
● dotnet ef migrations add: Compara seu modelo de código atual com o banco e gera o código C# para a migração.
● dotnet ef database update: Aplica as migrations pendentes ao banco de dados.
Operações CRUD (Create, Read, Update, Delete) com EF Core
Uma vez que seu DbContext está configurado, realizar operações CRUD se torna muito simples, usando LINQ (Language-Integrated Query). public class TodoItemsController : ControllerBase { private readonly TodoContext _context;
// O DbContext é injetado pelo container de DI (Cap. 9) public TodoItemsController(TodoContext context)
{ _context = context; }
// READ (Ler todos) [HttpGet]
public async Task<ActionResult<IEnumerable<TodoItem>>> GetTodoItems() { return await _context.TodoItems.ToListAsync(); }
// CREATE (Criar) [HttpPost]
public async Task<ActionResult<TodoItem>> PostTodoItem(TodoItem todoItem) { _context.TodoItems.Add(todoItem); await _context.SaveChangesAsync(); // Salva as mudanças no banco return CreatedAtAction(...); }
// DELETE (Deletar)
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(); } }
O método SaveChangesAsync() é o que de fato executa os comandos SQL no banco de dados.
Exercício: Integre o EF Core à sua API de tarefas
Vamos modificar a API do capítulo anterior para usar um banco de dados SQLite.
1. No projeto TodoApi, adicione os pacotes NuGet necessários: dotnet add package Microsoft.EntityFrameworkCore.Sqlite dotnet add package Microsoft.EntityFrameworkCore.Design
2. Crie o arquivo Data/TodoContext.cs (use o exemplo da seção "Configurando o DbContext").
3. No arquivo appsettings.json, adicione a string de conexão:
"ConnectionStrings": { "DefaultConnection": "DataSource=todo.db" }
4. No arquivo Program.cs, configure o serviço do DbContext: builder.Services.AddDbContext<TodoContext>(options => options.UseSqlite(builder.Configuration.GetConnectionString("Defau ltConnection")));
5. Crie sua primeira migration: dotnet ef migrations add InitialCreate
6. Aplique a migration para criar o banco de dados: dotnet ef database update
7. Refatore seu TodoItemsController.cs para injetar o TodoContext e usar os métodos do EF Core (como no exemplo CRUD) em vez da lista estática. Lembre-se de tornar seus métodos async e usar await.
8. Execute a aplicação. Agora, suas tarefas persistirão!
Capítulo 6: Views, Layouts e a Sintaxe Razor
Criando Views dinâmicas para exibir dados
Como vimos no Capítulo 2, as Views renderizam a interface. A Sintaxe Razor permite uma transição fluida entre HTML e C# usando o símbolo @. O Razor é inteligente o suficiente para entender onde seu código C# termina.
Você pode usar estruturas de controle C# comuns, como @if, @foreach, e @switch para gerar HTML dinamicamente.
@model List<Produto>
<h1>Lista de Produtos</h1>
@if (Model.Count == 0)
{ <p>Nenhum produto cadastrado.</p> } else
{ <ul> @foreach (var produto in Model)
{ <li>
@produto.Nome - @produto.Preco.ToString("C") </li> } </ul> }
Páginas de Layout (_Layout.cshtml) para uma UI consistente
A maioria dos sites tem uma estrutura comum (cabeçalho, rodapé, menus). Para evitar repetição, usamos páginas de Layout. Por convenção, o arquivo de layout principal fica em /Views/Shared/_Layout.cshtml.
Este arquivo define a estrutura HTML principal. O ponto-chave é a chamada ao método @RenderBody(). Este método atua como um placeholder onde o conteúdo da View específica (como Index.cshtml) será injetado.
<!DOCTYPE html> <html> <head>
<title>@ViewData - Meu Site</title> </head> <body> <header> </header>
<div class="container"> <main>
@RenderBody() </main> </div> <footer> © 2024 - Meu Site </footer> </body> </html>
Tag Helpers (asp-controller,
asp-action)
Tag Helpers são um dos recursos mais poderosos do Razor. Eles permitem que você use atributos especiais em elementos HTML para que o servidor os processe e gere o HTML final. Isso torna o código Razor muito mais limpo.
● Anchor Tag Helper (<a>): Gera URLs de forma segura. <a asp-controller="Produtos" asp-action="Detalhes" asp-routeid="5">Detalhes</a>
● Form Tag Helpers (<form>, <input>, <label>): Conectam o formulário ao seu Model, configuram id, name, value e exibem mensagens de validação. <form asp-action="Login" method="post"> <label asp-for="Email"></label> <input asp-for="Email" class="form-control" /> <span asp-validation-for="Email" class="text-danger"></span> </form>
Partial Views para reutilizar componentes de UI
Para pedaços de UI reutilizáveis que não são um layout completo (ex: um card de produto, uma barra lateral), usamos Partial Views. Uma Partial View é um arquivo .cshtml (ex: _CardProduto.cshtml) que é renderizado dentro de outra View principal.
@foreach (var produto in Model.Produtos) { <partial name="_CardProduto" model="produto" /> }
Exercício: Crie um layout base
1. Use o projeto MVC criado no Capítulo 2 (AppMvc).
2. Examine o arquivo Views/Shared/_Layout.cshtml.
3. Personalize o cabeçalho e adicione um novo link no menu de navegação que aponte para a página /Saudacao que criamos no Capítulo 2. <li class="nav-item">
<a class="nav-link text-dark" asp-area="" aspcontroller="Saudacao" asp-action="Index">Saudação</a> </li>
4. Execute a aplicação. Navegue entre as páginas Home e Saudação. Observe como o cabeçalho e o rodapé permanecem consistentes.
Capítulo 7: Validação e Model Binding
O que é Model Binding?
Model Binding é o processo pelo qual o ASP.NET Core pega dados de uma requisição HTTP (formulários, rotas, query strings) e os converte em parâmetros para uma action de controller ou propriedades de um PageModel. Essencialmente, ele preenche automaticamente seus objetos C# com os dados da requisição, economizando muito código manual.
Usando Data Annotations (, )
A validação é crucial. O ASP.NET Core oferece uma maneira declarativa de definir regras de validação diretamente em suas classes de modelo, usando Data Annotations. Data Annotations são atributos (do namespace System.ComponentModel.DataAnnotations) que você aplica às propriedades do seu modelo.
● ``: O campo não pode ser nulo ou vazio.
● ``: Define o tamanho máximo e mínimo de uma string.
● ``: O valor numérico deve estar dentro de um intervalo.
● [EmailAddress]: O valor deve ser um e-mail válido.
● [Compare("OutraPropriedade")]: O valor deve ser igual ao de outra propriedade (útil para confirmação de senha). public class RegistroViewModel { [EmailAddress] public string Email { get; set; }
public string Senha { get; set; }
public string ConfirmarSenha { get; set; } }
A propriedade ModelState nos Controllers
Após o model binding, o framework executa a validação. O resultado é armazenado na propriedade ModelState. A propriedade ModelState.IsValid retorna true se não houver erros. É uma prática padrão verificar ModelState.IsValid no início de qualquer action que processe dados (POST ou PUT). Se for inválido, você retorna a mesma View, para que o usuário possa ver os erros.
[HttpPost]
public IActionResult Registrar(RegistroViewModel model) { if (!ModelState.IsValid) { // O modelo tem erros. Retorna a mesma view para exibir os erros.
return View(model); }
// Se chegou aqui, o modelo é válido. Prossiga com a lógica. //...
return RedirectToAction("Sucesso"); }
Exibindo mensagens de erro na View
Para que o usuário veja os erros, usamos os Validation Tag Helpers:
● asp-validation-for: Exibe a mensagem de erro para uma propriedade específica.
● asp-validation-summary: Exibe uma lista de todos os erros em um único local. <form method="post">
<div asp-validation-summary="ModelOnly" class="alert alertdanger"></div>
<div class="form-group"> <label asp-for="Email"></label> <input asp-for="Email" class="form-control" /> <span asp-validation-for="Email" class="text-danger"></span> </div> </form>
Exercício: Adicione validações ao seu formulário de contato
1. Abra o projeto AppRazor (Capítulo 3).
2. Navegue até o arquivo Pages/Contato.cshtml.cs.
3. Adicione o using System.ComponentModel.DataAnnotations;.
4. Modifique a classe InputModel para adicionar Data Annotations: public class InputModel {
public string Nome { get; set; }
[EmailAddress(ErrorMessage = "Por favor, insira um e-mail válido.")]
public string Email { get; set; }
public string Mensagem { get; set; } }
5. Modifique o handler OnPost para verificar o ModelState: public IActionResult OnPost() { if (!ModelState.IsValid) { return Page(); // Retorna a página para mostrar os erros }
MensagemFeedback = $"Obrigado, {Input.Nome}! Sua mensagem foi recebida."; return Page(); }
6. Abra Pages/Contato.cshtml e adicione os <span> de validação para cada campo: <div class="form-group mb-3"> <label asp-for="Input.Nome"></label> <input asp-for="Input.Nome" class="form-control" /> <span asp-validation-for="Input.Nome" class="text-danger"></span> </div>
7. Execute a aplicação. Tente enviar o formulário em branco.
Capítulo 8: Autenticação e Autorização com ASP.NET Identity
Conceitos: Autenticação vs. Autorização
● Autenticação: É o processo de verificar quem você é. (Ex: Login e senha).
● Autorização: É o processo de verificar o que você tem permissão para fazer. (Ex: "Admins" podem deletar, "Usuários" podem apenas ver).
Configurando o ASP.NET Core Identity
ASP.NET Core Identity é um sistema completo que cuida do gerenciamento de usuários: registro, login, logout, gerenciamento de senhas, etc.
A maneira mais fácil de configurar é durante a criação do projeto: dotnet new mvc --auth Individual
Este comando configura automaticamente o DbContext do Identity (ApplicationDbContext), registra os serviços e adiciona o middleware de autenticação (app.UseAuthentication()) e autorização (app.UseAuthorization()) no Program.cs.
Scaffolding das páginas de login
O Identity vem com uma UI padrão (login, registro, etc.). Você pode gerar o código-fonte dessas páginas no seu projeto para personalizá-las. Isso é chamado de scaffolding
1. Instale a ferramenta de scaffolding: dotnet tool install -g dotnet-aspnet-codegenerator
2. Adicione o pacote de design: dotnet add package Microsoft.VisualStudio.Web.CodeGeneration.Design
3. Execute o scaffolding (exemplo para gerar Login e Register): dotnet aspnetcodegenerator identity -n SimpleBlog.Data.ApplicationDbContext --files "Account.Register;Account.Login"
Isso criará os arquivos em Areas/Identity/Pages/Account.
Protegendo Controllers e Actions com [Authorize]
Depois de configurado, proteger o acesso é simples. Use o atributo [Authorize].
● Aplicado a um Controller: Todas as actions dentro dele exigirão login. [Authorize]
public class PainelController : Controller
{ // Todas as actions aqui são protegidas }
● Aplicado a uma Action: Apenas aquela action específica exigirá login. public class HomeController : Controller {
public IActionResult Index() { return View(); } // Acessível a todos
[Authorize]
public IActionResult Perfil() { return View(); } // Apenas para usuários logados }
Se um usuário não autenticado tentar acessar, ele será redirecionado para a página de login.
Exercício: Adicione um sistema de login à sua aplicação
1. Crie um novo projeto MVC com autenticação individual: dotnet new mvc -n AppSegura -auth Individual
2. Ajuste a string de conexão em appsettings.json para usar SQLite (como no Cap. 5): "DefaultConnection": "DataSource=app.db"
3. Em Program.cs, troque UseSqlServer por UseSqlite.
4. Adicione o pacote SQLite: dotnet add package Microsoft.EntityFrameworkCore.Sqlite
5. Aplique as migrations do Identity: dotnet ef database update
6. Crie um novo controller AreaRestritaController.cs e proteja-o: using Microsoft.AspNetCore.Authorization; // Importante! using Microsoft.AspNetCore.Mvc;
[Authorize] // Protege o controller inteiro public class AreaRestritaController : Controller { public IActionResult Index() { return Content("Bem-vindo à área segura!"); } }
7. Execute a aplicação. Tente acessar /AreaRestrita. Você será redirecionado para o login.
8. Clique em "Register", crie uma conta e faça login.
9. Acesse /AreaRestrita novamente. Agora você conseguirá ver a página!
Capítulo 9: Injeção de Dependência (DI)
O que é Inversão de Controle (IoC) e Injeção de Dependência?
Inversão de Controle (IoC) é um princípio onde o controle sobre a criação de objetos é transferido para um framework ou container. Injeção de Dependência (DI) é o padrão que implementa a IoC. Em vez de uma classe criar suas próprias dependências (ex: var db = new MeuDbContext()), ela as recebe de fora, geralmente através de seu construtor.
Isso traz enormes benefícios:
● Baixo Acoplamento: As classes não dependem de implementações concretas, mas sim de abstrações (interfaces).
● Maior Testabilidade: Facilita testes de unidade, pois você pode "injetar" dependências falsas (mocks).
● Código mais Limpo: As responsabilidades ficam mais claras.
O container de DI nativo do ASP.NET Core
O ASP.NET Core foi projetado com DI em seu núcleo. O processo envolve dois passos:
1. Registrar o serviço: Em Program.cs, você informa ao container de DI como criar uma instância de um serviço (mapeando uma interface para uma classe).
2. Consumir o serviço: Em seus Controllers ou PageModels, você solicita o serviço no construtor.
Tempos de vida dos serviços: Singleton, Scoped e Transient
Ao registrar um serviço, você define seu tempo de vida:
● Transient: Uma nova instância é criada toda vez que o serviço é solicitado. builder.Services.AddTransient<IMeuServico, MeuServico>();
● Scoped: Uma única instância é criada por requisição HTTP. Todos que pedirem o serviço dentro daquela requisição compartilharão a mesma instância. É o tempo de vida mais comum (o DbContext do EF Core é Scoped). builder.Services.AddScoped<IMeuServico, MeuServico>();
● Singleton: Uma única instância é criada na primeira vez e reutilizada por toda a vida da aplicação. builder.Services.AddSingleton<IMeuServico, MeuServico>();
Registrando e consumindo serviços
1. Definir a Interface: public interface IServicoDeMensagem { string GetMensagem(); }
2. Criar a Implementação: public class ServicoDeMensagemSimples : IServicoDeMensagem { public string GetMensagem() { return "Olá do Serviço de Mensagem!"; } }
3. Registrar em Program.cs: builder.Services.AddScoped<IServicoDeMensagem, ServicoDeMensagemSimples>();
4. Consumir (injetar) no Controller: public class HomeController : Controller { private readonly IServicoDeMensagem _servicoDeMensagem; // O container de DI injetará a implementação registrada aqui public HomeController(IServicoDeMensagem servicoDeMensagem) { _servicoDeMensagem = servicoDeMensagem; } public IActionResult Index() { ViewData = _servicoDeMensagem.GetMensagem(); return View(); } }
Exercício: Crie um serviço simples e injete-o
1. Crie um novo projeto MVC (AppDI).
2. Crie a interface INumeroAleatorioService e a classe NumeroAleatorioService (veja abaixo).
// Interface
public interface INumeroAleatorioService { int Numero { get; } }
// Classe
public class NumeroAleatorioService : INumeroAleatorioService { public int Numero { get; }
public NumeroAleatorioService()
{ Numero = new Random().Next(1, 1001); } }
3. Em Program.cs, registre o serviço como Scoped: builder.Services.AddScoped<INumeroAleatorioService, NumeroAleatorioService>();
4. Modifique o HomeController.cs para injetar o serviço e passar o número para a View: private readonly INumeroAleatorioService _numeroService; public HomeController(INumeroAleatorioService numeroService) { _numeroService = numeroService;
}
public IActionResult Index()
{ ViewBag.Numero = _numeroService.Numero; return View();
}
5. Em Views/Home/Index.cshtml, exiba o número: <h2>Número Aleatório: @ViewBag.Numero</h2>
6. Execute. Atualize a página várias vezes (o número deve mudar a cada atualização, pois é Scoped).
7. Desafio: Mude o registro para AddSingleton e execute novamente. O número agora permanecerá o mesmo, não importa quantas vezes você atualize, até que a aplicação seja reiniciada.
Capítulo 10: O Pipeline de Middleware
O que é um Middleware?
No ASP.NET Core, toda requisição HTTP passa por um pipeline (uma "linha de montagem"). Cada componente nessa linha é um Middleware
Imagine a requisição entrando em uma ponta e a resposta saindo na outra. Cada middleware na linha tem a oportunidade de:
1. Examinar e modificar a requisição.
2. Passar a requisição para o próximo middleware.
3. Gerar uma resposta e "curto-circuitar" o pipeline (impedir que a requisição continue).
4. Examinar e modificar a resposta no caminho de volta. A ordem em que os middlewares são adicionados é crucial.
Configurando o pipeline no arquivo Program.cs
O pipeline é configurado no Program.cs (após a linha var app = builder.Build();). Cada chamada app.Use...() adiciona um middleware. var app = builder.Build();
//--- Início da Configuração do Pipeline ---
// 1. Middleware de tratamento de exceções (deve vir primeiro) if (!app.Environment.IsDevelopment()) { app.UseExceptionHandler("/Home/Error"); app.UseHsts(); }
// 2. Redirecionamento para HTTPS app.UseHttpsRedirection();
// 3. Servir arquivos estáticos (CSS, JS, imagens da pasta wwwroot) app.UseStaticFiles();
// 4. Roteamento (decide qual endpoint executar) app.UseRouting();
// 5. Autenticação (identifica o usuário) app.UseAuthentication();
// 6. Autorização (verifica as permissões) app.UseAuthorization();
// 7. Mapeia os endpoints (Controllers/Razor Pages) app.MapControllerRoute( name: "default", pattern: "{controller=Home}/{action=Index}/{id?}"); app.MapRazorPages();
//--- Fim da Configuração do Pipeline --app.Run();
Middlewares Comuns
● UseExceptionHandler: Captura exceções não tratadas e exibe uma página de erro.
● UseStaticFiles: Permite que a aplicação sirva arquivos da pasta wwwroot (CSS, JS, imagens).
● UseRouting: Analisa a URL e seleciona o endpoint (Action ou Razor Page) que deve lidar com ela.
● UseAuthentication: Identifica o usuário (geralmente lendo um cookie).
● UseAuthorization: Verifica se o usuário identificado tem permissão para acessar o endpoint.
● Map...: O middleware terminal que de fato executa o endpoint.
Exercício: Crie um middleware customizado
Vamos criar um middleware simples que registra o tempo de execução de cada requisição.
1. Crie um novo projeto web vazio: dotnet new web -n AppMiddleware.
2. Crie uma pasta Middlewares e o arquivo RequestTimingMiddleware.cs: using System.Diagnostics;
public class RequestTimingMiddleware { private readonly RequestDelegate _next; private readonly ILogger<RequestTimingMiddleware> _logger;
public RequestTimingMiddleware(RequestDelegate next, ILogger<RequestTimingMiddleware> logger)
{ _next = next; _logger = logger; }
public async Task InvokeAsync(HttpContext context)
{ var stopwatch = Stopwatch.StartNew();
await _next(context); // Processa o resto do pipeline
stopwatch.Stop(); var elapsedMs = stopwatch.ElapsedMilliseconds;
_logger.LogInformation($"Requisição {context.Request.Method} {context.Request.Path} levou {elapsedMs}ms"); } }
3. Modifique seu Program.cs para registrar e usar este middleware. Coloque-o no início do pipeline.
var builder = WebApplication.CreateBuilder(args); var app = builder.Build();
// Adiciona nosso middleware customizado ao pipeline
app.UseMiddleware<RequestTimingMiddleware>();
app.MapGet("/", () => "Hello World!"); app.Run();
4. Execute a aplicação: dotnet run.
5. Acesse a URL http://localhost:xxxx no seu navegador algumas vezes.
6. Observe o console onde a aplicação está rodando. Você verá as mensagens de log com o tempo de execução.
Capítulo 11: Configuração e Gerenciamento de Segredos
Usando o arquivo appsettings.json
O ASP.NET Core usa um sistema de configuração flexível. A fonte mais comum é o arquivo appsettings.json. Ele permite armazenar configurações, como strings de conexão, chaves de API, etc.
{ "Logging": { "LogLevel": { "Default": "Information" }
},
"AllowedHosts": "*", "ConnectionStrings": { "DefaultConnection": "Server=...;Database=...;" },
"MyCustomSettings": { "ApiKey": "12345-ABCDE", "RetryAttempts": 3 } }
Configurações específicas por ambiente
É comum ter configurações diferentes para Desenvolvimento (Development) e Produção (Production). O ASP.NET Core suporta isso nativamente com arquivos como appsettings.Development.json.
Quando a aplicação inicia, ela carrega o appsettings.json e, em seguida, carrega o arquivo específico do ambiente (se existir), sobrescrevendo as chaves.
A ferramenta Secret Manager (Gerenciador de Segredos)
Atenção: Nunca armazene informações sensíveis (senhas, chaves de API reais) no appsettings.json. Este arquivo é comumente enviado para o controle de versão (Git). Para o ambiente de desenvolvimento, use a ferramenta Secret Manager. Ela armazena os segredos em um arquivo JSON seguro no seu perfil de usuário, fora da pasta do projeto.
1. Inicialize o Secret Manager (execute na pasta do projeto): dotnet user-secrets init
2. Defina um segredo: dotnet user-secrets set "MyCustomSettings:ApiKey" "MINHA_CHAVE_SECRETA_REAL"
Em produção, os segredos devem ser gerenciados por provedores seguros, como Azure Key Vault ou Variáveis de Ambiente.
Lendo configurações com a interface IConfiguration
O resultado de todas as fontes de configuração (JSONs, Secret Manager, etc.) é agregado na interface IConfiguration, que é injetada automaticamente via DI. public class HomeController : Controller { private readonly IConfiguration _configuration; public HomeController(IConfiguration configuration) { _configuration = configuration; } public IActionResult Index() { // Lendo uma seção aninhada var apiKey = _configuration; // Lendo uma string de conexão var connectionString = _configuration.GetConnectionString("DefaultConnection");
ViewBag.ApiKey = apiKey; return View(); } }
Exercício: Adicione uma chave de configuração e leia-a
1. Use um projeto MVC.
2. Abra o appsettings.json e adicione uma nova seção: "AppInfo": { "AppName": "Minha Aplicação Incrível", "Version": "1.0.0" }
3. Abra o HomeController.cs. Injete IConfiguration no construtor.
4. Na action Index, leia os valores e passe-os para a View: ViewBag.AppName = _configuration["AppInfo:AppName"]; ViewBag.Version = _configuration["AppInfo:Version"];
5. Em Views/Home/Index.cshtml, exiba os valores: <h1 class="display-4">Bem-vindo ao @ViewBag.AppName</h1>
<p>Versão: @ViewBag.Version</p>
6. Execute a aplicação. Você deverá ver o nome e a versão lidos do arquivo.
Capítulo 12: Projeto Final: Criando um Blog Simples
Neste capítulo, vamos unir tudo o que aprendemos para construir uma aplicação web funcional: um blog simples. Recursos que utilizaremos:
● ASP.NET Core MVC
● Entity Framework Core com SQLite
● ASP.NET Core Identity para autenticação
● Injeção de Dependência
● Layouts, Views, Validação e Tag Helpers
Passo 1: Configuração do Projeto
1. Crie um novo projeto MVC com autenticação individual: dotnet new mvc -n SimpleBlog -auth Individual
2. Entre na pasta SimpleBlog. Adicione os pacotes do EF Core para SQLite: dotnet add package Microsoft.EntityFrameworkCore.Sqlite dotnet add package Microsoft.EntityFrameworkCore.Design
3. Abra appsettings.json e modifique a string de conexão DefaultConnection para usar SQLite: "DefaultConnection": "DataSource=blog.db"
4. Abra Program.cs e troque .UseSqlServer(...) por .UseSqlite(...) na configuração do ApplicationDbContext.
5. Execute a migração para criar o banco de dados e as tabelas do Identity: dotnet ef database update
Passo 2: Criando o Model do Post
Crie uma pasta Models e adicione o arquivo Post.cs. using System.ComponentModel.DataAnnotations; using Microsoft.AspNetCore.Identity; namespace SimpleBlog.Models { public class Post {
public int Id { get; set; }
public string Titulo { get; set; }
public string Conteudo { get; set; }
public DateTime DataPublicacao { get; set; } = DateTime.UtcNow;
// Chave estrangeira para o usuário que criou o post public string AutorId { get; set; } public virtual IdentityUser Autor { get; set; } } }
Passo 3: Atualizando o DbContext e Criando a Migração
Abra o arquivo Data/ApplicationDbContext.cs e adicione um DbSet para os Posts. using Microsoft.AspNetCore.Identity.EntityFrameworkCore; using Microsoft.EntityFrameworkCore; using SimpleBlog.Models; // Adicione este using
public class ApplicationDbContext : IdentityDbContext { // Adicione esta linha public DbSet<Post> Posts { get; set; }
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options) : base(options) { } }
Agora, crie uma nova migração e aplique-a: dotnet ef migrations add AddPostModel dotnet ef database update
Passo 4: Criando o Controller de Posts
Crie o arquivo Controllers/PostsController.cs. Este controller usará DI para obter o DbContext e o UserManager (para saber quem é o usuário logado). using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; using SimpleBlog.Data; using SimpleBlog.Models; using System.Threading.Tasks;
[Authorize] // Exige login para tudo, exceto onde marcado com [AllowAnonymous] public class PostsController : Controller { private readonly ApplicationDbContext _context; private readonly UserManager<IdentityUser> _userManager;
public PostsController(ApplicationDbContext context, UserManager<IdentityUser> userManager) { _context = context; _userManager = userManager; }
// GET: /Posts - Lista de todos os posts (público) [AllowAnonymous]
public async Task<IActionResult> Index() { var posts = await _context.Posts .Include(p => p.Autor) // Inclui dados do autor .OrderByDescending(p => p.DataPublicacao) .ToListAsync(); return View(posts); }
// GET: /Posts/Details/5 - Detalhes de um post (público) [AllowAnonymous]
public async Task<IActionResult> Details(int? id) { if (id == null) return NotFound(); var post = await _context.Posts .Include(p => p.Autor)
.FirstOrDefaultAsync(m => m.Id == id); if (post == null) return NotFound(); return View(post); }
// GET: /Posts/Create public IActionResult Create() { return View(); }
// POST: /Posts/Create [HttpPost]
public async Task<IActionResult> Create( Post post) { if (ModelState.IsValid) { post.AutorId = _userManager.GetUserId(User); // Associa o post ao usuário logado _context.Add(post); await _context.SaveChangesAsync(); return RedirectToAction(nameof(Index)); }
return View(post); }
// (Opcional: Adicione aqui as actions para Edit e Delete) }
Passo 5: Criando as Views para Posts
Crie uma pasta Views/Posts e adicione os arquivos:
● Index.cshtml (Listagem de Posts)
@model IEnumerable<SimpleBlog.Models.Post> <h1>Últimos Posts</h1> <p><a asp-action="Create">Criar Novo Post</a></p>
@foreach (var item in Model) { <article class="mb-4"> <h2><a asp-action="Details" asp-routeid="@item.Id">@item.Titulo</a></h2> <small>Publicado em
@item.DataPublicacao.ToShortDateString() por @item.Autor.UserName</small> <p class="mt-2">@(item.Conteudo.Length > 200? item.Conteudo.Substring(0, 200) + "..." : item.Conteudo)</p> </article> <hr /> }
● Details.cshtml (Visualização de um Post)
@model SimpleBlog.Models.Post <h1>@Model.Titulo</h1> <small>Publicado em @Model.DataPublicacao.ToLongDateString() por @Model.Autor.UserName</small> <hr /> <div class="mt-3"> @Html.Raw(Model.Conteudo.Replace("\n", "<br />")) </div> <hr /> <a asp-action="Index">Voltar para a Lista</a>
● Create.cshtml (Formulário de Criação)
@model SimpleBlog.Models.Post <h1>Novo Post</h1> <form asp-action="Create"> <div asp-validation-summary="ModelOnly" class="textdanger"></div> <div class="form-group mb-3"> <label asp-for="Titulo" class="control-label"></label> <input asp-for="Titulo" class="form-control" />
<span asp-validation-for="Titulo" class="text-danger"></span> </div>
<div class="form-group mb-3">
<label asp-for="Conteudo" class="control-label"></label> <textarea asp-for="Conteudo" class="form-control" rows="10"></textarea>
<span asp-validation-for="Conteudo" class="textdanger"></span> </div>
<div class="form-group">
<input type="submit" value="Publicar" class="btn btnprimary" /> </div> </form>
Passo 6: Ajustes Finais e Execução
1. Mude a página inicial da aplicação para ser a lista de posts. Em Program.cs, altere o MapControllerRoute padrão: app.MapControllerRoute( name: "default", pattern: "{controller=Posts}/{action=Index}/{id?}"); // Mude 'Home' para 'Posts'
2. Execute a aplicação! Você tem um blog funcional. Você pode se registrar, fazer login e criar posts.
Glossário
● ASP.NET Core: Framework de código aberto e multiplataforma para a construção de aplicações web modernas com.NET.
● DI (Injeção de Dependência): Um padrão de projeto onde um objeto recebe suas dependências de uma fonte externa (o container de DI) em vez de criá-las.
● EF Core (Entity Framework Core): O ORM (Object-Relational Mapper) oficial da Microsoft para.NET, que permite trabalhar com bancos de dados usando objetos C#.
● Kestrel: O servidor web multiplataforma, de código aberto e padrão para ASP.NET Core. É extremamente rápido e leve.
● Middleware: Componentes de software montados em um pipeline para lidar com requisições e respostas HTTP.
● Model Binding: O processo que pega dados de uma requisição HTTP (formulários, rotas) e os converte em parâmetros de métodos de action.
● MVC (Model-View-Controller): Padrão de projeto que separa uma aplicação em Modelo (dados), Visão (UI) e Controlador (lógica de requisição).
● NuGet: O gerenciador de pacotes para a plataforma.NET, usado para instalar bibliotecas de terceiros.
● ORM (Object-Relational Mapper): Técnica que mapeia classes de um programa para tabelas de um banco de dados.
● Razor: A sintaxe de marcação usada pelo ASP.NET Core para incorporar código C# em
páginas web (.cshtml).
● Razor Pages: Um modelo de programação focado em páginas, alternativo ao MVC, onde a lógica e a UI de uma página são mantidas juntas.
● Scaffolding: Processo de geração de código que cria arquivos básicos (controllers, views, páginas do Identity) com base nos modelos de dados.
● Tag Helpers: Atributos especiais do Razor que permitem que código do lado do servidor gere HTML de forma limpa (ex: <a asp-action="Index">).
Sua Jornada Continua
Parabéns por chegar ao final deste guia! Você percorreu um longo caminho, desde os conceitos mais básicos do ecossistema.NET até a construção de uma aplicação web completa, passando por tópicos avançados como injeção de dependência, segurança e acesso a dados. O conhecimento que você adquiriu aqui é uma base sólida para construir qualquer tipo de aplicação web moderna com ASP.NET Core. O mundo do desenvolvimento de software está em constante evolução. A chave para o sucesso é a curiosidade e o aprendizado contínuo. Explore a documentação oficial da Microsoft, participe de comunidades online e, o mais importante, continue construindo. Cada projeto é uma nova oportunidade de aprender e aprimorar suas habilidades.
Desejamos a você todo o sucesso em seus futuros projetos!