Anteckning
Åtkomst till den här sidan kräver auktorisering. Du kan prova att logga in eller ändra kataloger.
Åtkomst till den här sidan kräver auktorisering. Du kan prova att ändra kataloger.
Varning
Den här versionen av ASP.NET Core stöds inte längre. Mer information finns i supportpolicyn för .NET och .NET Core. För den nuvarande utgåvan, se .NET 9-versionen av den här artikeln .
Viktigt!
Den här informationen gäller en förhandsversionsprodukt som kan ändras avsevärt innan den släpps kommersiellt. Microsoft lämnar inga garantier, uttryckliga eller underförstådda, med avseende på den information som tillhandahålls här.
För den nuvarande utgåvan, se .NET 9-versionen av den här artikeln .
I den här handledningen går vi igenom de Razor sidor som skapades genom scaffolding i den föregående handledningen.
Sidorna Skapa, Ta bort, Detaljer och Redigera
Pages/Movies/Index.cshtml.cs Granska sidmodellen:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.EntityFrameworkCore;
using RazorPagesMovie.Data;
using RazorPagesMovie.Models;
using Microsoft.AspNetCore.Mvc.Rendering;
namespace RazorPagesMovie.Pages.Movies
{
public class IndexModel : PageModel
{
private readonly RazorPagesMovie.Data.RazorPagesMovieContext _context;
public IndexModel(RazorPagesMovie.Data.RazorPagesMovieContext context)
{
_context = context;
}
public IList<Movie> Movie { get;set; } = default!;
public async Task OnGetAsync()
{
Movie = await _context.Movie.ToListAsync();
}
}
}
Razor Sidor härleds från PageModel. Enligt konventionen heter den härledda klassen `PageModel` `PageNameModel`. Sidan Index heter IndexModeltill exempel .
Konstruktorn använder beroendeinmatning för att lägga RazorPagesMovieContext till på sidan:
public class IndexModel : PageModel
{
private readonly RazorPagesMovie.Data.RazorPagesMovieContext _context;
public IndexModel(RazorPagesMovie.Data.RazorPagesMovieContext context)
{
_context = context;
}
Mer information om asynkron programmering med Entity Framework finns i Asynkron kod .
När en GET begäran görs för sidan OnGetAsync returnerar metoden en lista över filmer till sidan Razor . På en Razor sida, OnGetAsync eller OnGet anropas för att initiera sidans tillstånd. I det här fallet hämtar OnGetAsync en lista över filmer och visar dem.
När OnGet returnerar void eller OnGetAsync returnerar Taskanvänds ingen retursats. Granska till exempel sidan Privacy :
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
namespace RazorPagesMovie.Pages
{
public class PrivacyModel : PageModel
{
private readonly ILogger<PrivacyModel> _logger;
public PrivacyModel(ILogger<PrivacyModel> logger)
{
_logger = logger;
}
public void OnGet()
{
}
}
}
När returtypen är IActionResult eller Task<IActionResult>måste en retursats anges. Till exempel metoden Pages/Movies/Create.cshtml.cs OnPostAsync :
public async Task<IActionResult> OnPostAsync()
{
if (!ModelState.IsValid)
{
return Page();
}
_context.Movie.Add(Movie);
await _context.SaveChangesAsync();
return RedirectToPage("./Index");
}
Granska sidan Pages/Movies/Index.cshtmlRazor :
@page
@model RazorPagesMovie.Pages.Movies.IndexModel
@{
ViewData["Title"] = "Index";
}
<h1>Index</h1>
<p>
<a asp-page="Create">Create New</a>
</p>
<table class="table">
<thead>
<tr>
<th>
@Html.DisplayNameFor(model => model.Movie[0].Title)
</th>
<th>
@Html.DisplayNameFor(model => model.Movie[0].ReleaseDate)
</th>
<th>
@Html.DisplayNameFor(model => model.Movie[0].Genre)
</th>
<th>
@Html.DisplayNameFor(model => model.Movie[0].Price)
</th>
<th></th>
</tr>
</thead>
<tbody>
@foreach (var item in Model.Movie) {
<tr>
<td>
@Html.DisplayFor(modelItem => item.Title)
</td>
<td>
@Html.DisplayFor(modelItem => item.ReleaseDate)
</td>
<td>
@Html.DisplayFor(modelItem => item.Genre)
</td>
<td>
@Html.DisplayFor(modelItem => item.Price)
</td>
<td>
<a asp-page="./Edit" asp-route-id="@item.Id">Edit</a> |
<a asp-page="./Details" asp-route-id="@item.Id">Details</a> |
<a asp-page="./Delete" asp-route-id="@item.Id">Delete</a>
</td>
</tr>
}
</tbody>
</table>
Razor kan övergå från HTML till C# eller till Razor-specifik markering. När en @ symbol följs av ett Razor reserverat nyckelord övergår den till Razor-specifik markering, annars övergår den till C#.
Direktivet @page
Direktivet @pageRazor gör filen till en MVC-åtgärd, vilket innebär att den kan hantera begäranden.
@page måste vara det första Razor direktivet på en sida.
@page och @model är exempel på övergång till Razor-specifik markering. Mer Razor information finns i syntaxen .
Direktivet @model
@page
@model RazorPagesMovie.Pages.Movies.IndexModel
Direktivet @model anger vilken typ av modell som skickas till sidan Razor . I föregående exempel gör raden @model den PageModel härledda klassen tillgänglig för sidan Razor. Modellen används i @Html.DisplayNameFor@Html.DisplayFor och på sidan.
Granska lambda-uttrycket som används i följande HTML-hjälp:
@Html.DisplayNameFor(model => model.Movie[0].Title)
DisplayNameFor HTML-hjälpen inspekterar egenskapen Title som refereras i lambda-uttrycket för att fastställa visningsnamnet. Lambda-uttrycket inspekteras i stället för att utvärderas. Det innebär att det inte finns någon åtkomstöverträdelse när model, model.Movieeller model.Movie[0] är null eller är tom. När lambda-uttrycket utvärderas, till exempel med @Html.DisplayFor(modelItem => item.Title), utvärderas modellens egenskapsvärden.
Layoutsidan
Välj menyn länkar RazorPagesMovie, Home, och Privacy. Varje sida visar samma menylayout. Menylayouten implementeras i Pages/Shared/_Layout.cshtml filen.
Öppna och granska Pages/Shared/_Layout.cshtml filen.
Med layoutmallar kan HTML-containerlayouten vara:
- Anges på ett ställe.
- Tillämpas på flera sidor på webbplatsen.
Hitta @RenderBody() raden.
RenderBody är en platsreserv där alla sidspecifika vyer dyker upp, omslutna i layoutsidan. Till exempel, välj Privacy länken och Pages/Privacy.cshtml vyn återges i RenderBody metoden.
ViewData och layout
Överväg följande markering från Pages/Movies/Index.cshtml filen:
@page
@model RazorPagesMovie.Pages.Movies.IndexModel
@{
ViewData["Title"] = "Index";
}
Föregående markerade markering är ett exempel på Razor övergången till C#. Tecknen { och } omger ett block med C#-kod.
Basklassen PageModel innehåller en ViewData ordlisteegenskap som kan användas för att skicka data till en vy. Objekt läggs till i ViewData ordlistan med hjälp av ett nyckelvärdemönster . I föregående exempel läggs egenskapen Title till i ViewData ordlistan.
Egenskapen Title används i Pages/Shared/_Layout.cshtml filen. Följande markering visar de första raderna i _Layout.cshtml filen.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>@ViewData["Title"] - RazorPagesMovie</title>
<link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.css" />
<link rel="stylesheet" href="~/css/site.css" asp-append-version="true" />
<link rel="stylesheet" href="~/RazorPagesMovie.styles.css" asp-append-version="true" />
Uppdatera layouten
Ändra elementet
<title>i filen så att detPages/Shared/_Layout.cshtmlvisar film i stället för RazorPagesMovie.<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>@ViewData["Title"] - Movie</title>Hitta följande fästpunktselement i
Pages/Shared/_Layout.cshtmlfilen.<a class="navbar-brand" asp-area="" asp-page="/Index">RazorPagesMovie</a>Ersätt föregående element med följande markering:
<a class="navbar-brand" asp-page="/Movies/Index">RpMovie</a>Föregående fästpunktselement är en Tag Helper. I det här fallet är det Anchor Tag Helper. Attributet
asp-page="/Movies/Index"och värdet för Tag Helper skapar en länk till sidan/Movies/IndexRazor . Attributvärdetasp-areaär tomt, så området används inte i länken. Mer information finns i Områden .Spara ändringarna och testa appen genom att välja länken RpMovie . Se filen _Layout.cshtml i GitHub om du har några problem.
Testa länkarna Home, RpMovie, Create, Edit och Delete . Varje sida anger rubriken, som du kan se på webbläsarfliken. När du bokmärker en sida används rubriken för bokmärket.
Anmärkning
Du kanske inte kan ange decimaltecken i fältet Price. Om du vill stödja jQuery-validering för språkvarianter som inte är engelska och som använder kommatecken (",") för en decimalpunkt och icke-US-English datumformat, måste du vidta åtgärder för att globalisera appen. Titta på det här GitHub-ärende 4076 för instruktioner om hur du lägger till decimaltecken.
Egenskapen Layout anges i Pages/_ViewStart.cshtml filen:
@{
Layout = "_Layout";
}
Föregående markering anger layoutfilen till Pages/Shared/_Layout.cshtml för alla Razor filer under mappen Sidor . Mer information finns i Layout .
Modellen för skapa-sidan
Pages/Movies/Create.cshtml.cs Granska sidmodellen:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.AspNetCore.Mvc.Rendering;
using RazorPagesMovie.Data;
using RazorPagesMovie.Models;
namespace RazorPagesMovie.Pages.Movies
{
public class CreateModel : PageModel
{
private readonly RazorPagesMovie.Data.RazorPagesMovieContext _context;
public CreateModel(RazorPagesMovie.Data.RazorPagesMovieContext context)
{
_context = context;
}
public IActionResult OnGet()
{
return Page();
}
[BindProperty]
public Movie Movie { get; set; } = default!;
// To protect from overposting attacks, see https://aka.ms/RazorPagesCRUD
public async Task<IActionResult> OnPostAsync()
{
if (!ModelState.IsValid)
{
return Page();
}
_context.Movie.Add(Movie);
await _context.SaveChangesAsync();
return RedirectToPage("./Index");
}
}
}
Metoden OnGet initierar alla tillstånd som behövs för sidan. Sidan Skapa har inget tillstånd att initiera, så Page returneras. Senare i självstudien visas ett exempel på initieringstillstånd OnGet . Metoden Page skapar ett PageResult objekt som renderar Create.cshtml sidan.
Egenskapen Movie använder attributet [BindProperty] för att välja modellbindning. När formuläret Skapa publicerar formulärvärdena binder ASP.NET Core-körningen de bokförda värdena till Movie modellen.
Metoden OnPostAsync körs när sidan publicerar formulärdata:
public async Task<IActionResult> OnPostAsync()
{
if (!ModelState.IsValid)
{
return Page();
}
_context.Movie.Add(Movie);
await _context.SaveChangesAsync();
return RedirectToPage("./Index");
}
Om det finns några modellfel spelas formuläret upp på ett annat sätt, tillsammans med eventuella formulärdata som publiceras. De flesta modellfel kan fångas på klientsidan innan formuläret publiceras. Ett exempel på ett modellfel är att publicera ett värde för datumfältet som inte kan konverteras till ett datum. Validering på klientsidan och modellverifiering beskrivs senare i självstudien.
Om det inte finns några modellfel:
- Data sparas.
- Webbläsaren omdirigeras till sidan Index.
Skapa sidan Razor
Pages/Movies/Create.cshtml
Razor Granska sidfilen:
@page
@model RazorPagesMovie.Pages.Movies.CreateModel
@{
ViewData["Title"] = "Create";
}
<h1>Create</h1>
<h4>Movie</h4>
<hr />
<div class="row">
<div class="col-md-4">
<form method="post">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="Movie.Title" class="control-label"></label>
<input asp-for="Movie.Title" class="form-control" />
<span asp-validation-for="Movie.Title" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Movie.ReleaseDate" class="control-label"></label>
<input asp-for="Movie.ReleaseDate" class="form-control" />
<span asp-validation-for="Movie.ReleaseDate" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Movie.Genre" class="control-label"></label>
<input asp-for="Movie.Genre" class="form-control" />
<span asp-validation-for="Movie.Genre" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Movie.Price" class="control-label"></label>
<input asp-for="Movie.Price" class="form-control" />
<span asp-validation-for="Movie.Price" class="text-danger"></span>
</div>
<div class="form-group">
<input type="submit" value="Create" class="btn btn-primary" />
</div>
</form>
</div>
</div>
<div>
<a asp-page="Index">Back to List</a>
</div>
@section Scripts {
@{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}
Visual Studio visar följande taggar i ett distinkt fetstilt teckensnitt som används för Tag Helpers:
<form method="post"><div asp-validation-summary="ModelOnly" class="text-danger"></div><label asp-for="Movie.Title" class="control-label"></label><input asp-for="Movie.Title" class="form-control" /><span asp-validation-for="Movie.Title" class="text-danger"></span>
Elementet <form method="post"> är en formulärtagghjälpare. Formulärtagghjälpen innehåller automatiskt en antiförfalskningstoken.
Byggnadsställningsmotorn skapar Razor markering för varje fält i modellen, förutom ID:t, ungefär så här:
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="Movie.Title" class="control-label"></label>
<input asp-for="Movie.Title" class="form-control" />
<span asp-validation-for="Movie.Title" class="text-danger"></span>
</div>
Valideringstagghjälparna (<div asp-validation-summary och <span asp-validation-for) visar valideringsfel. Valideringen beskrivs mer detaljerat senare i den här serien.
Label Tag Helper (<label asp-for="Movie.Title" class="control-label"></label>) genererar etiketttexten och [for]-attributet för egenskapen Title.
Hjälpverktyget för indatataggen (<input asp-for="Movie.Title" class="form-control">) använder attributen DataAnnotations och skapar HTML-attribut som behövs för jQuery-validering på klientsidan.
Mer information om Tag Helpers, till exempel <form method="post">, finns i Tag Helpers i ASP.NET Core.
Nästa steg
Sidorna Skapa, Ta bort, Detaljer och Redigera
Pages/Movies/Index.cshtml.cs Granska sidmodellen:
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.EntityFrameworkCore;
using RazorPagesMovie.Models;
namespace RazorPagesMovie.Pages.Movies;
public class IndexModel : PageModel
{
private readonly RazorPagesMovie.Data.RazorPagesMovieContext _context;
public IndexModel(RazorPagesMovie.Data.RazorPagesMovieContext context)
{
_context = context;
}
public IList<Movie> Movie { get;set; } = default!;
public async Task OnGetAsync()
{
if (_context.Movie != null)
{
Movie = await _context.Movie.ToListAsync();
}
}
}
Razor Sidor härleds från PageModel. Enligt konventionen heter den härledda klassen `PageModel` `PageNameModel`. Sidan Index heter IndexModeltill exempel .
Konstruktorn använder beroendeinmatning för att lägga RazorPagesMovieContext till på sidan:
public class IndexModel : PageModel
{
private readonly RazorPagesMovie.Data.RazorPagesMovieContext _context;
public IndexModel(RazorPagesMovie.Data.RazorPagesMovieContext context)
{
_context = context;
}
Mer information om asynkron programmering med Entity Framework finns i Asynkron kod .
När en GET begäran görs för sidan OnGetAsync returnerar metoden en lista över filmer till sidan Razor . På en Razor sida, OnGetAsync eller OnGet anropas för att initiera sidans tillstånd. I det här fallet hämtar OnGetAsync en lista över filmer och visar dem.
När OnGet returnerar void eller OnGetAsync returnerar Taskanvänds ingen retursats. Granska till exempel sidan Privacy :
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
namespace RazorPagesMovie.Pages
{
public class PrivacyModel : PageModel
{
private readonly ILogger<PrivacyModel> _logger;
public PrivacyModel(ILogger<PrivacyModel> logger)
{
_logger = logger;
}
public void OnGet()
{
}
}
}
När returtypen är IActionResult eller Task<IActionResult>måste en retursats anges. Till exempel metoden Pages/Movies/Create.cshtml.cs OnPostAsync :
public async Task<IActionResult> OnPostAsync()
{
if (!ModelState.IsValid)
{
return Page();
}
_context.Movie.Add(Movie);
await _context.SaveChangesAsync();
return RedirectToPage("./Index");
}
Granska sidan Pages/Movies/Index.cshtmlRazor :
@page
@model RazorPagesMovie.Pages.Movies.IndexModel
@{
ViewData["Title"] = "Index";
}
<h1>Index</h1>
<p>
<a asp-page="Create">Create New</a>
</p>
<table class="table">
<thead>
<tr>
<th>
@Html.DisplayNameFor(model => model.Movie[0].Title)
</th>
<th>
@Html.DisplayNameFor(model => model.Movie[0].ReleaseDate)
</th>
<th>
@Html.DisplayNameFor(model => model.Movie[0].Genre)
</th>
<th>
@Html.DisplayNameFor(model => model.Movie[0].Price)
</th>
<th></th>
</tr>
</thead>
<tbody>
@foreach (var item in Model.Movie) {
<tr>
<td>
@Html.DisplayFor(modelItem => item.Title)
</td>
<td>
@Html.DisplayFor(modelItem => item.ReleaseDate)
</td>
<td>
@Html.DisplayFor(modelItem => item.Genre)
</td>
<td>
@Html.DisplayFor(modelItem => item.Price)
</td>
<td>
<a asp-page="./Edit" asp-route-id="@item.Id">Edit</a> |
<a asp-page="./Details" asp-route-id="@item.Id">Details</a> |
<a asp-page="./Delete" asp-route-id="@item.Id">Delete</a>
</td>
</tr>
}
</tbody>
</table>
Razor kan övergå från HTML till C# eller till Razor-specifik markering. När en @ symbol följs av ett Razor reserverat nyckelord övergår den till Razor-specifik markering, annars övergår den till C#.
Direktivet @page
Direktivet @pageRazor gör filen till en MVC-åtgärd, vilket innebär att den kan hantera begäranden.
@page måste vara det första Razor direktivet på en sida.
@page och @model är exempel på övergång till Razor-specifik markering. Mer Razor information finns i syntaxen .
Direktivet @model
@page
@model RazorPagesMovie.Pages.Movies.IndexModel
Direktivet @model anger vilken typ av modell som skickas till sidan Razor . I föregående exempel gör raden @model den PageModel härledda klassen tillgänglig för sidan Razor. Modellen används i @Html.DisplayNameFor@Html.DisplayFor och på sidan.
Granska lambda-uttrycket som används i följande HTML-hjälp:
@Html.DisplayNameFor(model => model.Movie[0].Title)
DisplayNameFor HTML-hjälpen inspekterar egenskapen Title som refereras i lambda-uttrycket för att fastställa visningsnamnet. Lambda-uttrycket inspekteras i stället för att utvärderas. Det innebär att det inte finns någon åtkomstöverträdelse när model, model.Movieeller model.Movie[0] är null eller är tom. När lambda-uttrycket utvärderas, till exempel med @Html.DisplayFor(modelItem => item.Title), utvärderas modellens egenskapsvärden.
Layoutsidan
Välj menyn länkar RazorPagesMovie, Home, och Privacy. Varje sida visar samma menylayout. Menylayouten implementeras i Pages/Shared/_Layout.cshtml filen.
Öppna och granska Pages/Shared/_Layout.cshtml filen.
Med layoutmallar kan HTML-containerlayouten vara:
- Anges på ett ställe.
- Tillämpas på flera sidor på webbplatsen.
Hitta @RenderBody() raden.
RenderBody är en platsreserv där alla sidspecifika vyer dyker upp, omslutna i layoutsidan. Till exempel, välj Privacy länken och Pages/Privacy.cshtml vyn återges i RenderBody metoden.
ViewData och layout
Överväg följande markering från Pages/Movies/Index.cshtml filen:
@page
@model RazorPagesMovie.Pages.Movies.IndexModel
@{
ViewData["Title"] = "Index";
}
Föregående markerade markering är ett exempel på Razor övergången till C#. Tecknen { och } omger ett block med C#-kod.
Basklassen PageModel innehåller en ViewData ordlisteegenskap som kan användas för att skicka data till en vy. Objekt läggs till i ViewData ordlistan med hjälp av ett nyckelvärdemönster . I föregående exempel läggs egenskapen Title till i ViewData ordlistan.
Egenskapen Title används i Pages/Shared/_Layout.cshtml filen. Följande markering visar de första raderna i _Layout.cshtml filen.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>@ViewData["Title"] - RazorPagesMovie</title>
<link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.min.css" />
<link rel="stylesheet" href="~/css/site.css" asp-append-version="true" />
<link rel="stylesheet" href="~/RazorPagesMovie.styles.css" asp-append-version="true" />
Uppdatera layouten
Ändra elementet
<title>i filen så att detPages/Shared/_Layout.cshtmlvisar film i stället för RazorPagesMovie.<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>@ViewData["Title"] - Movie</title>Hitta följande fästpunktselement i
Pages/Shared/_Layout.cshtmlfilen.<a class="navbar-brand" asp-area="" asp-page="/Index">RazorPagesMovie</a>Ersätt föregående element med följande markering:
<a class="navbar-brand" asp-page="/Movies/Index">RpMovie</a>Föregående fästpunktselement är en Tag Helper. I det här fallet är det Anchor Tag Helper. Attributet
asp-page="/Movies/Index"och värdet för Tag Helper skapar en länk till sidan/Movies/IndexRazor . Attributvärdetasp-areaär tomt, så området används inte i länken. Mer information finns i Områden .Spara ändringarna och testa appen genom att välja länken RpMovie . Se filen _Layout.cshtml i GitHub om du har några problem.
Testa länkarna Home, RpMovie, Create, Edit och Delete . Varje sida anger rubriken, som du kan se på webbläsarfliken. När du bokmärker en sida används rubriken för bokmärket.
Anmärkning
Du kanske inte kan ange decimaltecken i fältet Price. Om du vill stödja jQuery-validering för språkvarianter som inte är engelska och som använder kommatecken (",") för en decimalpunkt och icke-US-English datumformat, måste du vidta åtgärder för att globalisera appen. Titta på det här GitHub-ärende 4076 för instruktioner om hur du lägger till decimaltecken.
Egenskapen Layout anges i Pages/_ViewStart.cshtml filen:
@{
Layout = "_Layout";
}
Föregående markering anger layoutfilen till Pages/Shared/_Layout.cshtml för alla Razor filer under mappen Sidor . Mer information finns i Layout .
Modellen för skapa-sidan
Pages/Movies/Create.cshtml.cs Granska sidmodellen:
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using RazorPagesMovie.Models;
namespace RazorPagesMovie.Pages.Movies
{
public class CreateModel : PageModel
{
private readonly RazorPagesMovie.Data.RazorPagesMovieContext _context;
public CreateModel(RazorPagesMovie.Data.RazorPagesMovieContext context)
{
_context = context;
}
public IActionResult OnGet()
{
return Page();
}
[BindProperty]
public Movie Movie { get; set; } = default!;
// To protect from overposting attacks, see https://aka.ms/RazorPagesCRUD
public async Task<IActionResult> OnPostAsync()
{
if (!ModelState.IsValid || _context.Movie == null || Movie == null)
{
return Page();
}
_context.Movie.Add(Movie);
await _context.SaveChangesAsync();
return RedirectToPage("./Index");
}
}
}
Metoden OnGet initierar alla tillstånd som behövs för sidan. Sidan Skapa har inget tillstånd att initiera, så Page returneras. Senare i självstudien visas ett exempel på initieringstillstånd OnGet . Metoden Page skapar ett PageResult objekt som renderar Create.cshtml sidan.
Egenskapen Movie använder attributet [BindProperty] för att välja modellbindning. När formuläret Skapa publicerar formulärvärdena binder ASP.NET Core-körningen de bokförda värdena till Movie modellen.
Metoden OnPostAsync körs när sidan publicerar formulärdata:
public async Task<IActionResult> OnPostAsync()
{
if (!ModelState.IsValid)
{
return Page();
}
_context.Movie.Add(Movie);
await _context.SaveChangesAsync();
return RedirectToPage("./Index");
}
Om det finns några modellfel spelas formuläret upp på ett annat sätt, tillsammans med eventuella formulärdata som publiceras. De flesta modellfel kan fångas på klientsidan innan formuläret publiceras. Ett exempel på ett modellfel är att publicera ett värde för datumfältet som inte kan konverteras till ett datum. Validering på klientsidan och modellverifiering beskrivs senare i självstudien.
Om det inte finns några modellfel:
- Data sparas.
- Webbläsaren omdirigeras till sidan Index.
Skapa sidan Razor
Pages/Movies/Create.cshtml
Razor Granska sidfilen:
@page
@model RazorPagesMovie.Pages.Movies.CreateModel
@{
ViewData["Title"] = "Create";
}
<h1>Create</h1>
<h4>Movie</h4>
<hr />
<div class="row">
<div class="col-md-4">
<form method="post">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="Movie.Title" class="control-label"></label>
<input asp-for="Movie.Title" class="form-control" />
<span asp-validation-for="Movie.Title" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Movie.ReleaseDate" class="control-label"></label>
<input asp-for="Movie.ReleaseDate" class="form-control" />
<span asp-validation-for="Movie.ReleaseDate" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Movie.Genre" class="control-label"></label>
<input asp-for="Movie.Genre" class="form-control" />
<span asp-validation-for="Movie.Genre" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Movie.Price" class="control-label"></label>
<input asp-for="Movie.Price" class="form-control" />
<span asp-validation-for="Movie.Price" class="text-danger"></span>
</div>
<div class="form-group">
<input type="submit" value="Create" class="btn btn-primary" />
</div>
</form>
</div>
</div>
<div>
<a asp-page="Index">Back to List</a>
</div>
@section Scripts {
@{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}
Visual Studio visar följande taggar i ett distinkt fetstilt teckensnitt som används för Tag Helpers:
<form method="post"><div asp-validation-summary="ModelOnly" class="text-danger"></div><label asp-for="Movie.Title" class="control-label"></label><input asp-for="Movie.Title" class="form-control" /><span asp-validation-for="Movie.Title" class="text-danger"></span>
Elementet <form method="post"> är en formulärtagghjälpare. Formulärtagghjälpen innehåller automatiskt en antiförfalskningstoken.
Byggnadsställningsmotorn skapar Razor markering för varje fält i modellen, förutom ID:t, ungefär så här:
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="Movie.Title" class="control-label"></label>
<input asp-for="Movie.Title" class="form-control" />
<span asp-validation-for="Movie.Title" class="text-danger"></span>
</div>
Valideringstagghjälparna (<div asp-validation-summary och <span asp-validation-for) visar valideringsfel. Valideringen beskrivs mer detaljerat senare i den här serien.
Label Tag Helper (<label asp-for="Movie.Title" class="control-label"></label>) genererar etiketttexten och [for]-attributet för egenskapen Title.
Hjälpverktyget för indatataggen (<input asp-for="Movie.Title" class="form-control">) använder attributen DataAnnotations och skapar HTML-attribut som behövs för jQuery-validering på klientsidan.
Mer information om Tag Helpers, till exempel <form method="post">, finns i Tag Helpers i ASP.NET Core.
Nästa steg
Sidorna Skapa, Ta bort, Detaljer och Redigera
Pages/Movies/Index.cshtml.cs Granska sidmodellen:
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.EntityFrameworkCore;
using RazorPagesMovie.Models;
namespace RazorPagesMovie.Pages.Movies;
public class IndexModel : PageModel
{
private readonly RazorPagesMovie.Data.RazorPagesMovieContext _context;
public IndexModel(RazorPagesMovie.Data.RazorPagesMovieContext context)
{
_context = context;
}
public IList<Movie> Movie { get;set; } = default!;
public async Task OnGetAsync()
{
if (_context.Movie != null)
{
Movie = await _context.Movie.ToListAsync();
}
}
}
Razor Sidor härleds från PageModel. Enligt konventionen heter den härledda klassen `PageModel` `PageNameModel`. Sidan Index heter IndexModeltill exempel .
Konstruktorn använder beroendeinmatning för att lägga RazorPagesMovieContext till på sidan:
public class IndexModel : PageModel
{
private readonly RazorPagesMovie.Data.RazorPagesMovieContext _context;
public IndexModel(RazorPagesMovie.Data.RazorPagesMovieContext context)
{
_context = context;
}
Mer information om asynkron programmering med Entity Framework finns i Asynkron kod .
När en GET begäran görs för sidan OnGetAsync returnerar metoden en lista över filmer till sidan Razor . På en Razor sida, OnGetAsync eller OnGet anropas för att initiera sidans tillstånd. I det här fallet hämtar OnGetAsync en lista över filmer och visar dem.
När OnGet returnerar void eller OnGetAsync returnerar Taskanvänds ingen retursats. Granska till exempel sidan Privacy :
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
namespace RazorPagesMovie.Pages
{
public class PrivacyModel : PageModel
{
private readonly ILogger<PrivacyModel> _logger;
public PrivacyModel(ILogger<PrivacyModel> logger)
{
_logger = logger;
}
public void OnGet()
{
}
}
}
När returtypen är IActionResult eller Task<IActionResult>måste en retursats anges. Till exempel metoden Pages/Movies/Create.cshtml.cs OnPostAsync :
public async Task<IActionResult> OnPostAsync()
{
if (!ModelState.IsValid)
{
return Page();
}
_context.Movie.Add(Movie);
await _context.SaveChangesAsync();
return RedirectToPage("./Index");
}
Granska sidan Pages/Movies/Index.cshtmlRazor :
@page
@model RazorPagesMovie.Pages.Movies.IndexModel
@{
ViewData["Title"] = "Index";
}
<h1>Index</h1>
<p>
<a asp-page="Create">Create New</a>
</p>
<table class="table">
<thead>
<tr>
<th>
@Html.DisplayNameFor(model => model.Movie[0].Title)
</th>
<th>
@Html.DisplayNameFor(model => model.Movie[0].ReleaseDate)
</th>
<th>
@Html.DisplayNameFor(model => model.Movie[0].Genre)
</th>
<th>
@Html.DisplayNameFor(model => model.Movie[0].Price)
</th>
<th></th>
</tr>
</thead>
<tbody>
@foreach (var item in Model.Movie) {
<tr>
<td>
@Html.DisplayFor(modelItem => item.Title)
</td>
<td>
@Html.DisplayFor(modelItem => item.ReleaseDate)
</td>
<td>
@Html.DisplayFor(modelItem => item.Genre)
</td>
<td>
@Html.DisplayFor(modelItem => item.Price)
</td>
<td>
<a asp-page="./Edit" asp-route-id="@item.Id">Edit</a> |
<a asp-page="./Details" asp-route-id="@item.Id">Details</a> |
<a asp-page="./Delete" asp-route-id="@item.Id">Delete</a>
</td>
</tr>
}
</tbody>
</table>
Razor kan övergå från HTML till C# eller till Razor-specifik markering. När en @ symbol följs av ett Razor reserverat nyckelord övergår den till Razor-specifik markering, annars övergår den till C#.
Direktivet @page
Direktivet @pageRazor gör filen till en MVC-åtgärd, vilket innebär att den kan hantera begäranden.
@page måste vara det första Razor direktivet på en sida.
@page och @model är exempel på övergång till Razor-specifik markering. Mer Razor information finns i syntaxen .
Direktivet @model
@page
@model RazorPagesMovie.Pages.Movies.IndexModel
Direktivet @model anger vilken typ av modell som skickas till sidan Razor . I föregående exempel gör raden @model den PageModel härledda klassen tillgänglig för sidan Razor. Modellen används i @Html.DisplayNameFor@Html.DisplayFor och på sidan.
Granska lambda-uttrycket som används i följande HTML-hjälp:
@Html.DisplayNameFor(model => model.Movie[0].Title)
DisplayNameFor HTML-hjälpen inspekterar egenskapen Title som refereras i lambda-uttrycket för att fastställa visningsnamnet. Lambda-uttrycket inspekteras i stället för att utvärderas. Det innebär att det inte finns någon åtkomstöverträdelse när model, model.Movieeller model.Movie[0] är null eller är tom. När lambda-uttrycket utvärderas, till exempel med @Html.DisplayFor(modelItem => item.Title), utvärderas modellens egenskapsvärden.
Layoutsidan
Välj menyn länkar RazorPagesMovie, Home, och Privacy. Varje sida visar samma menylayout. Menylayouten implementeras i Pages/Shared/_Layout.cshtml filen.
Öppna och granska Pages/Shared/_Layout.cshtml filen.
Med layoutmallar kan HTML-containerlayouten vara:
- Anges på ett ställe.
- Tillämpas på flera sidor på webbplatsen.
Hitta @RenderBody() raden.
RenderBody är en platsreserv där alla sidspecifika vyer dyker upp, omslutna i layoutsidan. Till exempel, välj Privacy länken och Pages/Privacy.cshtml vyn återges i RenderBody metoden.
ViewData och layout
Överväg följande markering från Pages/Movies/Index.cshtml filen:
@page
@model RazorPagesMovie.Pages.Movies.IndexModel
@{
ViewData["Title"] = "Index";
}
Föregående markerade markering är ett exempel på Razor övergången till C#. Tecknen { och } omger ett block med C#-kod.
Basklassen PageModel innehåller en ViewData ordlisteegenskap som kan användas för att skicka data till en vy. Objekt läggs till i ViewData ordlistan med hjälp av ett nyckelvärdemönster . I föregående exempel läggs egenskapen Title till i ViewData ordlistan.
Egenskapen Title används i Pages/Shared/_Layout.cshtml filen. Följande markering visar de första raderna i _Layout.cshtml filen.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>@ViewData["Title"] - RazorPagesMovie</title>
<link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.min.css" />
<link rel="stylesheet" href="~/css/site.css" asp-append-version="true" />
<link rel="stylesheet" href="~/RazorPagesMovie.styles.css" asp-append-version="true" />
Raden @*Markup removed for brevity.*@ är en Razor kommentar. Till skillnad från HTML-kommentarer <!-- -->Razor skickas inte kommentarer till klienten. Mer information finns i MDN-webbdokument: Komma igång med HTML .
Uppdatera layouten
Ändra elementet
<title>i filen så att detPages/Shared/_Layout.cshtmlvisar film i stället för RazorPagesMovie.<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>@ViewData["Title"] - Movie</title>Hitta följande fästpunktselement i
Pages/Shared/_Layout.cshtmlfilen.<a class="navbar-brand" asp-area="" asp-page="/Index">RazorPagesMovie</a>Ersätt föregående element med följande markering:
<a class="navbar-brand" asp-page="/Movies/Index">RpMovie</a>Föregående fästpunktselement är en Tag Helper. I det här fallet är det Anchor Tag Helper. Attributet
asp-page="/Movies/Index"och värdet för Tag Helper skapar en länk till sidan/Movies/IndexRazor . Attributvärdetasp-areaär tomt, så området används inte i länken. Mer information finns i Områden .Spara ändringarna och testa appen genom att välja länken RpMovie . Se filen _Layout.cshtml i GitHub om du har några problem.
Testa länkarna Home, RpMovie, Create, Edit och Delete . Varje sida anger rubriken, som du kan se på webbläsarfliken. När du bokmärker en sida används rubriken för bokmärket.
Anmärkning
Du kanske inte kan ange decimaltecken i fältet Price. Om du vill stödja jQuery-validering för språkvarianter som inte är engelska och som använder kommatecken (",") för en decimalpunkt och icke-US-English datumformat, måste du vidta åtgärder för att globalisera appen. Titta på det här GitHub-ärende 4076 för instruktioner om hur du lägger till decimaltecken.
Egenskapen Layout anges i Pages/_ViewStart.cshtml filen:
@{
Layout = "_Layout";
}
Föregående markering anger layoutfilen till Pages/Shared/_Layout.cshtml för alla Razor filer under mappen Sidor . Mer information finns i Layout .
Modellen för skapa-sidan
Pages/Movies/Create.cshtml.cs Granska sidmodellen:
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using RazorPagesMovie.Models;
namespace RazorPagesMovie.Pages.Movies
{
public class CreateModel : PageModel
{
private readonly RazorPagesMovie.Data.RazorPagesMovieContext _context;
public CreateModel(RazorPagesMovie.Data.RazorPagesMovieContext context)
{
_context = context;
}
public IActionResult OnGet()
{
return Page();
}
[BindProperty]
public Movie Movie { get; set; } = default!;
// To protect from overposting attacks, see https://aka.ms/RazorPagesCRUD
public async Task<IActionResult> OnPostAsync()
{
if (!ModelState.IsValid || _context.Movie == null || Movie == null)
{
return Page();
}
_context.Movie.Add(Movie);
await _context.SaveChangesAsync();
return RedirectToPage("./Index");
}
}
}
Metoden OnGet initierar alla tillstånd som behövs för sidan. Sidan Skapa har inget tillstånd att initiera, så Page returneras. Senare i självstudien visas ett exempel på initieringstillstånd OnGet . Metoden Page skapar ett PageResult objekt som renderar Create.cshtml sidan.
Egenskapen Movie använder attributet [BindProperty] för att välja modellbindning. När formuläret Skapa publicerar formulärvärdena binder ASP.NET Core-körningen de bokförda värdena till Movie modellen.
Metoden OnPostAsync körs när sidan publicerar formulärdata:
public async Task<IActionResult> OnPostAsync()
{
if (!ModelState.IsValid)
{
return Page();
}
_context.Movie.Add(Movie);
await _context.SaveChangesAsync();
return RedirectToPage("./Index");
}
Om det finns några modellfel spelas formuläret upp på ett annat sätt, tillsammans med eventuella formulärdata som publiceras. De flesta modellfel kan fångas på klientsidan innan formuläret publiceras. Ett exempel på ett modellfel är att publicera ett värde för datumfältet som inte kan konverteras till ett datum. Validering på klientsidan och modellverifiering beskrivs senare i självstudien.
Om det inte finns några modellfel:
- Data sparas.
- Webbläsaren omdirigeras till sidan Index.
Skapa sidan Razor
Pages/Movies/Create.cshtml
Razor Granska sidfilen:
@page
@model RazorPagesMovie.Pages.Movies.CreateModel
@{
ViewData["Title"] = "Create";
}
<h1>Create</h1>
<h4>Movie</h4>
<hr />
<div class="row">
<div class="col-md-4">
<form method="post">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="Movie.Title" class="control-label"></label>
<input asp-for="Movie.Title" class="form-control" />
<span asp-validation-for="Movie.Title" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Movie.ReleaseDate" class="control-label"></label>
<input asp-for="Movie.ReleaseDate" class="form-control" />
<span asp-validation-for="Movie.ReleaseDate" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Movie.Genre" class="control-label"></label>
<input asp-for="Movie.Genre" class="form-control" />
<span asp-validation-for="Movie.Genre" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Movie.Price" class="control-label"></label>
<input asp-for="Movie.Price" class="form-control" />
<span asp-validation-for="Movie.Price" class="text-danger"></span>
</div>
<div class="form-group">
<input type="submit" value="Create" class="btn btn-primary" />
</div>
</form>
</div>
</div>
<div>
<a asp-page="Index">Back to List</a>
</div>
@section Scripts {
@{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}
Visual Studio visar följande taggar i ett distinkt fetstilt teckensnitt som används för Tag Helpers:
<form method="post"><div asp-validation-summary="ModelOnly" class="text-danger"></div><label asp-for="Movie.Title" class="control-label"></label><input asp-for="Movie.Title" class="form-control" /><span asp-validation-for="Movie.Title" class="text-danger"></span>
Elementet <form method="post"> är en formulärtagghjälpare. Formulärtagghjälpen innehåller automatiskt en antiförfalskningstoken.
Byggnadsställningsmotorn skapar Razor markering för varje fält i modellen, förutom ID:t, ungefär så här:
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="Movie.Title" class="control-label"></label>
<input asp-for="Movie.Title" class="form-control" />
<span asp-validation-for="Movie.Title" class="text-danger"></span>
</div>
Valideringstagghjälparna (<div asp-validation-summary och <span asp-validation-for) visar valideringsfel. Valideringen beskrivs mer detaljerat senare i den här serien.
Label Tag Helper (<label asp-for="Movie.Title" class="control-label"></label>) genererar etiketttexten och [for]-attributet för egenskapen Title.
Hjälpverktyget för indatataggen (<input asp-for="Movie.Title" class="form-control">) använder attributen DataAnnotations och skapar HTML-attribut som behövs för jQuery-validering på klientsidan.
Mer information om Tag Helpers, till exempel <form method="post">, finns i Tag Helpers i ASP.NET Core.
Nästa steg
Sidorna Skapa, Ta bort, Detaljer och Redigera
Pages/Movies/Index.cshtml.cs Granska sidmodellen:
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.EntityFrameworkCore;
using RazorPagesMovie.Models;
namespace RazorPagesMovie.Pages.Movies
{
public class IndexModel : PageModel
{
private readonly RazorPagesMovie.Data.RazorPagesMovieContext _context;
public IndexModel(RazorPagesMovie.Data.RazorPagesMovieContext context)
{
_context = context;
}
public IList<Movie> Movie { get;set; } = default!;
public async Task OnGetAsync()
{
if (_context.Movie != null)
{
Movie = await _context.Movie.ToListAsync();
}
}
}
}
Razor Sidor härleds från PageModel. Enligt konventionen heter den härledda klassen `PageModel` `PageNameModel`. Sidan Index heter IndexModeltill exempel .
Konstruktorn använder beroendeinmatning för att lägga RazorPagesMovieContext till på sidan:
public class IndexModel : PageModel
{
private readonly RazorPagesMovie.Data.RazorPagesMovieContext _context;
public IndexModel(RazorPagesMovie.Data.RazorPagesMovieContext context)
{
_context = context;
}
Mer information om asynkron programmering med Entity Framework finns i Asynkron kod .
När en begäran görs för sidan OnGetAsync returnerar metoden en lista över filmer till sidan Razor . På en Razor sida, OnGetAsync eller OnGet anropas för att initiera sidans tillstånd. I det här fallet hämtar OnGetAsync en lista över filmer och visar dem.
När OnGet returnerar void eller OnGetAsync returnerar Taskanvänds ingen retursats. Granska till exempel sidan Privacy :
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
namespace RazorPagesMovie.Pages
{
public class PrivacyModel : PageModel
{
private readonly ILogger<PrivacyModel> _logger;
public PrivacyModel(ILogger<PrivacyModel> logger)
{
_logger = logger;
}
public void OnGet()
{
}
}
}
När returtypen är IActionResult eller Task<IActionResult>måste en retursats anges. Till exempel metoden Pages/Movies/Create.cshtml.csOnPostAsync :
public async Task<IActionResult> OnPostAsync()
{
if (!ModelState.IsValid || _context.Movie == null || Movie == null)
{
return Page();
}
_context.Movie.Add(Movie);
await _context.SaveChangesAsync();
return RedirectToPage("./Index");
}
Granska sidan Pages/Movies/Index.cshtmlRazor :
@page
@model RazorPagesMovie.Pages.Movies.IndexModel
@{
ViewData["Title"] = "Index";
}
<h1>Index</h1>
<p>
<a asp-page="Create">Create New</a>
</p>
<table class="table">
<thead>
<tr>
<th>
@Html.DisplayNameFor(model => model.Movie[0].Title)
</th>
<th>
@Html.DisplayNameFor(model => model.Movie[0].ReleaseDate)
</th>
<th>
@Html.DisplayNameFor(model => model.Movie[0].Genre)
</th>
<th>
@Html.DisplayNameFor(model => model.Movie[0].Price)
</th>
<th></th>
</tr>
</thead>
<tbody>
@foreach (var item in Model.Movie) {
<tr>
<td>
@Html.DisplayFor(modelItem => item.Title)
</td>
<td>
@Html.DisplayFor(modelItem => item.ReleaseDate)
</td>
<td>
@Html.DisplayFor(modelItem => item.Genre)
</td>
<td>
@Html.DisplayFor(modelItem => item.Price)
</td>
<td>
<a asp-page="./Edit" asp-route-id="@item.ID">Edit</a> |
<a asp-page="./Details" asp-route-id="@item.ID">Details</a> |
<a asp-page="./Delete" asp-route-id="@item.ID">Delete</a>
</td>
</tr>
}
</tbody>
</table>
Razor kan övergå från HTML till C# eller till Razor-specifik markering. När en @ symbol följs av ett Razor reserverat nyckelord övergår den till Razor-specifik markering, annars övergår den till C#.
Direktivet @page
Direktivet @pageRazor gör filen till en MVC-åtgärd, vilket innebär att den kan hantera begäranden.
@page måste vara det första Razor direktivet på en sida.
@page och @model är exempel på övergång till Razor-specifik markering. Mer Razor information finns i syntaxen .
Direktivet @model
@page
@model RazorPagesMovie.Pages.Movies.IndexModel
Direktivet @model anger vilken typ av modell som skickas till sidan Razor . I föregående exempel gör raden @model den PageModel härledda klassen tillgänglig för sidan Razor. Modellen används i @Html.DisplayNameFor@Html.DisplayFor och på sidan.
Granska lambda-uttrycket som används i följande HTML-hjälp:
@Html.DisplayNameFor(model => model.Movie[0].Title)
DisplayNameFor HTML-hjälpen inspekterar egenskapen Title som refereras i lambda-uttrycket för att fastställa visningsnamnet. Lambda-uttrycket inspekteras i stället för att utvärderas. Det innebär att det inte finns någon åtkomstöverträdelse när model, model.Movieeller model.Movie[0] är null eller är tom. När lambda-uttrycket utvärderas, till exempel med @Html.DisplayFor(modelItem => item.Title), utvärderas modellens egenskapsvärden.
Layoutsidan
Välj menyn länkar RazorPagesMovie, Home, och Privacy. Varje sida visar samma menylayout. Menylayouten implementeras i Pages/Shared/_Layout.cshtml filen.
Öppna och granska Pages/Shared/_Layout.cshtml filen.
Med layoutmallar kan HTML-containerlayouten vara:
- Anges på ett ställe.
- Tillämpas på flera sidor på webbplatsen.
Hitta @RenderBody() raden.
RenderBody är en platsreserv där alla sidspecifika vyer dyker upp, omslutna i layoutsidan. Till exempel, välj Privacy länken och Pages/Privacy.cshtml vyn återges i RenderBody metoden.
ViewData och layout
Överväg följande markering från Pages/Movies/Index.cshtml filen:
@page
@model RazorPagesMovie.Pages.Movies.IndexModel
@{
ViewData["Title"] = "Index";
}
Föregående markerade markering är ett exempel på Razor övergången till C#. Tecknen { och } omger ett block med C#-kod.
Basklassen PageModel innehåller en ViewData ordlisteegenskap som kan användas för att skicka data till en vy. Objekt läggs till i ViewData ordlistan med hjälp av ett nyckelvärdemönster . I föregående exempel läggs egenskapen Title till i ViewData ordlistan.
Egenskapen Title används i Pages/Shared/_Layout.cshtml filen. Följande markering visar de första raderna i _Layout.cshtml filen.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>@ViewData["Title"] - RazorPagesMovie</title>
@*Markup removed for brevity.*@
<link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.css" />
Raden @*Markup removed for brevity.*@ är en Razor kommentar. Till skillnad från HTML-kommentarer <!-- -->Razor skickas inte kommentarer till klienten. Mer information finns i MDN-webbdokument: Komma igång med HTML .
Uppdatera layouten
Ändra elementet
<title>i filen så att detPages/Shared/_Layout.cshtmlvisar film i stället för RazorPagesMovie.<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>@ViewData["Title"] - Movie</title>Hitta följande fästpunktselement i
Pages/Shared/_Layout.cshtmlfilen.<a class="navbar-brand" asp-area="" asp-page="/Index">RazorPagesMovie</a>Ersätt föregående element med följande markering:
<a class="navbar-brand" asp-page="/Movies/Index">RpMovie</a>Föregående fästpunktselement är en Tag Helper. I det här fallet är det Anchor Tag Helper. Attributet
asp-page="/Movies/Index"och värdet för Tag Helper skapar en länk till sidan/Movies/IndexRazor . Attributvärdetasp-areaär tomt, så området används inte i länken. Mer information finns i Områden .Spara ändringarna och testa appen genom att välja länken RpMovie . Se filen _Layout.cshtml i GitHub om du har några problem.
Testa länkarna Home, RpMovie, Create, Edit och Delete . Varje sida anger rubriken, som du kan se på webbläsarfliken. När du bokmärker en sida används rubriken för bokmärket.
Anmärkning
Du kanske inte kan ange decimaltecken i fältet Price. Om du vill stödja jQuery-validering för språkvarianter som inte är engelska och som använder kommatecken (",") för en decimalpunkt och icke-US-English datumformat, måste du vidta åtgärder för att globalisera appen. Titta på det här GitHub-ärende 4076 för instruktioner om hur du lägger till decimaltecken.
Egenskapen Layout anges i Pages/_ViewStart.cshtml filen:
@{
Layout = "_Layout";
}
Föregående markering anger layoutfilen till Pages/Shared/_Layout.cshtml för alla Razor filer under mappen Sidor . Mer information finns i Layout .
Modellen för skapa-sidan
Pages/Movies/Create.cshtml.cs Granska sidmodellen:
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using RazorPagesMovie.Models;
namespace RazorPagesMovie.Pages.Movies
{
public class CreateModel : PageModel
{
private readonly RazorPagesMovie.Data.RazorPagesMovieContext _context;
public CreateModel(RazorPagesMovie.Data.RazorPagesMovieContext context)
{
_context = context;
}
public IActionResult OnGet()
{
return Page();
}
[BindProperty]
public Movie Movie { get; set; } = default!;
// To protect from overposting attacks, see https://aka.ms/RazorPagesCRUD
public async Task<IActionResult> OnPostAsync()
{
if (!ModelState.IsValid || _context.Movie == null || Movie == null)
{
return Page();
}
_context.Movie.Add(Movie);
await _context.SaveChangesAsync();
return RedirectToPage("./Index");
}
}
}
Metoden OnGet initierar alla tillstånd som behövs för sidan. Sidan Skapa har inget tillstånd att initiera, så Page returneras. Senare i självstudien visas ett exempel på initieringstillstånd OnGet . Metoden Page skapar ett PageResult objekt som renderar Create.cshtml sidan.
Egenskapen Movie använder attributet [BindProperty] för att välja modellbindning. När formuläret Skapa publicerar formulärvärdena binder ASP.NET Core-körningen de bokförda värdena till Movie modellen.
Metoden OnPostAsync körs när sidan publicerar formulärdata:
public async Task<IActionResult> OnPostAsync()
{
if (!ModelState.IsValid || _context.Movie == null || Movie == null)
{
return Page();
}
_context.Movie.Add(Movie);
await _context.SaveChangesAsync();
return RedirectToPage("./Index");
}
Om det finns några modellfel spelas formuläret upp på ett annat sätt, tillsammans med eventuella formulärdata som publiceras. De flesta modellfel kan fångas på klientsidan innan formuläret publiceras. Ett exempel på ett modellfel är att publicera ett värde för datumfältet som inte kan konverteras till ett datum. Validering på klientsidan och modellverifiering beskrivs senare i självstudien.
Om det inte finns några modellfel:
- Data sparas.
- Webbläsaren omdirigeras till sidan Index.
Skapa sidan Razor
Pages/Movies/Create.cshtml
Razor Granska sidfilen:
@page
@model RazorPagesMovie.Pages.Movies.CreateModel
@{
ViewData["Title"] = "Create";
}
<h1>Create</h1>
<h4>Movie</h4>
<hr />
<div class="row">
<div class="col-md-4">
<form method="post">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="Movie.Title" class="control-label"></label>
<input asp-for="Movie.Title" class="form-control" />
<span asp-validation-for="Movie.Title" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Movie.ReleaseDate" class="control-label"></label>
<input asp-for="Movie.ReleaseDate" class="form-control" />
<span asp-validation-for="Movie.ReleaseDate" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Movie.Genre" class="control-label"></label>
<input asp-for="Movie.Genre" class="form-control" />
<span asp-validation-for="Movie.Genre" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Movie.Price" class="control-label"></label>
<input asp-for="Movie.Price" class="form-control" />
<span asp-validation-for="Movie.Price" class="text-danger"></span>
</div>
<div class="form-group">
<input type="submit" value="Create" class="btn btn-primary" />
</div>
</form>
</div>
</div>
<div>
<a asp-page="Index">Back to List</a>
</div>
@section Scripts {
@{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}
Visual Studio visar följande taggar i ett distinkt fetstilt teckensnitt som används för Tag Helpers:
<form method="post"><div asp-validation-summary="ModelOnly" class="text-danger"></div><label asp-for="Movie.Title" class="control-label"></label><input asp-for="Movie.Title" class="form-control" /><span asp-validation-for="Movie.Title" class="text-danger"></span>
Elementet <form method="post"> är en formulärtagghjälpare. Formulärtagghjälpen innehåller automatiskt en antiförfalskningstoken.
Byggnadsställningsmotorn skapar Razor markering för varje fält i modellen, förutom ID:t, ungefär så här:
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="Movie.Title" class="control-label"></label>
<input asp-for="Movie.Title" class="form-control" />
<span asp-validation-for="Movie.Title" class="text-danger"></span>
</div>
Valideringstagghjälparna (<div asp-validation-summary och <span asp-validation-for) visar valideringsfel. Valideringen beskrivs mer detaljerat senare i den här serien.
Label Tag Helper (<label asp-for="Movie.Title" class="control-label"></label>) genererar etiketttexten och [for]-attributet för egenskapen Title.
Hjälpverktyget för indatataggen (<input asp-for="Movie.Title" class="form-control">) använder attributen DataAnnotations och skapar HTML-attribut som behövs för jQuery-validering på klientsidan.
Mer information om Tag Helpers, till exempel <form method="post">, finns i Tag Helpers i ASP.NET Core.
Nästa steg
Sidorna Skapa, Ta bort, Detaljer och Redigera
Pages/Movies/Index.cshtml.cs Granska sidmodellen:
// Unused usings removed.
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.EntityFrameworkCore;
using RazorPagesMovie.Models;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace RazorPagesMovie.Pages.Movies
{
public class IndexModel : PageModel
{
private readonly RazorPagesMovie.Data.RazorPagesMovieContext _context;
public IndexModel(RazorPagesMovie.Data.RazorPagesMovieContext context)
{
_context = context;
}
public IList<Movie> Movie { get;set; }
public async Task OnGetAsync()
{
Movie = await _context.Movie.ToListAsync();
}
}
}
Razor Sidor härleds från PageModel. Enligt konvention kallas PageModel-derived-klassen <PageName>Model. Konstruktorn använder beroendeinmatning för att lägga RazorPagesMovieContext till på sidan:
public class IndexModel : PageModel
{
private readonly RazorPagesMovie.Data.RazorPagesMovieContext _context;
public IndexModel(RazorPagesMovie.Data.RazorPagesMovieContext context)
{
_context = context;
}
Mer information om asynkron programmering med Entity Framework finns i Asynkron kod .
När en begäran görs för sidan OnGetAsync returnerar metoden en lista över filmer till sidan Razor . På en Razor sida, OnGetAsync eller OnGet anropas för att initiera sidans tillstånd. I det här fallet hämtar OnGetAsync en lista över filmer och visar dem.
När OnGet returnerar void eller OnGetAsync returnerar Taskanvänds ingen retursats. Till exempel sidan Privacy :
public class PrivacyModel : PageModel
{
private readonly ILogger<PrivacyModel> _logger;
public PrivacyModel(ILogger<PrivacyModel> logger)
{
_logger = logger;
}
public void OnGet()
{
}
}
När returtypen är IActionResult eller Task<IActionResult>måste en retursats anges. Till exempel metoden Pages/Movies/Create.cshtml.csOnPostAsync :
public async Task<IActionResult> OnPostAsync()
{
if (!ModelState.IsValid)
{
return Page();
}
_context.Movie.Add(Movie);
await _context.SaveChangesAsync();
return RedirectToPage("./Index");
}
}
Granska sidan Pages/Movies/Index.cshtmlRazor :
@page
@model RazorPagesMovie.Pages.Movies.IndexModel
@{
ViewData["Title"] = "Index";
}
<h1>Index</h1>
<p>
<a asp-page="Create">Create New</a>
</p>
<table class="table">
<thead>
<tr>
<th>
@Html.DisplayNameFor(model => model.Movie[0].Title)
</th>
<th>
@Html.DisplayNameFor(model => model.Movie[0].ReleaseDate)
</th>
<th>
@Html.DisplayNameFor(model => model.Movie[0].Genre)
</th>
<th>
@Html.DisplayNameFor(model => model.Movie[0].Price)
</th>
<th></th>
</tr>
</thead>
<tbody>
@foreach (var item in Model.Movie) {
<tr>
<td>
@Html.DisplayFor(modelItem => item.Title)
</td>
<td>
@Html.DisplayFor(modelItem => item.ReleaseDate)
</td>
<td>
@Html.DisplayFor(modelItem => item.Genre)
</td>
<td>
@Html.DisplayFor(modelItem => item.Price)
</td>
<td>
<a asp-page="./Edit" asp-route-id="@item.ID">Edit</a> |
<a asp-page="./Details" asp-route-id="@item.ID">Details</a> |
<a asp-page="./Delete" asp-route-id="@item.ID">Delete</a>
</td>
</tr>
}
</tbody>
</table>
Razor kan övergå från HTML till C# eller till Razor-specifik markering. När en @ symbol följs av ett Razor reserverat nyckelord övergår den till Razor-specifik markering, annars övergår den till C#.
Direktivet @page
Direktivet @pageRazor gör filen till en MVC-åtgärd, vilket innebär att den kan hantera begäranden.
@page måste vara det första Razor direktivet på en sida.
@page och @model är exempel på övergång till Razor-specifik markering. Mer Razor information finns i syntaxen .
Direktivet @model
@page
@model RazorPagesMovie.Pages.Movies.IndexModel
Direktivet @model anger vilken typ av modell som skickas till sidan Razor . I föregående exempel gör raden @model den av PageModel-härledda klassen tillgänglig för Razor-sidan. Modellen används i @Html.DisplayNameFor@Html.DisplayFor och på sidan.
Granska lambda-uttrycket som används i följande HTML-hjälp:
@Html.DisplayNameFor(model => model.Movie[0].Title)
DisplayNameFor HTML-hjälpen inspekterar egenskapen Title som refereras i lambda-uttrycket för att fastställa visningsnamnet. Lambda-uttrycket inspekteras i stället för att utvärderas. Det innebär att det inte finns någon åtkomstöverträdelse när model, model.Movieeller model.Movie[0] är null eller är tom. När lambda-uttrycket utvärderas, till exempel med @Html.DisplayFor(modelItem => item.Title), utvärderas modellens egenskapsvärden.
Layoutsidan
Välj menyn länkar RazorPagesMovie, Home, och Privacy. Varje sida visar samma menylayout. Menylayouten implementeras i Pages/Shared/_Layout.cshtml filen.
Öppna och granska Pages/Shared/_Layout.cshtml filen.
Med layoutmallar kan HTML-containerlayouten vara:
- Anges på ett ställe.
- Tillämpas på flera sidor på webbplatsen.
Hitta @RenderBody() raden.
RenderBody är en platsreserv där alla sidspecifika vyer dyker upp, omslutna i layoutsidan. Till exempel, välj Privacy länken och Pages/Privacy.cshtml vyn återges i RenderBody metoden.
ViewData och layout
Överväg följande markering från Pages/Movies/Index.cshtml filen:
@page
@model RazorPagesMovie.Pages.Movies.IndexModel
@{
ViewData["Title"] = "Index";
}
Föregående markerade markering är ett exempel på Razor övergången till C#. Tecknen { och } omger ett block med C#-kod.
Basklassen PageModel innehåller en ViewData ordlisteegenskap som kan användas för att skicka data till en vy. Objekt läggs till i ViewData ordlistan med hjälp av ett nyckelvärdemönster . I föregående exempel läggs egenskapen Title till i ViewData ordlistan.
Egenskapen Title används i Pages/Shared/_Layout.cshtml filen. Följande markering visar de första raderna i _Layout.cshtml filen.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>@ViewData["Title"] - RazorPagesMovie</title>
@*Markup removed for brevity.*@
Raden @*Markup removed for brevity.*@ är en Razor kommentar. Till skillnad från HTML-kommentarer <!-- -->Razor skickas inte kommentarer till klienten. Mer information finns i MDN-webbdokument: Komma igång med HTML .
Uppdatera layouten
Ändra elementet
<title>i filen så att detPages/Shared/_Layout.cshtmlvisar film i stället för RazorPagesMovie.<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>@ViewData["Title"] - Movie</title>Hitta följande fästpunktselement i
Pages/Shared/_Layout.cshtmlfilen.<a class="navbar-brand" asp-area="" asp-page="/Index">RazorPagesMovie</a>Ersätt föregående element med följande markering:
<a class="navbar-brand" asp-page="/Movies/Index">RpMovie</a>Föregående fästpunktselement är en Tag Helper. I det här fallet är det Anchor Tag Helper. Attributet
asp-page="/Movies/Index"och värdet för Tag Helper skapar en länk till sidan/Movies/IndexRazor . Attributvärdetasp-areaär tomt, så området används inte i länken. Mer information finns i Områden .Spara ändringarna och testa appen genom att välja länken RpMovie . Se filen _Layout.cshtml i GitHub om du har några problem.
Testa länkarna Home, RpMovie, Create, Edit och Delete . Varje sida anger rubriken, som du kan se på webbläsarfliken. När du bokmärker en sida används rubriken för bokmärket.
Anmärkning
Du kanske inte kan ange decimaltecken i fältet Price. Om du vill stödja jQuery-validering för språkvarianter som inte är engelska och som använder kommatecken (",") för en decimalpunkt och icke-US-English datumformat, måste du vidta åtgärder för att globalisera appen. Titta på det här GitHub-ärende 4076 för instruktioner om hur du lägger till decimaltecken.
Egenskapen Layout anges i Pages/_ViewStart.cshtml filen:
@{
Layout = "_Layout";
}
Föregående markering anger layoutfilen till Pages/Shared/_Layout.cshtml för alla Razor filer under mappen Sidor . Mer information finns i Layout .
Modellen för skapa-sidan
Pages/Movies/Create.cshtml.cs Granska sidmodellen:
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using RazorPagesMovie.Models;
using System;
using System.Threading.Tasks;
namespace RazorPagesMovie.Pages.Movies
{
public class CreateModel : PageModel
{
private readonly RazorPagesMovie.Data.RazorPagesMovieContext _context;
public CreateModel(RazorPagesMovie.Data.RazorPagesMovieContext context)
{
_context = context;
}
public IActionResult OnGet()
{
return Page();
}
[BindProperty]
public Movie Movie { get; set; }
public async Task<IActionResult> OnPostAsync()
{
if (!ModelState.IsValid)
{
return Page();
}
_context.Movie.Add(Movie);
await _context.SaveChangesAsync();
return RedirectToPage("./Index");
}
}
}
Metoden OnGet initierar alla tillstånd som behövs för sidan. Sidan Skapa har inget tillstånd att initiera, så Page returneras. Senare i självstudien visas ett exempel på initieringstillstånd OnGet . Metoden Page skapar ett PageResult objekt som renderar Create.cshtml sidan.
Egenskapen Movie använder attributet [BindProperty] för att välja modellbindning. När formuläret Skapa publicerar formulärvärdena binder ASP.NET Core-körningen de bokförda värdena till Movie modellen.
Metoden OnPostAsync körs när sidan publicerar formulärdata:
public async Task<IActionResult> OnPostAsync()
{
if (!ModelState.IsValid)
{
return Page();
}
_context.Movie.Add(Movie);
await _context.SaveChangesAsync();
return RedirectToPage("./Index");
}
Om det finns några modellfel spelas formuläret upp på ett annat sätt, tillsammans med eventuella formulärdata som publiceras. De flesta modellfel kan fångas på klientsidan innan formuläret publiceras. Ett exempel på ett modellfel är att publicera ett värde för datumfältet som inte kan konverteras till ett datum. Validering på klientsidan och modellverifiering beskrivs senare i självstudien.
Om det inte finns några modellfel:
- Data sparas.
- Webbläsaren omdirigeras till sidan Index.
Skapa sidan Razor
Pages/Movies/Create.cshtml
Razor Granska sidfilen:
@page
@model RazorPagesMovie.Pages.Movies.CreateModel
@{
ViewData["Title"] = "Create";
}
<h1>Create</h1>
<h4>Movie</h4>
<hr />
<div class="row">
<div class="col-md-4">
<form method="post">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="Movie.Title" class="control-label"></label>
<input asp-for="Movie.Title" class="form-control" />
<span asp-validation-for="Movie.Title" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Movie.ReleaseDate" class="control-label"></label>
<input asp-for="Movie.ReleaseDate" class="form-control" />
<span asp-validation-for="Movie.ReleaseDate" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Movie.Genre" class="control-label"></label>
<input asp-for="Movie.Genre" class="form-control" />
<span asp-validation-for="Movie.Genre" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Movie.Price" class="control-label"></label>
<input asp-for="Movie.Price" class="form-control" />
<span asp-validation-for="Movie.Price" class="text-danger"></span>
</div>
<div class="form-group">
<input type="submit" value="Create" class="btn btn-primary" />
</div>
</form>
</div>
</div>
<div>
<a asp-page="Index">Back to List</a>
</div>
@section Scripts {
@{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}
Visual Studio visar följande taggar i ett distinkt fetstilt teckensnitt som används för Tag Helpers:
<form method="post"><div asp-validation-summary="ModelOnly" class="text-danger"></div><label asp-for="Movie.Title" class="control-label"></label><input asp-for="Movie.Title" class="form-control" /><span asp-validation-for="Movie.Title" class="text-danger"></span>
Elementet <form method="post"> är en formulärtagghjälpare. Formulärtagghjälpen innehåller automatiskt en antiförfalskningstoken.
Byggnadsställningsmotorn skapar Razor markering för varje fält i modellen, förutom ID:t, ungefär så här:
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="Movie.Title" class="control-label"></label>
<input asp-for="Movie.Title" class="form-control" />
<span asp-validation-for="Movie.Title" class="text-danger"></span>
</div>
Valideringstagghjälparna (<div asp-validation-summary och <span asp-validation-for) visar valideringsfel. Valideringen beskrivs mer detaljerat senare i den här serien.
Label Tag Helper (<label asp-for="Movie.Title" class="control-label"></label>) genererar etiketttexten och [for]-attributet för egenskapen Title.
Hjälpverktyget för indatataggen (<input asp-for="Movie.Title" class="form-control">) använder attributen DataAnnotations och skapar HTML-attribut som behövs för jQuery-validering på klientsidan.
Mer information om Tag Helpers, till exempel <form method="post">, finns i Tag Helpers i ASP.NET Core.
Nästa steg
ASP.NET Core