Parte 4, adicionar um modelo a um aplicativo ASP.NET Core MVC
Observação
Esta não é a versão mais recente deste artigo. Para a versão atual, consulte a versão .NET 9 deste artigo.
Advertência
Esta versão do ASP.NET Core não é mais suportada. Para obter mais informações, consulte a Política de suporte do .NET e .NET Core. Para a versão atual, consulte a versão .NET 9 deste artigo.
Importante
Estas informações referem-se a um produto de pré-lançamento que pode ser substancialmente modificado antes de ser lançado comercialmente. A Microsoft não oferece garantias, expressas ou implícitas, em relação às informações fornecidas aqui.
Para a versão atual, consulte a versão .NET 9 deste artigo.
Por Rick Anderson e Jon P Smith.
Neste tutorial, as classes são adicionadas para gerenciar filmes em um banco de dados. Estas classes são a parte "Model" da aplicação MVC.
Essas classes de modelo são usadas com Entity Framework Core (EF Core) para trabalhar com um banco de dados. EF Core é uma estrutura de mapeamento objeto-relacional (ORM) 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 qualquer dependência de EF Core. Eles apenas definem as propriedades dos dados a serem armazenados no banco de dados.
Neste tutorial, as classes de modelo são criadas primeiro e EF Core cria o banco de dados.
Adicionar uma classe de modelo de dados
- Visual Studio
- de código do Visual Studio
Clique com o botão direito do rato na pasta Modelos>Adicionar>Classe. Nomeie o arquivo Movie.cs
.
Atualize o arquivo Models/Movie.cs
com o seguinte código:
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 atributo DataType em ReleaseDate
especifica o tipo de dados (Date
). Com este atributo:
- O usuário não é obrigado a inserir informações de hora no campo de data.
- Apenas a data é exibida, não as informações de hora.
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, consulte Tipos de referência anuláveis.
Adicionar pacotes NuGet
- Visual Studio
- de código do Visual Studio
O Visual Studio instala automaticamente os pacotes necessários.
Construa o projeto como uma verificação de erros do compilador.
Páginas de filmes em andaimes
Use a ferramenta de scaffolding para produzir páginas Create
, Read
, Update
e Delete
(CRUD) para o modelo de filme.
- Visual Studio
- de código do Visual Studio
No Explorador de Soluções , clique com o botão direito na pasta Controladores e selecione Adicionar > Novo Item Estruturado.
acima
Na caixa de diálogo Adicionar Novo Item Andaime:
- No painel esquerdo, selecione Installed>Common>MVC.
- Selecione controlador MVC com exibições, usando o Entity Framework.
- Selecione Adicionar.
Conclua o Adicionar Controlador MVC com modos de exibição, usando a caixa de diálogo do Entity Framework:
- Na lista suspensa da classe Model , selecione Filme (MvcMovie.Models).
- Na linha da classe de contexto de dados, selecione o sinal de + (mais).
- Na caixa de diálogo Adicionar Contexto de Dados , o nome da classe MvcMovie.Data.MvcMovieContext é gerado.
- Selecione Adicionar.
- Na lista suspensa Provedor de banco de dados, selecione SQL Server.
- Visualizações e nome do controlador: Mantenha o padrão.
- Selecione Adicionar.
Se receber uma mensagem de erro, selecione Adicionar uma segunda vez para tentar novamente.
Andaimes adiciona os seguintes pacotes:
Microsoft.EntityFrameworkCore.SqlServer
Microsoft.EntityFrameworkCore.Tools
Microsoft.VisualStudio.Web.CodeGeneration.Design
O andaime cria o seguinte:
- Um controlador de filmes:
Controllers/MoviesController.cs
-
Razor visualizar arquivos para Criar, Excluir, Detalhes, Editare Índice páginas:
Views/Movies/*.cshtml
- Uma classe de contexto de banco de dados:
Data/MvcMovieContext.cs
O andaime atualiza o seguinte:
- Insere as referências de pacote necessárias no arquivo de projeto
MvcMovie.csproj
. - Registra o contexto do banco de dados no arquivo
Program.cs
. - Adiciona uma cadeia de conexão de banco de dados ao arquivo
appsettings.json
.
A criação automática desses arquivos e a atualização dos mesmos é conhecida como scaffolding.
As páginas com andaimes ainda não podem ser usadas porque o banco de dados não existe. Executar a aplicação e selecionar o link Movie App resulta numa mensagem de erro Não é possível abrir o banco de dados ou nenhuma tabela: Movie.
Crie o aplicativo para verificar se não há erros.
Migração inicial
Utilize a funcionalidade EF CoreMigrações para criar a base de dados. de Migrações é um conjunto de ferramentas que criam e atualizam um banco de dados para corresponder ao modelo de dados.
- Visual Studio
- de código do Visual Studio
No menu Ferramentas, selecione Gestor de Pacotes NuGet>Consola do Gestor de Pacotes.
No Console do Gerenciador de Pacotes (PMC), digite o seguinte comando:
Add-Migration InitialCreate
-
Add-Migration InitialCreate
: Gera um arquivo de migraçãoMigrations/{timestamp}_InitialCreate.cs
. O argumentoInitialCreate
é o nome da migração. Qualquer nome pode ser usado, mas, por convenção, é selecionado um nome que descreve a migração. Como esta é a primeira migração, a classe gerada contém código para criar o esquema de banco de dados. O esquema de banco de dados é baseado no modelo especificado na classeMvcMovieContext
.
O seguinte aviso é exibido, que é abordado em uma etapa posterior:
Não foi especificado um tipo de armazenamento para a propriedade decimal 'Preço' no tipo de entidade 'Filme'. Isso fará com que os valores sejam truncados silenciosamente se não se ajustarem à precisão e escala padrão. Especifique explicitamente o tipo de coluna do servidor SQL que pode acomodar todos os valores em 'OnModelCreating' usando 'HasColumnType', especifique precisão e escala usando 'HasPrecision' ou configure um conversor de valores usando 'HasConversion'.
No PMC, digite o seguinte comando:
Update-Database
-
Update-Database
: Atualiza o banco de dados para a migração mais recente, que o comando anterior criou. Este comando executa o métodoUp
no arquivoMigrations/{time-stamp}_InitialCreate.cs
, que cria o banco de dados.
Para obter mais informações sobre as ferramentas PMC para EF Core, consulte a Referência de Ferramentas EF Core - PMC no Visual Studio.
Testar a aplicação
- Visual Studio
- de código do Visual Studio
Execute a aplicação e selecione o link do Movie App.
Se obtiveres uma exceção semelhante à seguinte, talvez tenhas perdido o comando Update-Database
na etapa de migrações :
SqlException: Cannot open database "MvcMovieContext-1" requested by the login. The login failed.
Observação
Talvez não seja possível inserir vírgulas decimais no campo Price
. Para oferecer suporte a de validação do jQuery para localidades diferentes do inglês que usam uma vírgula (",") para um ponto decimal e para formatos de data não US-English, o aplicativo deve ser globalizado. Para obter instruções sobre globalização, consulte esta questão do GitHub.
Examine a classe de contexto e o registro do banco de dados gerado
Com EF Core, o acesso aos dados é realizado usando um modelo. Um modelo é composto 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 do banco de dados é derivado de Microsoft.EntityFrameworkCore.DbContext e especifica as entidades a serem incluídas no modelo de dados.
Scaffolding cria a classe de contexto de banco de dados Data/MvcMovieContext.cs
:
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; } = default!;
}
}
O código anterior cria uma propriedade DbSet<Movie> que representa os filmes no banco de dados.
Injeção de dependência
ASP.NET Core é construído com injeção de dependência (DI). Serviços, como o contexto do banco de dados, são registrados com DI em Program.cs
. Esses serviços são fornecidos a componentes que os exigem por meio de parâmetros do construtor.
No arquivo Controllers/MoviesController.cs
, o construtor usa Dependency Injection para injetar o contexto de banco de dados MvcMovieContext
no controlador. O contexto do banco de dados é usado em cada um dos métodos CRUD no controlador.
Andaime gerou o seguinte código destacado em Program.cs
:
- Visual Studio
- de código do Visual Studio
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddDbContext<MvcMovieContext>(options =>
options.UseSqlServer(builder.Configuration.GetConnectionString("MvcMovieContext") ?? throw new InvalidOperationException("Connection string 'MvcMovieContext' not found.")));
O sistema de configuração ASP.NET Core lê a cadeia de conexão do banco de dados "MvcMovieContext".
Examinar a string de conexão de base de dados gerada
Scaffolding adicionou uma cadeia de conexão ao arquivo appsettings.json
:
- Visual Studio
- de código do Visual Studio
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*",
"ConnectionStrings": {
"MvcMovieContext": "Server=(localdb)\\mssqllocaldb;Database=MvcMovieContext-4ebefa10-de29-4dea-b2ad-8a8dc6bcf374;Trusted_Connection=True;MultipleActiveResultSets=true"
}
}
Para o desenvolvimento local, o sistema de configuração ASP.NET Core lê a chave ConnectionString
do arquivo appsettings.json
.
A classe InitialCreate
Examine o arquivo de migração Migrations/{timestamp}_InitialCreate.cs
:
using System;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace MvcMovie.Migrations
{
/// <inheritdoc />
public partial class InitialCreate : Migration
{
/// <inheritdoc />
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);
});
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "Movie");
}
}
}
No código anterior:
-
InitialCreate.Up
cria a tabela Filme e configuraId
como a chave primária. -
InitialCreate.Down
reverte as alterações de esquema feitas pela migração deUp
.
Injeção de dependência no controlador
Abra o ficheiro Controllers/MoviesController.cs
e examine o construtor:
public class MoviesController : Controller
{
private readonly MvcMovieContext _context;
public MoviesController(MvcMovieContext context)
{
_context = context;
}
O construtor usa Dependency Injection para injetar o contexto do banco de dados (MvcMovieContext
) no controlador. O contexto do banco de dados é usado em cada um dos métodos CRUD no controlador.
Teste a página Criar. Insira e envie dados.
Teste as páginas Editar, Detalhese Eliminar.
Modelos fortemente tipificados e a diretiva @model
No início deste 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 e tardia de passar informações para uma exibição.
O MVC fornece a capacidade de passar objetos de modelo fortemente tipados para uma exibição. Esta abordagem fortemente tipada permite a verificação de código em tempo de compilação. O mecanismo de andaime passou por um modelo fortemente tipado na classe MoviesController
e visualizações.
Examine o método Details
gerado no arquivo Controllers/MoviesController.cs
:
// 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 que aponta para o controlador
movies
, o primeiro segmento de URL. - A ação para
details
, o segundo segmento de URL. - O
id
a 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 parâmetro id
é definido como um tipo anulável (int?
) nos casos em que o valor id
não é fornecido.
Um de expressão lambda é passado para o método FirstOrDefaultAsync para selecionar entidades de filme que correspondam aos dados de rota ou ao valor da cadeia de caracteres de consulta.
var movie = await _context.Movie
.FirstOrDefaultAsync(m => m.Id == id);
Se um filme for encontrado, uma instância do modelo Movie
será passada para a visualização Details
:
return View(movie);
Examine o conteúdo do arquivo Views/Movies/Details.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 visualização especifica o tipo de objeto que a visualização espera. Quando o controlador de filme foi criado, a seguinte instrução @model
foi incluída:
@model MvcMovie.Models.Movie
Esta diretiva @model
permite o acesso ao filme que o controlador passou para a visualização. O objeto Model
é fortemente tipado. Por exemplo, na visualização Details.cshtml
, o código passa cada campo de filme para os auxiliares de HTML DisplayNameFor
e DisplayFor
usando o objeto Model
fortemente tipado. Os métodos e exibições Create
e Edit
também passam por um objeto de modelo Movie
.
Examine a visualização Index.cshtml
e o método Index
no controlador Movies. Observe como o código cria um objeto List
quando chama o método View
. O código passa essa lista de Movies
do método de ação Index
para a exibição:
// GET: Movies
public async Task<IActionResult> Index()
{
return View(await _context.Movie.ToListAsync());
}
O código retorna detalhes do problema se a propriedade Movie
do contexto de dados for nulo.
Quando o controlador de filmes foi criado, o andaime incluía a seguinte instrução @model
na parte superior do arquivo Index.cshtml
:
@model IEnumerable<MvcMovie.Models.Movie>
A diretiva @model
permite o acesso à lista de filmes que o controlador passou para a visualização usando um objeto Model
fortemente digitado. Por exemplo, na visualização Index.cshtml
, o código percorre os filmes com uma instrução foreach
sobre o objeto Model
fortemente tipado:
@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 objeto Model
é fortemente tipado como um objeto IEnumerable<Movie>
, cada item no loop é tipado como Movie
. Entre outros benefícios, o compilador valida os tipos usados no código.
Recursos adicionais
Neste tutorial, as classes são adicionadas para gerenciar filmes em um banco de dados. Estas classes são a parte "Model" da aplicação MVC.
Essas classes de modelo são usadas com Entity Framework Core (EF Core) para trabalhar com um banco de dados. EF Core é uma estrutura de mapeamento objeto-relacional (ORM) 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 qualquer dependência de EF Core. Eles apenas definem as propriedades dos dados a serem armazenados no banco de dados.
Neste tutorial, as classes de modelo são criadas primeiro e EF Core cria o banco de dados.
Adicionar uma classe de modelo de dados
- Visual Studio
- de código do Visual Studio
- Visual Studio para Mac
Clique com o botão direito do rato na pasta Modelos>Adicionar>Classe. Nomeie o arquivo Movie.cs
.
Atualize o arquivo Models/Movie.cs
com o seguinte código:
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 atributo DataType em ReleaseDate
especifica o tipo de dados (Date
). Com este atributo:
- O usuário não é obrigado a inserir informações de hora no campo de data.
- Apenas a data é exibida, não as informações de hora.
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, consulte Tipos de referência anuláveis.
Adicionar pacotes NuGet
- Visual Studio
- de código do Visual Studio
- Visual Studio para Mac
O Visual Studio instala automaticamente os pacotes necessários.
Construa o projeto como uma verificação de erros do compilador.
Páginas de filmes em andaimes
Use a ferramenta de scaffolding para produzir as páginas Create
, Read
, Update
e Delete
(CRUD) para o modelo de filme.
- Visual Studio
- de código do Visual Studio
- Visual Studio para Mac
No Explorador de Soluções, clique com o botão direito do rato na pasta Controladores e selecione Adicionar Novo Item Estruturado >.
acima
Na caixa de diálogo Adicionar Novo Item Andaime:
- No painel esquerdo, selecione Instalado>Comum>MVC.
- Selecione controlador MVC com vistas, usando Entity Framework.
- Selecione Adicionar.
Conclua o Adicionar Controlador MVC com modos de exibição, usando a caixa de diálogo do Entity Framework:
- Na lista suspensa classe Model, selecione Filme (MvcMovie.Models).
- Na linha da classe de contexto de Dados, selecione o sinal + (mais).
- Na caixa de diálogo Adicionar Contexto de Dados, é gerado o nome da classe MvcMovie.Data.MvcMovieContext.
- Selecione Adicionar.
- Na lista suspensa Provedor de banco de dados, selecione SQL Server.
- Visualizações e Nome do Controlador: Mantenha como predefinido.
- Selecione Adicionar.
Se receber uma mensagem de erro, selecione Adicionar uma segunda vez para tentar novamente.
Andaimes adiciona os seguintes pacotes:
Microsoft.EntityFrameworkCore.SqlServer
Microsoft.EntityFrameworkCore.Tools
Microsoft.VisualStudio.Web.CodeGeneration.Design
O andaime cria o seguinte:
- Um controlador de filmes:
Controllers/MoviesController.cs
-
Razor visualizar arquivos para Criar, Eliminar, Detalhes, Editare Índice de páginas:
Views/Movies/*.cshtml
- Uma classe de contexto de banco de dados:
Data/MvcMovieContext.cs
O andaime atualiza o seguinte:
- Insere as referências de pacote necessárias no arquivo de projeto
MvcMovie.csproj
. - Registra o contexto do banco de dados no arquivo
Program.cs
. - Adiciona uma cadeia de conexão de banco de dados ao arquivo
appsettings.json
.
A criação automática desses arquivos e atualizações de arquivos é conhecida como scaffolding.
As páginas com andaimes ainda não podem ser usadas porque o banco de dados não existe. Executar o aplicativo e selecionar o link do Movie App resulta numa mensagem de erro Não é possível abrir o banco de dados ou não existe tal tabela: Movie.
Crie o aplicativo para verificar se não há erros.
Migração inicial
Use o recurso EF CoreMigrações para criar a base de dados. Migrações é um conjunto de ferramentas que criam e atualizam uma base de dados para corresponder ao modelo de dados.
No menu Ferramentas, selecione Gestor de Pacotes NuGet>Consola do Gestor de Pacotes.
No Console do Gerenciador de Pacotes (PMC), digite os seguintes comandos:
Add-Migration InitialCreate
Update-Database
Add-Migration InitialCreate
: Gera um arquivo de migraçãoMigrations/{timestamp}_InitialCreate.cs
. O argumentoInitialCreate
corresponde ao nome da migração. Qualquer nome pode ser usado, mas, por convenção, é selecionado um nome que descreve a migração. Como esta é a primeira migração, a classe gerada contém código para criar o esquema de banco de dados. O esquema de banco de dados é baseado no modelo especificado na classeMvcMovieContext
.Update-Database
: Atualiza o banco de dados para a migração mais recente, que o comando anterior criou. Este comando executa o métodoUp
no arquivoMigrations/{time-stamp}_InitialCreate.cs
, que cria o banco de dados.
O comando Update-Database
gera o seguinte aviso:
Nenhum tipo de loja foi especificado para a propriedade decimal 'Price' no tipo de entidade 'Movie'. Isso fará com que os valores sejam truncados silenciosamente se não se ajustarem à precisão e escala padrão. Especifique explicitamente o tipo de coluna do servidor SQL que pode acomodar todos os valores em 'OnModelCreating' usando 'HasColumnType', especifique precisão e escala usando 'HasPrecision' ou configure um conversor de valores usando 'HasConversion'.
Ignore o aviso anterior, ele é corrigido em um tutorial posterior.
Para obter mais informações sobre as ferramentas PMC para EF Core, consulte a referência de ferramentas EF Core - PMC no Visual Studio.
Testar a aplicação
Execute a aplicação e selecione o link Movie App.
Se obtiveres uma exceção semelhante à seguinte, talvez tenhas perdido o comando Update-Database
na etapa de migrações :
SqlException: Cannot open database "MvcMovieContext-1" requested by the login. The login failed.
Observação
Talvez não seja possível inserir vírgulas decimais no campo Price
. Para oferecer suporte à validação do jQuery para locais que não sejam de língua inglesa e que usem a vírgula (",") como ponto decimal, assim como para formatos de data que não sejam US-English, é necessário que o aplicativo seja internacionalizado. Para obter instruções sobre globalização, consulte este issue do GitHub .
Examine a classe de contexto e o registro do banco de dados gerado
Com EF Core, o acesso aos dados é realizado usando um modelo. Um modelo é composto 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 do banco de dados é derivado de Microsoft.EntityFrameworkCore.DbContext e especifica as entidades a serem incluídas no modelo de dados.
Scaffolding cria a classe de contexto de banco de dados Data/MvcMovieContext.cs
:
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
ASP.NET Core é construído com injeção de dependência (DI). Serviços, como o contexto do banco de dados, são registrados com DI em Program.cs
. Esses serviços são fornecidos a componentes que os exigem por meio de parâmetros do construtor.
No arquivo Controllers/MoviesController.cs
, o construtor usa Dependency Injection para injetar o contexto de banco de dados MvcMovieContext
no controlador. O contexto do banco de dados é usado em cada um dos métodos CRUD no controlador.
Scaffolding gerou o seguinte código realçado em Program.cs
:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddDbContext<MvcMovieContext>(options =>
options.UseSqlServer(builder.Configuration.GetConnectionString("MvcMovieContext")));
O do sistema de configuração ASP.NET Core lê a cadeia de conexão do banco de dados "MvcMovieContext".
Analisar a cadeia de conexão da base de dados gerada
Scaffolding adicionou uma cadeia de conexão ao arquivo appsettings.json
:
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*",
"ConnectionStrings": {
"MvcMovieContext": "Data Source=MvcMovieContext-ea7a4069-f366-4742-bd1c-3f753a804ce1.db"
}
}
Para o desenvolvimento local, o sistema de configuração ASP.NET Core lê a chave ConnectionString
do arquivo appsettings.json
.
A classe InitialCreate
Examine o arquivo de migração Migrations/{timestamp}_InitialCreate.cs
:
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 Filme e configuraId
como a chave primária. -
InitialCreate.Down
reverte as alterações de esquema feitas pela migração deUp
.
Injeção de dependência no controlador
Abra o arquivo Controllers/MoviesController.cs
e examine o construtor:
public class MoviesController : Controller
{
private readonly MvcMovieContext _context;
public MoviesController(MvcMovieContext context)
{
_context = context;
}
O construtor usa Dependency Injection para injetar o contexto do banco de dados (MvcMovieContext
) no controlador. O contexto do banco de dados é usado em cada um dos métodos CRUD dentro do controlador.
Teste a página Criar. Insira e envie dados.
Teste as páginas Editar, Detalhese Eliminar.
Modelos fortemente tipificados e a diretiva @model
No início deste 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 e tardia de passar informações para uma exibição.
O MVC fornece a capacidade de passar objetos de modelo fortemente tipados para uma exibição. Essa abordagem fortemente tipada permite a verificação de código durante a compilação. O mecanismo de andaime passou por um modelo fortemente tipado na classe MoviesController
e visualizações.
Examine o método Details
gerado no arquivo Controllers/MoviesController.cs
:
// 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, o https://localhost:5001/movies/details/1
define:
- O controlador para o
movies
, o primeiro segmento de URL. - A ação para
details
, o segundo segmento de URL. - Do
id
até 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 parâmetro id
é definido como um tipo anulável (int?
) nos casos em que o valor id
não é fornecido.
Um de expressão lambda é passado para o método FirstOrDefaultAsync para selecionar entidades de filme que correspondam aos dados de rota ou ao valor da cadeia de caracteres de consulta.
var movie = await _context.Movie
.FirstOrDefaultAsync(m => m.Id == id);
Se um filme for encontrado, uma instância do modelo Movie
será passada para a visualização Details
:
return View(movie);
Examine o conteúdo do arquivo Views/Movies/Details.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 vista especifica o tipo de objeto que a vista espera. Quando o controlador de filme foi criado, a seguinte instrução @model
foi incluída:
@model MvcMovie.Models.Movie
Esta diretiva @model
permite o acesso ao filme que o controlador passou para a vista. O objeto Model
é fortemente tipado. Por exemplo, na visualização Details.cshtml
, o código passa cada campo de filme para os HTML Helpers DisplayNameFor
e DisplayFor
com o objeto Model
fortemente tipado. Os métodos e exibições Create
e Edit
também passam por um objeto de modelo Movie
.
Examine a exibição Index.cshtml
e o método Index
no controlador de filmes. Observe como o código cria um objeto List
quando chama o método View
. O código passa essa lista de Movies
do método de ação Index
para a exibição:
// GET: Movies
public async Task<IActionResult> Index()
{
return View(await _context.Movie.ToListAsync());
}
O código retorna detalhes do problema se a propriedade Movie
do contexto de dados for null.
Quando o controlador de filmes foi criado, o scaffolding incluiu a seguinte instrução @model
na parte superior do arquivo Index.cshtml
:
@model IEnumerable<MvcMovie.Models.Movie>
A diretiva @model
permite o acesso à lista de filmes que o controlador passou para a visualização usando um objeto Model
fortemente digitado. Por exemplo, na visualização Index.cshtml
, o código percorre os filmes com uma instrução foreach
sobre o objeto Model
fortemente tipado:
@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 objeto Model
é fortemente tipado como um objeto IEnumerable<Movie>
, cada item no loop está tipado como Movie
. Entre outros benefícios, o compilador valida os tipos usados no código.
Recursos adicionais
Neste tutorial, as classes são adicionadas para gerenciar filmes em um banco de dados. Estas classes são a parte "Model" da aplicação MVC.
Essas classes de modelo são usadas com Entity Framework Core (EF Core) para trabalhar com um banco de dados. EF Core é uma estrutura de mapeamento objeto-relacional (ORM) 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 qualquer dependência de EF Core. Eles apenas definem as propriedades dos dados a serem armazenados no banco de dados.
Neste tutorial, as classes de modelo são criadas primeiro e EF Core cria o banco de dados.
Adicionar uma classe de modelo de dados
- Visual Studio
- de código do Visual Studio
- Visual Studio para Mac
Clique com o botão direito do rato na pasta Modelos>Adicionar>Classe. Nomeie o arquivo Movie.cs
.
Atualize o arquivo Models/Movie.cs
com o seguinte código:
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 atributo DataType em ReleaseDate
especifica o tipo de dados (Date
). Com este atributo:
- O usuário não é obrigado a inserir informações de hora no campo de data.
- Apenas a data é exibida, não as informações de hora.
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, consulte Tipos de referência anuláveis.
Adicionar pacotes NuGet
- Visual Studio
- de código do Visual Studio
- Visual Studio para Mac
O Visual Studio instala automaticamente os pacotes necessários.
Construa o projeto como uma verificação de erros do compilador.
Páginas de filmes em andaimes
Utilize a ferramenta de scaffolding para produzir páginas Create
, Read
, Update
e Delete
(CRUD) para o modelo de filme.
- Visual Studio
- de código do Visual Studio
- Visual Studio para Mac
No Explorador de Soluções , clicar com o botão direito na pasta Controladores e selecionar Adicionar > Novo Item com Estrutura de Suporte.
acima
Na caixa de diálogo Adicionar Novo Item Andaime:
- No painel esquerdo, selecione Instalado>Comum>MVC.
- Selecione controlador MVC com vistas, usando Entity Framework.
- Selecione Adicionar.
Conclua o Adicionar Controlador MVC com modos de exibição, usando a caixa de diálogo do Entity Framework:
- Na lista suspensa da classe Model, selecione Filme (MvcMovie.Models).
- Na linha da classe de contexto de Dados, selecione o sinal + (mais).
- Na caixa de diálogo Adicionar Contexto de Dados , o nome da classe MvcMovie.Data.MvcMovieContext é gerado.
- Selecione Adicionar.
- Na lista suspensa Provedor de banco de dados, selecione SQL Server.
- Visualizações e nome do controlador : Mantenha o padrão.
- Selecione Adicionar.
Se você receber uma mensagem de erro, selecione Adicionar segunda vez para tentar novamente.
Andaimes adiciona os seguintes pacotes:
Microsoft.EntityFrameworkCore.SqlServer
Microsoft.EntityFrameworkCore.Tools
Microsoft.VisualStudio.Web.CodeGeneration.Design
O andaime cria o seguinte:
- Um controlador de filmes:
Controllers/MoviesController.cs
-
Razor visualizar arquivos para Criar, Excluir, Detalhes, Editare Índice páginas:
Views/Movies/*.cshtml
- Uma classe de contexto de banco de dados:
Data/MvcMovieContext.cs
O andaime atualiza o seguinte:
- Insere as referências de pacote necessárias no arquivo de projeto
MvcMovie.csproj
. - Registra o contexto do banco de dados no arquivo
Program.cs
. - Adiciona uma cadeia de conexão de banco de dados ao arquivo
appsettings.json
.
A criação automática desses arquivos e atualizações de arquivos é conhecida como scaffolding.
As páginas com andaimes ainda não podem ser usadas porque o banco de dados não existe. Executar a aplicação e selecionar o link Movie App resulta numa mensagem de erro Não é possível abrir o banco de dados ou nenhuma tabela: Movie.
Crie o aplicativo para verificar se não há erros.
Migração inicial
Use a funcionalidade EF CoreMigrações para criar a base de dados. Migrações é um conjunto de ferramentas que cria e atualiza uma base de dados para corresponder ao modelo de dados.
No menu Ferramentas, selecione Gestor de Pacotes NuGet>Consola do Gestor de Pacotes .
No Console do Gerenciador de Pacotes (PMC), digite os seguintes comandos:
Add-Migration InitialCreate
Update-Database
Add-Migration InitialCreate
: Gera um arquivo de migraçãoMigrations/{timestamp}_InitialCreate.cs
. O argumentoInitialCreate
é o nome da migração. Qualquer nome pode ser usado, mas, por convenção, é selecionado um nome que descreve a migração. Como esta é a primeira migração, a classe gerada contém código para criar o esquema de banco de dados. O esquema de banco de dados é baseado no modelo especificado na classeMvcMovieContext
.Update-Database
: Atualiza o banco de dados para a migração mais recente, que o comando anterior criou. Este comando executa o métodoUp
no arquivoMigrations/{time-stamp}_InitialCreate.cs
, que cria o banco de dados.
O comando Update-Database
gera o seguinte aviso:
Nenhum tipo foi especificado para a coluna decimal 'Preço' no tipo de entidade 'Filme'. Isso fará com que os valores sejam truncados silenciosamente se não se ajustarem à precisão e escala padrão. Especifique explicitamente o tipo de coluna do servidor SQL que pode acomodar todos os valores usando 'HasColumnType()'.
Ignore o aviso anterior, ele é corrigido em um tutorial posterior.
Para obter mais informações sobre as ferramentas PMC para EF Core, consulte a referência de ferramentas EF Core - PMC no Visual Studio.
Testar a aplicação
Execute a aplicação e, em seguida, selecione o link Movie App.
Se obtiveres uma exceção semelhante à seguinte, talvez tenhas perdido o comando Update-Database
na etapa das migrações:
SqlException: Cannot open database "MvcMovieContext-1" requested by the login. The login failed.
Observação
Talvez não seja possível inserir vírgulas decimais no campo Price
. Para oferecer suporte a de validação do jQuery para localidades diferentes do inglês que usam uma vírgula (",") para um ponto decimal e para formatos de data não US-English, o aplicativo deve ser globalizado. Para obter instruções sobre globalização, consulte este tópico do GitHub .
Examine a classe de contexto e o registro do banco de dados gerado
Com EF Core, o acesso aos dados é realizado usando um modelo. Um modelo é composto 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 do banco de dados é derivado de Microsoft.EntityFrameworkCore.DbContext e especifica as entidades a serem incluídas no modelo de dados.
Scaffolding cria a classe de contexto de banco de dados Data/MvcMovieContext.cs
:
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
ASP.NET Core é construído com injeção de dependência (DI). Serviços, como o contexto do banco de dados, são registrados com DI em Program.cs
. Esses serviços são fornecidos a componentes que os exigem por meio de parâmetros do construtor.
No arquivo Controllers/MoviesController.cs
, o construtor usa Dependency Injection para injetar o contexto de banco de dados MvcMovieContext
no controlador. O contexto do banco de dados é usado em cada um dos métodos CRUD no controlador.
Andaime gerou o seguinte código destacado em Program.cs
:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddDbContext<MvcMovieContext>(options =>
options.UseSqlServer(builder.Configuration.GetConnectionString("MvcMovieContext")));
O sistema de configuração do ASP.NET Core lê a cadeia de conexão do banco de dados "MvcMovieContext".
Examinar a string de conexão de base de dados gerada
Scaffolding adicionou uma cadeia de conexão ao arquivo appsettings.json
:
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*",
"ConnectionStrings": {
"MvcMovieContext": "Data Source=MvcMovieContext-ea7a4069-f366-4742-bd1c-3f753a804ce1.db"
}
}
Para o desenvolvimento local, o sistema de configuração ASP.NET Core lê a chave ConnectionString
do arquivo appsettings.json
.
A classe InitialCreate
Examine o arquivo de migração Migrations/{timestamp}_InitialCreate.cs
:
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 Filme e configuraId
como a chave primária. -
InitialCreate.Down
reverte as alterações de esquema feitas pela migração deUp
.
Injeção de dependência no controlador
Abra o arquivo Controllers/MoviesController.cs
e examine o construtor:
public class MoviesController : Controller
{
private readonly MvcMovieContext _context;
public MoviesController(MvcMovieContext context)
{
_context = context;
}
O construtor usa Dependency Injection para injetar o contexto do banco de dados (MvcMovieContext
) no controlador. O contexto do banco de dados é usado em cada um dos métodos CRUD no controlador.
Teste a página Criar. Insira e envie dados.
Teste o Editar, Detalhese Excluir páginas.
Modelos fortemente tipificados e a diretiva @model
No início deste 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 e tardia de passar informações para uma exibição.
O MVC fornece a capacidade de passar objetos de modelo fortemente tipados para uma exibição. Essa abordagem fortemente tipada permite a verificação de código em tempo de compilação. O mecanismo de andaime passou por um modelo fortemente tipado na classe MoviesController
e visualizações.
Examine o método Details
gerado no arquivo Controllers/MoviesController.cs
:
// 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, o https://localhost:5001/movies/details/1
define:
- O controlador para o controlador
movies
, o primeiro segmento de URL. - A ação relativa a
details
, o segundo segmento de URL. - O
id
a 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 parâmetro id
é definido como um tipo anulável (int?
) nos casos em que o valor id
não é fornecido.
Um de expressão lambda é passado para o método FirstOrDefaultAsync para selecionar entidades de filme que correspondam aos dados de rota ou ao valor da cadeia de caracteres de consulta.
var movie = await _context.Movie
.FirstOrDefaultAsync(m => m.Id == id);
Se um filme for encontrado, uma instância do modelo Movie
será passada para a visualização Details
:
return View(movie);
Examine o conteúdo do arquivo Views/Movies/Details.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 ficheiro de visualização especifica o tipo de objeto que a vista espera. Quando o controlador de filme foi criado, a seguinte instrução @model
foi incluída:
@model MvcMovie.Models.Movie
Esta diretiva @model
permite o acesso ao filme que o controlador passou para a vista. O objeto Model
é fortemente tipado. Por exemplo, na vista Details.cshtml
, o código passa cada campo do filme para os auxiliares HTML DisplayNameFor
e DisplayFor
com o objeto Model
fortemente tipado. Os métodos e exibições Create
e Edit
também passam por um objeto de modelo Movie
.
Verifique a visualização Index.cshtml
e o método Index
no controlador de Filmes. Observe como o código cria um objeto List
quando chama o método View
. O código passa essa lista de Movies
do método de ação Index
para a exibição:
// GET: Movies
public async Task<IActionResult> Index()
{
return View(await _context.Movie.ToListAsync());
}
O código retorna detalhes do problema caso a propriedade Movie
do contexto de dados seja nulo.
Quando o controlador de filmes foi criado, o andaime incluía a seguinte instrução @model
na parte superior do arquivo Index.cshtml
:
@model IEnumerable<MvcMovie.Models.Movie>
A diretiva @model
permite o acesso à lista de filmes que o controlador passou para a visualização usando um objeto Model
fortemente digitado. Por exemplo, na visualização Index.cshtml
, o código percorre os filmes através de uma instrução foreach
aplicada ao objeto fortemente tipado Model
.
@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 objeto Model
é fortemente tipado como um objeto IEnumerable<Movie>
, cada item no loop é tipado como Movie
. Entre outros benefícios, o compilador valida os tipos usados no código.
Recursos adicionais
Neste tutorial, as classes são adicionadas para gerenciar filmes em um banco de dados. Estas classes são a parte "Model" da aplicação MVC.
Essas classes de modelo são usadas com Entity Framework Core (EF Core) para trabalhar com um banco de dados. EF Core é uma estrutura de mapeamento objeto-relacional (ORM) 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 qualquer dependência de EF Core. Eles apenas definem as propriedades dos dados a serem armazenados no banco de dados.
Neste tutorial, as classes de modelo são criadas primeiro e EF Core cria o banco de dados.
Adicionar uma classe de modelo de dados
- Visual Studio
- de código do Visual Studio
- Visual Studio para Mac
Clique com o botão direito do rato na pasta Modelos>Adicionar>Classe. Nomeie o arquivo Movie.cs
.
Atualize o arquivo Models/Movie.cs
com o seguinte código:
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 atributo DataType em ReleaseDate
especifica o tipo de dados (Date
). Com este atributo:
- O usuário não é obrigado a inserir informações de hora no campo de data.
- Apenas a data é exibida, não as informações de hora.
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, consulte Tipos de referência anuláveis.
Adicionar pacotes NuGet
- Visual Studio
- de código do Visual Studio
- Visual Studio para Mac
No menu Ferramentas, selecione Gestor de Pacotes NuGet>Consola do Gestor de Pacotes (PMC).
No PMC, execute o seguinte comando:
Install-Package Microsoft.EntityFrameworkCore.Design
Install-Package Microsoft.EntityFrameworkCore.SqlServer
Os comandos anteriores adicionam:
- O fornecedor EF Core do SQL Server. O pacote do provedor instala o pacote EF Core como uma dependência.
- Os utilitários utilizados automaticamente na instalação dos pacotes durante a etapa de estruturação serão abordados mais adiante no tutorial.
Construa o projeto como uma verificação de erros do compilador.
Páginas de filmes em andaimes
Utilize a ferramenta de scaffolding para gerar as páginas Create
, Read
, Update
e Delete
(CRUD) para o modelo de filme.
- Visual Studio
- de código do Visual Studio
- Visual Studio para Mac
No Explorador de Soluções, clique com o botão direito na pasta Controladores e selecione Adicionar > Novo Item com Estrutura.
acima
Na caixa de diálogo Adicionar de Andaime, selecione Controlador MVC com modos de exibição, usando o Entity Framework > Adicionar.
Conclua o Adicionar Controlador MVC com modos de exibição, usando a caixa de diálogo do Entity Framework:
- No menu pendente da classe Model, selecione Movie (MvcMovie.Models).
- Na linha classe de contexto Data, selecione o sinal de + (mais).
- Na caixa de diálogo Adicionar Contexto de Dados, o nome da classe MvcMovie.Data.MvcMovieContext é gerado.
- Selecione Adicionar.
- Visualizações e Nome do Controlador: Mantenha o padrão.
- Selecione Adicionar.
Se receber uma mensagem de erro, selecione Adicionar uma segunda vez para tentar novamente.
O andaime atualiza o seguinte:
- Insere as referências de pacote necessárias no arquivo de projeto
MvcMovie.csproj
. - Registra o contexto do banco de dados no arquivo
Program.cs
. - Adiciona uma cadeia de conexão de banco de dados ao arquivo
appsettings.json
.
O andaime cria o seguinte:
- Um controlador de filmes:
Controllers/MoviesController.cs
-
Razor visualizar arquivos para Criar, Excluir, Detalhes, Editare Índice páginas:
Views/Movies/*.cshtml
- Uma classe de contexto de banco de dados:
Data/MvcMovieContext.cs
A criação automática desses arquivos e as atualizações de arquivos são conhecidas como scaffolding.
As páginas com andaimes ainda não podem ser usadas porque o banco de dados não existe. Ao executar a aplicação e selecionar o link Movie App, resulta numa mensagem de erro Não é possível abrir o banco de dados ou não existe tal tabela: Movie.
Crie o aplicativo
Crie o aplicativo. O compilador gera vários avisos sobre como null
valores são tratados. Consulte este problema do GitHub e os tipos de referência anuláveis para obter mais informações.
Para eliminar os avisos de tipos de referência anuláveis, remova a seguinte linha do arquivo MvcMovie.csproj
:
<Nullable>enable</Nullable>
Esperamos corrigir esse problema na próxima versão.
Migração inicial
Use o recurso EF CoreMigrações para criar o banco de dados. de Migrações é um conjunto de ferramentas que criam e atualizam um banco de dados para corresponder ao modelo de dados.
No menu Ferramentas, selecione Gestor de Pacotes NuGet>Consola do Gestor de Pacotes .
No Console do Gerenciador de Pacotes (PMC), digite os seguintes comandos:
Add-Migration InitialCreate
Update-Database
Add-Migration InitialCreate
: Gera um arquivo de migraçãoMigrations/{timestamp}_InitialCreate.cs
. O argumentoInitialCreate
é o nome da migração. Qualquer nome pode ser usado, mas, por convenção, é selecionado um nome que descreve a migração. Como esta é a primeira migração, a classe gerada contém código para criar o esquema de banco de dados. O esquema de banco de dados é baseado no modelo especificado na classeMvcMovieContext
.Update-Database
: Atualiza o banco de dados para a migração mais recente, que o comando anterior criou. Este comando executa o métodoUp
no arquivoMigrations/{time-stamp}_InitialCreate.cs
, que cria o banco de dados.
O comando Update-Database
gera o seguinte aviso:
Nenhum tipo foi especificado para a coluna decimal 'Preço' no tipo de entidade 'Filme'. Isso fará com que os valores sejam truncados silenciosamente se não se ajustarem à precisão e escala padrão. Especifique explicitamente o tipo de coluna do servidor SQL que pode acomodar todos os valores usando 'HasColumnType()'.
Ignore o aviso anterior, ele é corrigido em um tutorial posterior.
Para obter mais informações sobre as ferramentas PMC para EF Core, consulte a referência das ferramentas EF Core - PMC no Visual Studio.
Testar a aplicação
Execute a aplicação e selecione o link Movie App.
Se tu obtiveres uma exceção semelhante à seguinte, talvez tenhas faltado a etapa de migrações :
SqlException: Cannot open database "MvcMovieContext-1" requested by the login. The login failed.
Observação
Talvez não seja possível inserir vírgulas decimais no campo Price
. Para oferecer suporte a de validação do jQuery para localidades diferentes do inglês que usam uma vírgula (",") para um ponto decimal e para formatos de data não US-English, o aplicativo deve ser globalizado. Para obter instruções sobre globalização, consulte esta questão do GitHub.
Examine a classe de contexto e o registro do banco de dados gerado
Com EF Core, o acesso aos dados é realizado usando um modelo. Um modelo é composto 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 do banco de dados é derivado de Microsoft.EntityFrameworkCore.DbContext e especifica as entidades a serem incluídas no modelo de dados.
Scaffolding cria a classe de contexto de banco de dados Data/MvcMovieContext.cs
:
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
ASP.NET Core foi criado com injeção de dependência (DI). Serviços, como o contexto do banco de dados, são registrados com DI em Program.cs
. Esses serviços são fornecidos a componentes que os exigem por meio de parâmetros do construtor.
No arquivo Controllers/MoviesController.cs
, o construtor usa Dependency Injection para injetar o contexto de banco de dados MvcMovieContext
no controlador. O contexto do banco de dados é usado em cada um dos métodos CRUD no controlador.
Scaffolding gerou o seguinte código destacado em Program.cs
:
- Visual Studio
- de código do Visual Studio
- Visual Studio para Mac
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddDbContext<MvcMovieContext>(options =>
options.UseSqlServer(builder.Configuration.GetConnectionString("MvcMovieContext")));
O sistema de configuração ASP.NET Core lê a cadeia de conexão do banco de dados "MvcMovieContext".
Examine a cadeia de conexão à base de dados gerada
Scaffolding adicionou uma cadeia de conexão ao arquivo appsettings.json
:
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*",
"ConnectionStrings": {
"MvcMovieContext": "Server=(localdb)\\mssqllocaldb;Database=MvcMovieContext-7dc5;Trusted_Connection=True;MultipleActiveResultSets=true"
}
}
Para o desenvolvimento local, o sistema de configuração ASP.NET Core lê a chave ConnectionString
do arquivo appsettings.json
.
A classe InitialCreate
Examine o arquivo de migração Migrations/{timestamp}_InitialCreate.cs
:
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 Filme e configuraId
como a chave primária. -
InitialCreate.Down
reverte as alterações de esquema feitas pela migração deUp
.
Injeção de dependência no controlador
Abra o arquivo Controllers/MoviesController.cs
e examine o construtor:
public class MoviesController : Controller
{
private readonly MvcMovieContext _context;
public MoviesController(MvcMovieContext context)
{
_context = context;
}
O construtor usa Dependency Injection para injetar o contexto do banco de dados (MvcMovieContext
) no controlador. O contexto do banco de dados é usado em cada um dos métodos CRUD no controlador.
Teste a página Criar. Insira e envie dados.
Teste a página Editar, a página Detalhes, e a página Apagar.
Modelos fortemente tipificados e a diretiva @model
No início deste 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 e tardia de passar informações para uma exibição.
O MVC fornece a capacidade de passar objetos de modelo fortemente tipados para uma exibição. Essa abordagem fortemente tipada permite a verificação de código em tempo de compilação. O mecanismo de andaime passou por um modelo fortemente tipado na classe MoviesController
e visualizações.
Examine o método Details
gerado no arquivo Controllers/MoviesController.cs
:
// 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, o https://localhost:5001/movies/details/1
define conjuntos:
- O controlador para o
movies
controlador, o primeiro segmento de URL. - Ação para
details
, o segundo segmento do URL. -
id
a 1 é o último segmento do 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 parâmetro id
é definido como um tipo anulável (int?
) nos casos em que o valor id
não é fornecido.
Um de expressão lambda é passado para o método FirstOrDefaultAsync para selecionar entidades de filme que correspondam aos dados de rota ou ao valor da cadeia de caracteres de consulta.
var movie = await _context.Movie
.FirstOrDefaultAsync(m => m.Id == id);
Se um filme for encontrado, uma instância do modelo Movie
será passada para a visualização Details
:
return View(movie);
Examine o conteúdo do arquivo Views/Movies/Details.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 ficheiro de vista especifica o tipo de objeto que a vista espera. Quando o controlador de filme foi criado, a seguinte instrução @model
foi incluída:
@model MvcMovie.Models.Movie
Esta diretiva @model
permite o acesso ao filme que o controlador passou para a visualização. O objeto Model
é fortemente tipado. Por exemplo, na visualização Details.cshtml
, o código passa cada campo do filme para os DisplayNameFor
e DisplayFor
HTML Helpers com o objeto Model
fortemente tipado. Os métodos e exibições Create
e Edit
também passam por um objeto de modelo Movie
.
Examine a visualização Index.cshtml
e o método Index
no controlador Movies. Observe como o código cria um objeto List
quando chama o método View
. O código passa essa lista de Movies
do método de ação Index
para a exibição:
// GET: Movies
public async Task<IActionResult> Index()
{
return View(await _context.Movie.ToListAsync());
}
Quando o controlador de filmes foi criado, o andaime incluía a seguinte instrução @model
na parte superior do arquivo Index.cshtml
:
@model IEnumerable<MvcMovie.Models.Movie>
A diretiva @model
permite o acesso à lista de filmes que o controlador passou para a visualização usando um objeto Model
fortemente digitado. Por exemplo, na visualização Index.cshtml
, o código percorre os filmes com uma instrução foreach
sobre um objeto fortemente tipado Model
:
@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 objeto Model
é fortemente tipado como um objeto IEnumerable<Movie>
, cada item no loop é tipado como Movie
. Entre outros benefícios, o compilador valida os tipos usados no código.
Recursos adicionais
Neste tutorial, as classes são adicionadas para gerenciar filmes em um banco de dados. Estas classes são a parte "Model" da aplicação MVC.
Essas classes de modelo são usadas com Entity Framework Core (EF Core) para trabalhar com um banco de dados. EF Core é uma estrutura de mapeamento objeto-relacional (ORM) 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 qualquer dependência de EF Core. Eles apenas definem as propriedades dos dados a serem armazenados no banco de dados.
Neste tutorial, as classes de modelo são criadas primeiro e EF Core cria o banco de dados.
Adicionar uma classe de modelo de dados
- Visual Studio
- de código do Visual Studio
- Visual Studio para Mac
Clique com o botão direito do rato na pasta Modelos>Adicionar>Classe. Nomeie o arquivo Movie.cs
.
Atualize o arquivo Models/Movie.cs
com o seguinte código:
using System;
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 atributo DataType em ReleaseDate
especifica o tipo de dados (Date
). Com este atributo:
- O usuário não é obrigado a inserir informações de hora no campo de data.
- Apenas a data é exibida, não as informações de hora.
DataAnnotations são abordados em um tutorial posterior.
Adicionar pacotes NuGet
- Visual Studio
- de código do Visual Studio
- Visual Studio para Mac
No menu Ferramentas, selecione Gestor de Pacotes NuGet>Consola do Gestor de Pacotes (PMC).
No PMC, execute o seguinte comando:
Install-Package Microsoft.EntityFrameworkCore.Design
Os comandos anteriores adicionam:
- O provedor do SQL Server EF Core. O pacote do provedor instala o pacote EF Core como uma dependência.
- Os utilitários utilizados pelos pacotes instalados automaticamente na etapa de estruturação, serão abordados mais adiante no tutorial.
Construa o projeto como uma verificação de erros do compilador.
Páginas de filmes em andaimes
Use a ferramenta de andaime para produzir as páginas Create
, Read
, Update
e Delete
(CRUD) para o modelo do filme.
- Visual Studio
- de código do Visual Studio
- Visual Studio para Mac
No Explorador de Soluções , clique com o botão direito do rato na pasta Controladores e selecione Adicionar > Novo Item Estruturado.
acima
Na caixa de diálogo Adicionar Scaffold, selecione Controlador MVC com vistas, utilizando o Entity Framework > Adicionar.
Conclua o Adicionar Controlador MVC com modos de exibição, usando a caixa de diálogo do Entity Framework:
- Na lista suspensa classe Model, selecione Filme (MvcMovie.Models).
- Na linha da classe de contexto Data, selecione o + (mais).
- Na caixa de diálogo Adicionar Contexto de Dados , é gerado o nome da classe MvcMovie.Data.MvcMovieContext .
- Selecione Adicionar.
- Visualizações e nome do controlador: Mantenha o padrão.
- Selecione Adicionar.
O andaime atualiza o seguinte:
- Insere as referências de pacote necessárias no arquivo de projeto
MvcMovie.csproj
. - Regista o contexto da base de dados em
Startup.ConfigureServices
do ficheiroStartup.cs
. - Adiciona uma cadeia de conexão de banco de dados ao arquivo
appsettings.json
.
O andaime cria o seguinte:
- Um controlador de filmes:
Controllers/MoviesController.cs
-
Razor visualizar ficheiros para Criar, Apagar, Detalhes, Editare Índice páginas:
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 arquivos é conhecida como scaffolding.
As páginas com andaimes ainda não podem ser usadas porque o banco de dados não existe. Executar o aplicativo e selecionar o link do Movie App resulta numa mensagem de erro Não é possível abrir o banco de dados ou nenhuma tabela chamada Movie.
Migração inicial
Use a funcionalidade EF CoreMigrações para criar a base 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.
No menu Ferramentas, selecione Gestor de Pacotes NuGet>Console do Gestor de Pacotes.
No Console do Gerenciador de Pacotes (PMC), digite os seguintes comandos:
Add-Migration InitialCreate
Update-Database
Add-Migration InitialCreate
: Gera um arquivo de migraçãoMigrations/{timestamp}_InitialCreate.cs
. O argumentoInitialCreate
é o nome da migração. Qualquer nome pode ser usado, mas, por convenção, é selecionado um nome que descreve a migração. Como esta é a primeira migração, a classe gerada contém código para criar o esquema de banco de dados. O esquema de banco de dados é baseado no modelo especificado na classeMvcMovieContext
.Update-Database
: Atualiza o banco de dados para a migração mais recente, que o comando anterior criou. Este comando executa o métodoUp
no arquivoMigrations/{time-stamp}_InitialCreate.cs
, que cria o banco de dados.
O comando Update-Database
gera o seguinte aviso:
Nenhum tipo foi especificado para a coluna decimal 'Preço' no tipo de entidade 'Filme'. Isso fará com que os valores sejam truncados silenciosamente se não se ajustarem à precisão e escala padrão. Especifique explicitamente o tipo de coluna do servidor SQL que pode acomodar todos os valores usando 'HasColumnType()'.
Ignore o aviso anterior, ele é corrigido em um tutorial posterior.
Para mais informações sobre as ferramentas PMC para EF Core, consulte a referência de ferramentas EF Core - PMC no Visual Studio.
Testar a aplicação
Execute a aplicação e selecione o link Movie App.
Se obtiveres uma exceção semelhante à seguinte, é possível que tenhas falhado o passo das migrações :
SqlException: Cannot open database "MvcMovieContext-1" requested by the login. The login failed.
Observação
Talvez não seja possível inserir vírgulas decimais no campo Price
. Para oferecer suporte à validação do jQuery para em locais não ingleses que usam uma vírgula (",") como ponto decimal e para formatos de data que não sejam US-English, o aplicativo deve ser globalizado. Para obter instruções sobre globalização, consulte esta questão do GitHub .
Examine a classe de contexto e o registro do banco de dados gerado
Com EF Core, o acesso aos dados é realizado usando um modelo. Um modelo é composto 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 do banco de dados é derivado de Microsoft.EntityFrameworkCore.DbContext e especifica as entidades a serem incluídas no modelo de dados.
Scaffolding cria a classe de contexto de banco de dados Data/MvcMovieContext.cs
:
using Microsoft.EntityFrameworkCore;
using MvcMovie.Models;
namespace MvcMovie.Data
{
public class MvcMovieContext : DbContext
{
public MvcMovieContext (DbContextOptions<MvcMovieContext> options)
: base(options)
{
}
public DbSet<Movie> Movie { get; set; }
}
}
O código anterior cria uma propriedade DbSet<Movie> que representa os filmes no banco de dados.
ASP.NET Core foi desenvolvido com injeção de dependência (DI). Serviços, como o contexto do banco de dados, devem ser registrados com DI em Startup
. Os componentes que requerem esses serviços são fornecidos por meio de parâmetros do construtor.
No arquivo Controllers/MoviesController.cs
, o construtor usa Dependency Injection para injetar o contexto de banco de dados MvcMovieContext
no controlador. O contexto do banco de dados é usado em cada um dos métodos CRUD no controlador.
Andaime gerou o seguinte código destacado em Startup.ConfigureServices
:
- Visual Studio
- de código do Visual Studio
- Visual Studio para Mac
public void ConfigureServices(IServiceCollection services)
{
services.AddControllersWithViews();
services.AddDbContext<MvcMovieContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("MvcMovieContext")));
}
O do sistema de configuração ASP.NET Core lê a cadeia de conexão do banco de dados "MvcMovieContext".
Examinar a cadeia de conexão de banco de dados gerada
Scaffolding adicionou uma cadeia de conexão ao arquivo appsettings.json
:
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"AllowedHosts": "*",
"ConnectionStrings": {
"MvcMovieContext": "Server=(localdb)\\mssqllocaldb;Database=MvcMovieContext-1;Trusted_Connection=True;MultipleActiveResultSets=true"
}
}
Para o desenvolvimento local, o sistema de configuração ASP.NET Core lê a chave ConnectionString
do arquivo appsettings.json
.
A classe InitialCreate
Examine o arquivo de migração Migrations/{timestamp}_InitialCreate.cs
:
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 Filme e configuraId
como a chave primária. -
InitialCreate.Down
reverte as alterações de esquema feitas pela migração deUp
.
Injeção de dependência no controlador
Abra o ficheiro Controllers/MoviesController.cs
e examine o construtor:
public class MoviesController : Controller
{
private readonly MvcMovieContext _context;
public MoviesController(MvcMovieContext context)
{
_context = context;
}
O construtor usa Dependency Injection para injetar o contexto do banco de dados (MvcMovieContext
) no controlador. O contexto do banco de dados é usado em cada um dos métodos CRUD no controlador.
Teste a página Criar. Insira e envie dados.
Teste as páginas Editar, Detalhese Eliminar.
Modelos fortemente tipados e a diretiva @model
No início deste 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 e tardia de passar informações para uma exibição.
O MVC fornece a capacidade de passar objetos de modelo fortemente tipados para uma exibição. Esta abordagem de tipagem forte permite a verificação de código em tempo de compilação. O mecanismo de andaime passou por um modelo fortemente tipado na classe MoviesController
e visualizações.
Examine o método Details
gerado no arquivo Controllers/MoviesController.cs
:
// 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
movies
, o primeiro segmento de URL. - A ação para
details
, o segundo segmento de URL. - O
id
até 1, o último segmento do 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 parâmetro id
é definido como um tipo anulável (int?
) nos casos em que o valor id
não é fornecido.
Um de expressão lambda é passado para o método FirstOrDefaultAsync para selecionar entidades de filme que correspondam aos dados de rota ou ao valor da cadeia de caracteres de consulta.
var movie = await _context.Movie
.FirstOrDefaultAsync(m => m.Id == id);
Se um filme for encontrado, uma instância do modelo Movie
será passada para a visualização Details
:
return View(movie);
Examine o conteúdo do arquivo Views/Movies/Details.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 ficheiro de vista especifica o tipo de objeto que a vista espera. Quando o controlador de filme foi criado, a seguinte instrução @model
foi incluída:
@model MvcMovie.Models.Movie
Esta diretiva @model
permite o acesso ao filme que o controlador passou para a vista. O objeto Model
é fortemente tipado. Por exemplo, na visualização Details.cshtml
, o código passa cada campo de filme para os auxiliares HTML DisplayNameFor
e DisplayFor
com o objeto de tipagem forte Model
. Os métodos e exibições Create
e Edit
também passam por um objeto de modelo Movie
.
Examine a visualização Index.cshtml
e o método Index
no controlador Movies. Observe como o código cria um objeto List
quando chama o método View
. O código passa esta lista Movies
do método de ação Index
para a vista:
// GET: Movies
public async Task<IActionResult> Index()
{
return View(await _context.Movie.ToListAsync());
}
Quando o controlador de filmes foi criado, o scaffolding incluiu a seguinte instrução @model
no topo do arquivo Index.cshtml
:
@model IEnumerable<MvcMovie.Models.Movie>
A diretiva @model
permite o acesso à lista de filmes que o controlador passou para a visualização usando um objeto Model
fortemente digitado. Por exemplo, na visualização Index.cshtml
, o código percorre os filmes com uma instrução foreach
sobre o objeto Model
fortemente tipado:
@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 objeto Model
é fortemente tipado como um objeto IEnumerable<Movie>
, cada item no loop é do tipo Movie
. Entre outros benefícios, o compilador valida os tipos usados no código.
Registo de SQL do Entity Framework Core
A configuração de registro em log geralmente é fornecida pela seção Logging
de arquivos appsettings.{Environment}.json
. Para registrar instruções SQL, adicione "Microsoft.EntityFrameworkCore.Database.Command": "Information"
ao arquivo appsettings.Development.json
:
{
"ConnectionStrings": {
"DefaultConnection": "Server=(localdb)\\mssqllocaldb;Database=MyDB-2;Trusted_Connection=True;MultipleActiveResultSets=true"
},
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
,"Microsoft.EntityFrameworkCore.Database.Command": "Information"
}
},
"AllowedHosts": "*"
}
Com o JSON anterior, as instruções SQL são exibidas na linha de comando e na janela de saída do Visual Studio.
Para obter mais informações, consulte Logging in .NET Core e ASP.NET Core e este problema do GitHub.
Recursos adicionais
Neste tutorial, as classes são adicionadas para gerenciar filmes em um banco de dados. Estas classes são a parte "Model" da aplicação MVC.
Essas classes de modelo são usadas com Entity Framework Core (EF Core) para trabalhar com um banco de dados. EF Core é uma estrutura de mapeamento objeto-relacional (ORM) que simplifica o código de acesso a dados que você precisa escrever.
As classes de modelo criadas são conhecidas como POCO classes, derivadas de Plain Old CLR Objects. As classes POCO não têm qualquer dependência de EF Core. Eles apenas definem as propriedades dos dados a serem armazenados no banco de dados.
Neste tutorial, as classes de modelo são criadas primeiro e EF Core cria o banco de dados.
Adicionar uma classe de modelo de dados
- Visual Studio
- de código do Visual Studio
- Visual Studio para Mac
Clique com o botão direito do rato na pasta Modelos>Adicionar>Classe. Nomeie o arquivo Movie.cs
.
Atualize o arquivo Movie.cs
com o seguinte código:
using System;
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 atributo DataType em ReleaseDate
especifica o tipo de dados (Date
). Com este atributo:
- O usuário não é obrigado a inserir informações de hora no campo de data.
- Apenas a data é exibida, não as informações de hora.
DataAnnotations são abordados em um tutorial posterior.
Adicionar pacotes NuGet
- Visual Studio
- de código do Visual Studio
- Visual Studio para Mac
No menu Ferramentas, selecione Gestor de Pacotes NuGet>Consola do Gestor de Pacotes (PMC).
No PMC, execute o seguinte comando:
Install-Package Microsoft.EntityFrameworkCore.SqlServer
O comando anterior adiciona o provedor EF Core SQL Server. O pacote do provedor instala o pacote EF Core como uma dependência. Pacotes adicionais são instalados automaticamente na etapa de andaimes mais adiante no tutorial.
Criar uma classe de contexto de banco de dados
É necessária uma classe de contexto de base de dados para coordenar a funcionalidade de EF Core (Criar, Ler, Atualizar, Excluir) para o modelo Movie
. O contexto do banco de dados é derivado de Microsoft.EntityFrameworkCore.DbContext e especifica as entidades a serem incluídas no modelo de dados.
Crie uma pasta Data.
Adicione um arquivo Data/MvcMovieContext.cs
com o seguinte código:
using Microsoft.EntityFrameworkCore;
using MvcMovie.Models;
namespace MvcMovie.Data
{
public class MvcMovieContext : DbContext
{
public MvcMovieContext (DbContextOptions<MvcMovieContext> options)
: base(options)
{
}
public DbSet<Movie> Movie { get; set; }
}
}
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 na tabela.
Registrar o contexto do banco de dados
ASP.NET Core é construído com injeção de dependência (DI). Os serviços (como o contexto de banco de dados EF Core) devem ser registrados com DI durante a inicialização do aplicativo. Os componentes que requerem esses serviços (como Razor Pages) são fornecidos por meio de parâmetros do construtor. O código do construtor que obtém uma instância de contexto de banco de dados é mostrado posteriormente no tutorial. Nesta seção, você registra o contexto do banco de dados com o contêiner DI.
Adicione as seguintes instruções using
na parte superior do Startup.cs
:
using MvcMovie.Data;
using Microsoft.EntityFrameworkCore;
Adicione o seguinte código realçado em Startup.ConfigureServices
:
public void ConfigureServices(IServiceCollection services)
{
services.AddControllersWithViews();
services.AddDbContext<MvcMovieContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("MvcMovieContext")));
}
O nome da cadeia de conexão é passado para o contexto chamando um método em um objeto DbContextOptions. Para o desenvolvimento local, o sistema de configuração ASP.NET Core lê a cadeia de conexão do arquivo appsettings.json
.
Examinar a cadeia de conexão do banco de dados
Adicione uma cadeia de conexão ao arquivo appsettings.json
:
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"AllowedHosts": "*",
"ConnectionStrings": {
"MvcMovieContext": "Server=(localdb)\\mssqllocaldb;Database=MvcMovieContext-1;Trusted_Connection=True;MultipleActiveResultSets=true"
}
}
Construa o projeto como uma verificação de erros do compilador.
Páginas de filmes em andaimes
Use a ferramenta de andaime para produzir páginas CRUD (Criar, Ler, Atualizar e Excluir) para o modelo de filme.
- Visual Studio
- de código do Visual Studio
- Visual Studio para Mac
No Gerenciador de Soluções , clique com o botão direito do mouse na pasta Controladores> Adicionar > Novo Item Andaime.
acima
Na caixa de diálogo Adicionar Scaffold, selecione Controlador MVC com vistas, usando o Entity Framework > Adicionar.
Preencha a caixa de diálogo Adicionar controlador:
- Classe de modelo:Movie (MvcMovie.Models)
- Classe de contexto de dados:MvcMovieContext (MvcMovie.Data)
Adicionar dados de contexto
- Visualizações: Manter o padrão de cada opção marcado
- Nome do controlador: Manter o padrão MoviesController
- Selecione Adicionar
O Visual Studio cria:
- Um controlador de filmes (
Controllers/MoviesController.cs
) - Razor visualizar arquivos para as páginas Criar, Excluir, Detalhes, Editar e Índice (*Visualizações/Filmes/'.cshtml')
A criação automática desses arquivos é conhecida como scaffolding.
Ainda não é possível usar as páginas com andaimes porque o banco de dados não existe. Se você executar o aplicativo e clicar no link do Movie App, receberá uma mensagem de erro Não é possível abrir o banco de dados ou não nenhuma tabela: Movie.
Migração inicial
Use o recurso EF CoreMigrações para criar o banco de dados. Migrações é um conjunto de ferramentas que permite criar e atualizar um banco de dados para corresponder ao seu modelo de dados.
No menu Ferramentas, selecione Gestor de Pacotes NuGet>Consola do Gestor de Pacotes (PMC).
No PMC, digite os seguintes comandos:
Add-Migration InitialCreate
Update-Database
Add-Migration InitialCreate
: Gera um arquivo de migraçãoMigrations/{timestamp}_InitialCreate.cs
. O argumentoInitialCreate
é o nome da migração. Qualquer nome pode ser usado, mas, por convenção, é selecionado um nome que descreve a migração. Como esta é a primeira migração, a classe gerada contém código para criar o esquema de banco de dados. O esquema de banco de dados é baseado no modelo especificado na classeMvcMovieContext
.Update-Database
: Atualiza o banco de dados para a migração mais recente, que o comando anterior criou. Este comando executa o métodoUp
no arquivoMigrations/{time-stamp}_InitialCreate.cs
, que cria o banco de dados.O comando database update gera o seguinte aviso:
Nenhum tipo foi especificado para a coluna decimal 'Preço' no tipo de entidade 'Filme'. Isso fará com que os valores sejam truncados silenciosamente se não se ajustarem à precisão e escala padrão. Especifique explicitamente o tipo de coluna do servidor SQL que pode acomodar todos os valores usando 'HasColumnType()'.
Você pode ignorar esse aviso, ele será corrigido em um tutorial posterior.
Para obter mais informações sobre as ferramentas PMC para EF Core, consulte a referência de ferramentas EF Core - PMC no Visual Studio.
A classe InitialCreate
Examine o arquivo de migração Migrations/{timestamp}_InitialCreate.cs
:
public partial class InitialCreate : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "Movie",
columns: table => new
{
Id = table.Column<int>(nullable: false)
.Annotation("SqlServer:ValueGenerationStrategy",
SqlServerValueGenerationStrategy.IdentityColumn),
Title = table.Column<string>(nullable: true),
ReleaseDate = table.Column<DateTime>(nullable: false),
Genre = table.Column<string>(nullable: true),
Price = table.Column<decimal>(nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Movie", x => x.Id);
});
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "Movie");
}
}
O método Up
cria a tabela Movie e configura Id
como a chave primária. O método Down
reverte as alterações de esquema feitas pela migração de Up
.
Testar a aplicação
Execute a aplicação e clique no link Movie App.
Se você obtiver uma exceção semelhante a uma das seguintes:
SqlException: Cannot open database "MvcMovieContext-1" requested by the login. The login failed.
Você provavelmente perdeu o passo de migrações .
Teste a página Criar. Insira e envie dados.
Observação
Talvez não seja possível inserir vírgulas decimais no campo
Price
. Para oferecer suporte a de validação do jQuery para localidades diferentes do inglês que usam uma vírgula (",") para um ponto decimal e para formatos de data não US-English, o aplicativo deve ser globalizado. Para obter instruções sobre globalização, consulte esta questão do GitHub.Teste o Editar, Detalhese Excluir páginas.
Injeção de dependência no controlador
Abra o ficheiro Controllers/MoviesController.cs
e examine o construtor:
public class MoviesController : Controller
{
private readonly MvcMovieContext _context;
public MoviesController(MvcMovieContext context)
{
_context = context;
}
O construtor usa Dependency Injection para injetar o contexto do banco de dados (MvcMovieContext
) no controlador. O contexto do banco de dados é usado em cada um dos métodos CRUD no controlador.
Modelos fortemente tipados e a palavra-chave @model
No início deste 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 e tardia de passar informações para uma exibição.
O MVC também oferece a capacidade de passar objetos de modelo fortemente tipados para uma exibição. Esta abordagem fortemente tipada permite a verificação de código durante o tempo de compilação. O mecanismo de andaime usou essa abordagem (ou seja, passar um modelo fortemente tipado) com a classe MoviesController
e as visualizações.
Examine o método Details
gerado no arquivo Controllers/MoviesController.cs
:
// 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
(o primeiro segmento de URL). - A ação relacionada a
details
(o segundo segmento de URL). - O id é 1 (o segmento final do URL).
Você também pode passar o id
com uma string de consulta da seguinte maneira:
https://localhost:5001/movies/details?id=1
O parâmetro id
é definido como um tipo anulável (int?
) caso um valor de ID não seja fornecido.
Uma expressão lambda é passada para FirstOrDefaultAsync
para selecionar entidades de filmes que correspondam aos dados de rota ou ao valor da cadeia de consulta.
var movie = await _context.Movie
.FirstOrDefaultAsync(m => m.Id == id);
Se um filme for encontrado, uma instância do modelo Movie
será passada para a visualização Details
:
return View(movie);
Examine o conteúdo do arquivo Views/Movies/Details.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 ficheiro de vista especifica o tipo de objeto que a vista espera. Quando o controlador de filme foi criado, a seguinte instrução @model
foi incluída:
@model MvcMovie.Models.Movie
Esta diretiva @model
permite o acesso ao filme que o controlador passou para a vista. O objeto Model
é fortemente tipado. Por exemplo, na visualização Details.cshtml
, o código passa cada campo de filme para os Helpers HTML DisplayNameFor
e DisplayFor
com o objeto fortemente tipado Model
. Os métodos e exibições Create
e Edit
também passam por um objeto de modelo Movie
.
Examine a visualização Index.cshtml
e o método Index
no controlador de filmes. Observe como o código cria um objeto List
quando chama o método View
. O código passa essa lista de Movies
do método de ação Index
para a exibição:
// GET: Movies
public async Task<IActionResult> Index()
{
return View(await _context.Movie.ToListAsync());
}
Quando o controlador de filmes foi criado, o scaffolding incluiu a seguinte instrução @model
no início do ficheiro Index.cshtml
.
@model IEnumerable<MvcMovie.Models.Movie>
A diretiva @model
permite que você acesse a lista de filmes que o controlador passou para a exibição usando um objeto Model
que é fortemente tipado. Por exemplo, na visualização Index.cshtml
, o código percorre os filmes com uma instrução foreach
sobre o objeto Model
fortemente tipado:
@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 objeto Model
é fortemente tipado (como um objeto IEnumerable<Movie>
), cada item no loop é tipado como Movie
. Entre outros benefícios, isso significa que você obtém verificação de tempo de compilação do código.