Úvod do Razor stránek v ASP.NET Core
Autor: Rick Anderson, Dave Brock a Kirk Larkin
Razor Stránky můžou usnadnit a zvýšit produktivitu scénářů zaměřených na kódování stránek než používání kontrolerů a zobrazení.
Pokud hledáte kurz, který používá přístup Model-View-Controller, podívejte se na Začínáme s ASP.NET Core MVC.
Tento dokument obsahuje úvod do Razor stránek. Nejedná se o podrobný kurz. Pokud najdete některé oddíly příliš pokročilé, podívejte se na Začínáme se stránkamiRazor. Přehled ASP.NET Core najdete v tématu Úvod do ASP.NET Core.
Požadavky
- Visual Studio 2022 s úlohou vývoje pro ASP.NET a web.
Razor Vytvoření projektu Stránky
Podrobné pokyny k vytvoření Razor projektu Pages najdete v Začínáme se stránkamiRazor.
Razor Stránky
Razor Stránky jsou povoleny v Program.cs
:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages();
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthorization();
app.MapRazorPages();
app.Run();
V předchozím kódu:
- AddRazorPages přidá do aplikace služby Razor Pages.
- MapRazorPages přidá koncové body pro Razor stránky do souboru IEndpointRouteBuilder.
@page
<h1>Hello, world!</h1>
<h2>The time on the server is @DateTime.Now</h2>
Předchozí kód vypadá hodně jako Razor soubor zobrazení používaný v aplikaci ASP.NET Core s kontrolery a zobrazeními. Čím se direktiva @page
liší. @page
vytvoří soubor do akce MVC, což znamená, že zpracovává požadavky přímo, aniž by procházel kontrolerem. @page
musí být první Razor direktivou na stránce. @page
ovlivňuje chování jiných Razor konstruktorů. Razor Názvy souborů stránek mají příponu .cshtml
.
Podobná stránka, která používá PageModel
třídu, je zobrazena v následujících dvou souborech. Soubor Pages/Index2.cshtml
:
@page
@using RazorPagesIntro.Pages
@model Index2Model
<h2>Separate page model</h2>
<p>
@Model.Message
</p>
Model Pages/Index2.cshtml.cs
stránky:
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.Extensions.Logging;
using System;
namespace RazorPagesIntro.Pages
{
public class Index2Model : PageModel
{
public string Message { get; private set; } = "PageModel in C#";
public void OnGet()
{
Message += $" Server time is { DateTime.Now }";
}
}
}
Podle konvence PageModel
má soubor třídy stejný název jako Razor stránkovací soubor s připojeným .cs
. Například předchozí Razor stránka je Pages/Index2.cshtml
. Soubor obsahující PageModel
třídu má název Pages/Index2.cshtml.cs
.
Přidružení cest URL na stránky jsou určena umístěním stránky v systému souborů. Následující tabulka ukazuje Razor cestu stránky a odpovídající adresu URL:
Název souboru a cesta | odpovídající adresa URL |
---|---|
/Pages/Index.cshtml |
/ nebo /Index |
/Pages/Contact.cshtml |
/Contact |
/Pages/Store/Contact.cshtml |
/Store/Contact |
/Pages/Store/Index.cshtml |
/Store nebo /Store/Index |
Poznámky:
- Modul runtime ve výchozím nastavení hledá Razor soubory Pages ve složce Pages .
Index
je výchozí stránka, pokud adresa URL neobsahuje stránku.
Zápis základního formuláře
Razor Stránky jsou navržené tak, aby se při vytváření aplikace snadno implementovaly běžné vzory používané ve webových prohlížečích. Vazby modelu, pomocné rutiny značek a pomocné rutiny HTML pracují s vlastnostmi definovanými ve Razor třídě Page. Zvažte stránku, která implementuje základní formulář Contact
"kontaktujte nás":
Pro ukázky v tomto dokumentu DbContext
se inicializuje v souboru Startup.cs .
Databáze v paměti vyžaduje Microsoft.EntityFrameworkCore.InMemory
balíček NuGet.
using Microsoft.EntityFrameworkCore;
using RazorPagesContacts.Data;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages();
builder.Services.AddDbContext<CustomerDbContext>(options =>
options.UseInMemoryDatabase("name"));
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthorization();
app.MapRazorPages();
app.Run();
Datový model:
using System.ComponentModel.DataAnnotations;
namespace RazorPagesContacts.Models
{
public class Customer
{
public int Id { get; set; }
[Required, StringLength(10)]
public string? Name { get; set; }
}
}
Kontext databáze:
using Microsoft.EntityFrameworkCore;
namespace RazorPagesContacts.Data
{
public class CustomerDbContext : DbContext
{
public CustomerDbContext (DbContextOptions<CustomerDbContext> options)
: base(options)
{
}
public DbSet<RazorPagesContacts.Models.Customer> Customer { get; set; }
}
}
Soubor Pages/Create.cshtml
zobrazení:
@page
@model RazorPagesContacts.Pages.Customers.CreateModel
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
<p>Enter a customer name:</p>
<form method="post">
Name:
<input asp-for="Customer.Name" />
<input type="submit" />
</form>
Model Pages/Create.cshtml.cs
stránky:
public class CreateModel : PageModel
{
private readonly Data.CustomerDbContext _context;
public CreateModel(Data.CustomerDbContext context)
{
_context = context;
}
public IActionResult OnGet()
{
return Page();
}
[BindProperty]
public Customer Customer { get; set; }
public async Task<IActionResult> OnPostAsync()
{
if (!ModelState.IsValid)
{
return Page();
}
_context.Customer.Add(Customer);
await _context.SaveChangesAsync();
return RedirectToPage("./Index");
}
}
Podle konvence PageModel
se třída volá <PageName>Model
a je ve stejném oboru názvů jako stránka.
Třída PageModel
umožňuje oddělení logiky stránky od prezentace. Definuje obslužné rutiny stránek pro požadavky odeslané na stránku a data použitá k vykreslení stránky. Toto oddělení umožňuje:
- Správa závislostí stránek prostřednictvím injektáže závislostí
- Testování jednotek
Stránka má metodu OnPostAsync
obslužné rutiny, která běží na POST
požadavcích (když uživatel publikuje formulář). Metody obslužné rutiny pro jakékoli příkazy HTTP lze přidat. Nejběžnější obslužné rutiny jsou:
OnGet
pro inicializaci stavu potřebného pro stránku. V předchozím kódu seOnGet
v metodě zobrazíCreateModel.cshtml
Razor stránka.OnPost
pro zpracování odesílání formulářů.
Přípona názvu Async
je volitelná, ale často se podle konvence používá pro asynchronní funkce. Předchozí kód je typický pro Razor Stránky.
Pokud znáte ASP.NET aplikace pomocí kontrolerů a zobrazení:
- Kód
OnPostAsync
v předchozím příkladu vypadá podobně jako typický kód kontroleru. - Většina primitivních objektů MVC, jako jsou vazby modelu, ověření a výsledky akcí, fungují stejně s řadiči a Razor stránkami.
Předchozí OnPostAsync
metoda:
[BindProperty]
public Customer Customer { get; set; }
public async Task<IActionResult> OnPostAsync()
{
if (!ModelState.IsValid)
{
return Page();
}
_context.Customer.Add(Customer);
await _context.SaveChangesAsync();
return RedirectToPage("./Index");
}
Základní tok OnPostAsync
:
Zkontrolujte chyby ověření.
- Pokud nedošlo k žádným chybám, uložte data a přesměrujte je.
- Pokud dojde k chybám, zobrazte stránku znovu s ověřovacími zprávami. V mnoha případech by se v klientovi zjistily chyby ověřování a nikdy by se neodeslaly na server.
Soubor Pages/Create.cshtml
zobrazení:
@page
@model RazorPagesContacts.Pages.Customers.CreateModel
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
<p>Enter a customer name:</p>
<form method="post">
Name:
<input asp-for="Customer.Name" />
<input type="submit" />
</form>
Vykreslený kód HTML z Pages/Create.cshtml
:
<p>Enter a customer name:</p>
<form method="post">
Name:
<input type="text" data-val="true"
data-val-length="The field Name must be a string with a maximum length of 10."
data-val-length-max="10" data-val-required="The Name field is required."
id="Customer_Name" maxlength="10" name="Customer.Name" value="" />
<input type="submit" />
<input name="__RequestVerificationToken" type="hidden"
value="<Antiforgery token here>" />
</form>
V předchozím kódu publikujte formulář:
S platnými daty:
Metoda
OnPostAsync
obslužné rutiny volá pomocnou metodu RedirectToPage .RedirectToPage
vrací instanci RedirectToPageResult.RedirectToPage
:- Je výsledek akce.
- Podobá se
RedirectToAction
neboRedirectToRoute
(používá se v kontrolérech a zobrazeních). - Je přizpůsobený pro stránky. V předchozí ukázce se přesměruje na kořenovou stránku indexu (
/Index
).RedirectToPage
je podrobně popsáno v části Generování adres URL pro stránky .
Při ověřování chyb, které se předávají serveru:
- Metoda
OnPostAsync
obslužné rutiny volá pomocnou metodu Page .Page
vrací instanci PageResult.Page
Vrácení se podobá tomu, jak se vrátí akce v řadičíchView
.PageResult
je výchozí návratový typ pro metodu obslužné rutiny. Metoda obslužné rutiny, která vrátívoid
vykreslení stránky. - V předchozím příkladu publikování formuláře bez hodnoty způsobí , že ModelState.IsValid vrátí hodnotu false. V této ukázce se v klientovi nezobrazují žádné chyby ověření. Předání chyby ověření je popsané dále v tomto dokumentu.
[BindProperty] public Customer Customer { get; set; } public async Task<IActionResult> OnPostAsync() { if (!ModelState.IsValid) { return Page(); } _context.Customer.Add(Customer); await _context.SaveChangesAsync(); return RedirectToPage("./Index"); }
- Metoda
S chybami ověření zjištěnými ověřením na straně klienta:
- Data se na server neodesílala.
- Ověření na straně klienta je vysvětleno dále v tomto dokumentu.
Vlastnost Customer
používá [BindProperty]
atribut k vyjádření souhlasu s vazbou modelu:
public class CreateModel : PageModel
{
private readonly Data.CustomerDbContext _context;
public CreateModel(Data.CustomerDbContext context)
{
_context = context;
}
public IActionResult OnGet()
{
return Page();
}
[BindProperty]
public Customer Customer { get; set; }
public async Task<IActionResult> OnPostAsync()
{
if (!ModelState.IsValid)
{
return Page();
}
_context.Customer.Add(Customer);
await _context.SaveChangesAsync();
return RedirectToPage("./Index");
}
}
[BindProperty]
by se neměly používat u modelů obsahujících vlastnosti, které by klient neměl měnit. Další informace naleznete v tématu Overposting.
Razor Stránky ve výchozím nastavení sváže vlastnosti pouze s jinýmiGET
příkazy. Vazba na vlastnosti odebere nutnost zápisu kódu pro převod dat HTTP na typ modelu. Vazba omezuje kód pomocí stejné vlastnosti k vykreslení polí formuláře (<input asp-for="Customer.Name">
) a přijetí vstupu.
Upozornění
Z bezpečnostních důvodů se musíte přihlásit k vytvoření vazby GET
dat požadavku na vlastnosti modelu stránky. Před mapováním na vlastnosti ověřte vstup uživatele. Při přidělování scénářů, které se spoléhají na řetězec dotazu nebo hodnoty směrování, je vhodné vyjádřit výslovný souhlas s GET
vazbou.
Chcete-li vytvořit vazbu vlastnosti na GET
požadavky, nastavte vlastnost atributu [BindProperty]
SupportsGet
na true
:
[BindProperty(SupportsGet = true)]
Další informace najdete v tématu ASP.NET Core Community Standup: Bind on GET discussion (YouTube).
Pages/Create.cshtml
Kontrola souboru zobrazení:
@page
@model RazorPagesContacts.Pages.Customers.CreateModel
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
<p>Enter a customer name:</p>
<form method="post">
Name:
<input asp-for="Customer.Name" />
<input type="submit" />
</form>
- V předchozím kódu pomocné rutina
<input asp-for="Customer.Name" />
vstupní značky vytvoří vazbu elementu HTML<input>
naCustomer.Name
výraz modelu. @addTagHelper
zpřístupňuje pomocné rutiny značek.
Domovská stránka
Index.cshtml
je domovská stránka:
@page
@model RazorPagesContacts.Pages.Customers.IndexModel
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
<h1>Contacts home page</h1>
<form method="post">
<table class="table">
<thead>
<tr>
<th>ID</th>
<th>Name</th>
<th></th>
</tr>
</thead>
<tbody>
@foreach (var contact in Model.Customer)
{
<tr>
<td> @contact.Id </td>
<td>@contact.Name</td>
<td>
<a asp-page="./Edit" asp-route-id="@contact.Id">Edit</a> |
<button type="submit" asp-page-handler="delete"
asp-route-id="@contact.Id">delete
</button>
</td>
</tr>
}
</tbody>
</table>
<a asp-page="Create">Create New</a>
</form>
Přidružená PageModel
třída (Index.cshtml.cs
):
public class IndexModel : PageModel
{
private readonly CustomerDbContext _context;
public IndexModel(CustomerDbContext context)
{
_context = context;
}
public IList<Customer> Customer { get; set; }
public async Task OnGetAsync()
{
Customer = await _context.Customers.ToListAsync();
}
public async Task<IActionResult> OnPostDeleteAsync(int id)
{
var contact = await _context.Customers.FindAsync(id);
if (contact != null)
{
_context.Customers.Remove(contact);
await _context.SaveChangesAsync();
}
return RedirectToPage();
}
}
Soubor Index.cshtml
obsahuje následující revize:
<a asp-page="./Edit" asp-route-id="@contact.Id">Edit</a> |
Pomocný <a /a>
pomocník značky ukotveníasp-route-{value}
použil atribut k vygenerování odkazu na stránku Upravit. Odkaz obsahuje směrovací data s ID kontaktu. Například, https://localhost:5001/Edit/1
. Pomocné rutiny značek umožňují, aby se podíleli na vytváření a vykreslování elementů HTML v Razor souborech.
Soubor Index.cshtml
obsahuje kód pro vytvoření tlačítka pro odstranění pro každý kontakt zákazníka:
<button type="submit" asp-page-handler="delete" asp-route-id="@contact.Id">delete</button>
Vykreslený kód HTML:
<button type="submit" formaction="/Customers?id=1&handler=delete">delete</button>
Když se tlačítko pro odstranění vykreslí ve formátu HTML, jeho formaction obsahuje parametry pro:
- ID kontaktu zákazníka zadané atributem
asp-route-id
. - Vlastnost
handler
, určená atributemasp-page-handler
.
Po výběru tlačítka se na server odešle žádost o formulář POST
. Podle konvence je název metody obslužné rutiny vybrán na základě hodnoty handler
parametru podle schématu OnPost[handler]Async
.
Vzhledem k tomu, že handler
je delete
v tomto příkladu OnPostDeleteAsync
, metoda obslužné rutiny se používá ke zpracování POST
požadavku. asp-page-handler
Pokud je nastavena na jinou hodnotu, například remove
, je vybrána metoda obslužné rutiny s názvemOnPostRemoveAsync
.
public async Task<IActionResult> OnPostDeleteAsync(int id)
{
var contact = await _context.Customers.FindAsync(id);
if (contact != null)
{
_context.Customers.Remove(contact);
await _context.SaveChangesAsync();
}
return RedirectToPage();
}
Metoda OnPostDeleteAsync
:
id
Získá z řetězce dotazu.- Dotazuje databázi na kontakt zákazníka s
FindAsync
. - Pokud se najde kontakt zákazníka, odebere se a databáze se aktualizuje.
- Volání RedirectToPage přesměrování na kořenovou stránku indexu (
/Index
).
Soubor Edit.cshtml
@page "{id:int}"
@model RazorPagesContacts.Pages.Customers.EditModel
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
<h1>Edit Customer - @Model.Customer.Id</h1>
<form method="post">
<div asp-validation-summary="All"></div>
<input asp-for="Customer.Id" type="hidden" />
<div>
<label asp-for="Customer.Name"></label>
<div>
<input asp-for="Customer.Name" />
<span asp-validation-for="Customer.Name"></span>
</div>
</div>
<div>
<button type="submit">Save</button>
</div>
</form>
První řádek obsahuje direktivu @page "{id:int}"
. Omezení "{id:int}"
směrování informuje stránku, aby přijímala požadavky na stránku, která obsahuje int
směrovací data. Pokud požadavek na stránku neobsahuje směrovací data, která lze převést na , int
vrátí modul runtime chybu HTTP 404 (nenalezena). Pokud chcete, aby ID bylo volitelné, připojte ?
se k omezení trasy:
@page "{id:int?}"
Soubor Edit.cshtml.cs
:
public class EditModel : PageModel
{
private readonly CustomerDbContext _context;
public EditModel(CustomerDbContext context)
{
_context = context;
}
[BindProperty]
public Customer Customer { get; set; }
public async Task<IActionResult> OnGetAsync(int id)
{
Customer = await _context.Customers.FindAsync(id);
if (Customer == null)
{
return RedirectToPage("./Index");
}
return Page();
}
public async Task<IActionResult> OnPostAsync()
{
if (!ModelState.IsValid)
{
return Page();
}
_context.Attach(Customer).State = EntityState.Modified;
try
{
await _context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
throw new Exception($"Customer {Customer.Id} not found!");
}
return RedirectToPage("./Index");
}
}
Ověřování
Ověřovací pravidla:
- Jsou deklarativní zadané ve třídě modelu.
- Vynucují se všude v aplikaci.
Obor System.ComponentModel.DataAnnotations názvů poskytuje sadu předdefinovaných ověřovacích atributů, které se aplikují deklarativním způsobem na třídu nebo vlastnost. Objekty DataAnnotation také obsahují atributy formátování, jako [DataType]
je například formátování, a neposkytuje žádné ověření.
Customer
Zvažte model:
using System.ComponentModel.DataAnnotations;
namespace RazorPagesContacts.Models
{
public class Customer
{
public int Id { get; set; }
[Required, StringLength(10)]
public string Name { get; set; }
}
}
Pomocí následujícího Create.cshtml
souboru zobrazení:
@page
@model RazorPagesContacts.Pages.Customers.CreateModel
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
<p>Validation: customer name:</p>
<form method="post">
<div asp-validation-summary="ModelOnly"></div>
<span asp-validation-for="Customer.Name"></span>
Name:
<input asp-for="Customer.Name" />
<input type="submit" />
</form>
<script src="~/lib/jquery/dist/jquery.js"></script>
<script src="~/lib/jquery-validation/dist/jquery.validate.js"></script>
<script src="~/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.js"></script>
Předchozí kód:
Obsahuje ověřovací skripty jQuery a jQuery.
Pomocí pomocných rutin a
<span />
pomocných<div />
rutin značek povolíte:- Ověření na straně klienta
- Vykreslování chyby ověření
Vygeneruje následující kód HTML:
<p>Enter a customer name:</p> <form method="post"> Name: <input type="text" data-val="true" data-val-length="The field Name must be a string with a maximum length of 10." data-val-length-max="10" data-val-required="The Name field is required." id="Customer_Name" maxlength="10" name="Customer.Name" value="" /> <input type="submit" /> <input name="__RequestVerificationToken" type="hidden" value="<Antiforgery token here>" /> </form> <script src="/lib/jquery/dist/jquery.js"></script> <script src="/lib/jquery-validation/dist/jquery.validate.js"></script> <script src="/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.js"></script>
Publikování formuláře Vytvořit bez hodnoty názvu zobrazí chybovou zprávu "Pole Název je požadováno" ve formuláři. Pokud je v klientovi povolený JavaScript, zobrazí se v prohlížeči chyba bez publikování na server.
Atribut [StringLength(10)]
vygeneruje data-val-length-max="10"
vykreslený kód HTML. data-val-length-max
zabraňuje prohlížečům zadávat více než maximální zadanou délku. Pokud se nástroj, jako je Fiddler , používá k úpravám a přehrání příspěvku:
- S názvem delším než 10.
- Vrátí se chybová zpráva "Název pole musí být řetězec s maximální délkou 10".
Zvažte následující Movie
model:
using System;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace RazorPagesMovie.Models
{
public class Movie
{
public int ID { get; set; }
[StringLength(60, MinimumLength = 3)]
[Required]
public string Title { get; set; }
[Display(Name = "Release Date")]
[DataType(DataType.Date)]
public DateTime ReleaseDate { get; set; }
[Range(1, 100)]
[DataType(DataType.Currency)]
[Column(TypeName = "decimal(18, 2)")]
public decimal Price { get; set; }
[RegularExpression(@"^[A-Z]+[a-zA-Z\s]*$")]
[Required]
[StringLength(30)]
public string Genre { get; set; }
[RegularExpression(@"^[A-Z]+[a-zA-Z0-9""'\s-]*$")]
[StringLength(5)]
[Required]
public string Rating { get; set; }
}
}
Atributy ověření určují chování, které se má vynutit u vlastností modelu, na které se použijí:
MinimumLength
AtributyRequired
označují, že vlastnost musí mít hodnotu, ale nic nebrání uživateli v zadávání prázdného místa, aby toto ověření splnil.Atribut
RegularExpression
slouží k omezení toho, jaké znaky lze zadat. V předchozím kódu "Žánr":- Musí používat jenom písmena.
- První písmeno musí být velké. Prázdné znaky, čísla a speciální znaky nejsou povolené.
"
RegularExpression
Hodnocení":- Vyžaduje, aby první znak byl velkým písmenem.
- Umožňuje speciální znaky a čísla v dalších mezerách. "PG-13" je platný pro hodnocení, ale selže pro "Žánr".
Atribut
Range
omezuje hodnotu v konkrétním rozsahu.Atribut
StringLength
nastaví maximální délku vlastnosti řetězce a volitelně její minimální délku.Typy hodnot (například
decimal
, ,int
float
DateTime
) jsou ze své podstaty povinné a nepotřebují[Required]
atribut.
Na stránce Vytvořit pro Movie
model se zobrazují chyby s neplatnými hodnotami:
Další informace naleznete v tématu:
Izolace šablon stylů CSS
Izolujte styly CSS na jednotlivé stránky, zobrazení a komponenty, abyste snížili nebo zabránili těmto stránkám:
- Závislosti na globálních stylech, které můžou být náročné na údržbu.
- Konflikty stylů v vnořeném obsahu
Pokud chcete přidat soubor CSS s vymezeným oborem pro stránku nebo zobrazení, umístěte styly CSS do doprovodného .cshtml.css
souboru odpovídající názvu .cshtml
souboru. V následujícím příkladu Index.cshtml.css
soubor poskytuje styly CSS, které se použijí jenom na Index.cshtml
stránku nebo zobrazení.
Pages/Index.cshtml.css
(Razor Stránky) nebo Views/Index.cshtml.css
(MVC):
h1 {
color: red;
}
Izolace šablon stylů CSS probíhá v době sestavení. Architektura přepisuje selektory css tak, aby odpovídaly revizím vykresleným stránkami nebo zobrazeními aplikace. Přepsané styly CSS jsou seskupené a vytvářeny jako statický prostředek, {APP ASSEMBLY}.styles.css
. Zástupný symbol {APP ASSEMBLY}
je název sestavení projektu. Odkaz na seskupené styly CSS se umístí do rozložení aplikace.
<head>
V obsahu aplikace Pages/Shared/_Layout.cshtml
(RazorStránky) nebo Views/Shared/_Layout.cshtml
MVC přidejte nebo potvrďte přítomnost odkazu na sbalené styly CSS:
<link rel="stylesheet" href="{APP ASSEMBLY}.styles.css" />
V následujícím příkladu je WebApp
název sestavení aplikace:
<link rel="stylesheet" href="WebApp.styles.css" />
Styly definované v souboru CSS s vymezeným oborem se použijí pouze na vykreslený výstup odpovídajícího souboru. V předchozím příkladu nejsou všechny h1
deklarace CSS definované jinde v aplikaci v konfliktu se stylem nadpisu Index
. Šablony stylů CSS a pravidla dědičnosti zůstávají v platnosti pro soubory CSS s vymezeným oborem. Styly použité například přímo u <h1>
elementu Index.cshtml
v souboru přepíší styly souboru CSS s vymezeným oborem v Index.cshtml.css
souboru .
Poznámka
Pokud chcete zaručit izolaci stylu CSS při sdružování, import šablon stylů CSS v Razor blocích kódu se nepodporuje.
Izolace šablon stylů CSS se vztahuje pouze na elementy HTML. Izolace šablon stylů CSS není podporována pro pomocné rutiny značek.
V souboru CSS v rámci sady je každá stránka, zobrazení nebo Razor komponenta přidružena k identifikátoru oboru ve formátu b-{STRING}
, kde {STRING}
zástupný symbol je desetimínný řetězec vygenerovaný architekturou. Následující příklad poskytuje styl pro předchozí <h1>
prvek na Index
stránce Razor aplikace Pages:
/* /Pages/Index.cshtml.rz.scp.css */
h1[b-3xxtam6d07] {
color: red;
}
Na Index
stránce, kde se styl CSS použije ze souboru se souborem s balíčkem, se identifikátor oboru připojí jako atribut HTML:
<h1 b-3xxtam6d07>
Identifikátor je jedinečný pro aplikaci. V době sestavení se vytvoří sada projektů s konvencí {STATIC WEB ASSETS BASE PATH}/Project.lib.scp.css
, kde zástupný symbol {STATIC WEB ASSETS BASE PATH}
představuje základní cestu statických webových prostředků.
Pokud se využívají jiné projekty, například balíčky NuGet nebo Razor knihovny tříd, soubor se váže:
- Odkazuje na styly pomocí importů css.
- Nepublikuje se jako statický webový prostředek aplikace, který využívá styly.
Podpora preprocesoru CSS
Preprocesory css jsou užitečné pro zlepšení vývoje css pomocí funkcí, jako jsou proměnné, vnořování, moduly, mixiny a dědičnost. I když izolace šablon stylů CSS nativně nepodporuje preprocesory šablon stylů CSS, jako jsou Sass nebo Less, integrace preprocesorů CSS je bezproblémová, pokud dojde k kompilaci preprocesoru před přepsáním selektorů CSS během procesu sestavení. Pomocí Visual Studio například nakonfigurujte existující kompilaci preprocesoru jako úlohu Před sestavením v průzkumníku Visual Studio Spouštěč úloh.
Řada balíčků NuGet třetích stran, jako Delegate.SassBuilder
je například , může kompilovat soubory SASS/SCSS na začátku procesu sestavení před izolací CSS a nevyžaduje se žádná další konfigurace.
Konfigurace izolace šablon stylů CSS
Izolace šablon stylů CSS umožňuje konfiguraci pro některé pokročilé scénáře, například pokud existují závislosti na existujících nástrojích nebo pracovních postupech.
Přizpůsobení formátu identifikátoru oboru
V této části {Pages|Views}
je Pages
zástupný symbol pro Razor aplikace Pages nebo Views
pro aplikace MVC.
Ve výchozím nastavení identifikátory oboru používají formát b-{STRING}
, kde {STRING}
zástupný symbol je řetězec desetimísek vygenerovaný architekturou. Pokud chcete přizpůsobit formát identifikátoru oboru, aktualizujte soubor projektu na požadovaný vzor:
<ItemGroup>
<None Update="{Pages|Views}/Index.cshtml.css" CssScope="custom-scope-identifier" />
</ItemGroup>
V předchozím příkladu vygeneroval css pro Index.cshtml.css
změny jeho identifikátor oboru z b-{STRING}
na custom-scope-identifier
.
Pomocí identifikátorů oboru dosáhnete dědičnosti s vymezenými soubory CSS. V následujícím příkladu BaseView.cshtml.css
souboru projektu soubor obsahuje společné styly napříč zobrazeními. DerivedView.cshtml.css
Soubor dědí tyto styly.
<ItemGroup>
<None Update="{Pages|Views}/BaseView.cshtml.css" CssScope="custom-scope-identifier" />
<None Update="{Pages|Views}/DerivedView.cshtml.css" CssScope="custom-scope-identifier" />
</ItemGroup>
Pomocí operátoru se zástupným znakem (*
) můžete sdílet identifikátory oboru mezi více soubory:
<ItemGroup>
<None Update="{Pages|Views}/*.cshtml.css" CssScope="custom-scope-identifier" />
</ItemGroup>
Změna základní cesty pro statické webové prostředky
V kořenovém adresáři aplikace se vygeneruje soubor CSS s vymezeným oborem. V souboru projektu použijte StaticWebAssetBasePath
vlastnost ke změně výchozí cesty. Následující příklad umístí soubor CSS s vymezeným oborem a zbytek prostředků aplikace na _content
cestu:
<PropertyGroup>
<StaticWebAssetBasePath>_content/$(PackageId)</StaticWebAssetBasePath>
</PropertyGroup>
Zakázání automatického sdružování
Pokud chcete vyloučit, jak architektura publikuje a načítá soubory s vymezeným oborem za běhu, použijte DisableScopedCssBundling
tuto vlastnost. Při použití této vlastnosti zodpovídají za převzetí izolovaných souborů CSS z obj
adresáře a jejich publikování a jejich načítání za běhu další nástroje nebo procesy:
<PropertyGroup>
<DisableScopedCssBundling>true</DisableScopedCssBundling>
</PropertyGroup>
Razor Podpora knihovny tříd (RCL)
Razor Když knihovna tříd (RCL) poskytuje izolované styly, <link>
atribut značky href
odkazuje na {STATIC WEB ASSET BASE PATH}/{PACKAGE ID}.bundle.scp.css
, kde jsou zástupné symboly:
{STATIC WEB ASSET BASE PATH}
: Základní cesta statického webového prostředku.{PACKAGE ID}
: Identifikátor balíčku knihovny. Identifikátor balíčku ve výchozím nastavení odkazuje na název sestavení projektu, pokud není v souboru projektu zadaný identifikátor balíčku.
V následujícím příkladu:
- Základní cesta statického webového prostředku je
_content/ClassLib
. - Název sestavení knihovny tříd je
ClassLib
.
Pages/Shared/_Layout.cshtml
(Razor Stránky) nebo Views/Shared/_Layout.cshtml
(MVC):
<link href="_content/ClassLib/ClassLib.bundle.scp.css" rel="stylesheet">
Další informace o náležcích RCL najdete v následujících článcích:
- Opakovaně použitelné Razor uživatelské rozhraní v knihovnách tříd pomocí ASP.NET Core
- Využívání ASP.NET Core Razor komponent z Razor knihovny tříd (RCL)
Informace o Blazor izolaci šablon stylů CSS najdete v tématu ASP.NET Core Blazor izolace šablon stylů CSS.
Zpracování požadavků HEAD pomocí náhradní obslužné rutiny OnGet
HEAD
požadavky umožňují načtení hlaviček pro konkrétní prostředek. Na rozdíl od GET
požadavků HEAD
nevrací požadavky text odpovědi.
Obvykle se vytvoří obslužná rutina OnHead
a volá se pro HEAD
požadavky:
public void OnHead()
{
HttpContext.Response.Headers.Add("Head Test", "Handled by OnHead!");
}
Razor Stránky se vrátí do volání obslužné OnGet
rutiny, pokud není definována žádná OnHead
obslužná rutina.
XSRF/CSRF a Razor stránky
Razor Stránky jsou chráněny ověřením antiforgery. FormTagHelper vloží antiforgery tokeny do elementů formuláře HTML.
Použití pomocných rutin rozložení, částečných hodnot, šablon a značek se stránkami Razor
Stránky pracují se všemi funkcemi Razor modulu zobrazení. Rozložení, části, šablony, pomocné rutiny _ViewStart.cshtml
značek a _ViewImports.cshtml
fungují stejným způsobem jako u konvenčních Razor zobrazení.
Podívejme se na tuto stránku tím, že využijeme některé z těchto možností.
Přidání stránky rozložení do Pages/Shared/_Layout.cshtml
:
<!DOCTYPE html>
<html>
<head>
<title>RP Sample</title>
<link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.css" />
</head>
<body>
<a asp-page="/Index">Home</a>
<a asp-page="/Customers/Create">Create</a>
<a asp-page="/Customers/Index">Customers</a> <br />
@RenderBody()
<script src="~/lib/jquery/dist/jquery.js"></script>
<script src="~/lib/jquery-validation/dist/jquery.validate.js"></script>
<script src="~/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.js"></script>
</body>
</html>
- Určuje rozložení jednotlivých stránek (pokud se stránka nevyhlásí z rozložení).
- Importuje struktury HTML, jako jsou JavaScript a šablony stylů.
- Razor Obsah stránky se vykreslí tam, kde
@RenderBody()
se volá.
Další informace najdete na stránce rozložení.
Vlastnost Layout je nastavena v Pages/_ViewStart.cshtml
:
@{
Layout = "_Layout";
}
Rozložení je ve složce Pages/Shared . Stránky vyhledávají další zobrazení (rozložení, šablony, části) hierarchicky, počínaje stejnou složkou jako aktuální stránka. Rozložení ve složce Pages/Shared lze použít z libovolné Razor stránky ve složce Stránky .
Soubor rozložení by měl být ve složce Pages/Shared .
Doporučujeme, abyste soubor rozložení nevložili do složky Zobrazení/Sdílené složky. Zobrazení/sdílené zobrazení je vzor zobrazení MVC. Razor Stránky jsou určené k závislosti na hierarchii složek, nikoli na konvence cest.
Zobrazení hledání ze Razor stránky obsahuje složku Stránky . Rozložení, šablony a části používané s řadiči MVC a konvenčními Razor zobrazeními fungují.
Pages/_ViewImports.cshtml
Přidejte soubor:
@namespace RazorPagesContacts.Pages
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
@namespace
je vysvětleno dále v tomto kurzu. Direktiva @addTagHelper
přináší integrované pomocné rutiny značek na všechny stránky ve složce Pages .
Direktiva @namespace
nastavená na stránce:
@page
@namespace RazorPagesIntro.Pages.Customers
@model NameSpaceModel
<h2>Name space</h2>
<p>
@Model.Message
</p>
Direktiva @namespace
nastaví obor názvů stránky. Direktiva @model
nemusí zahrnovat obor názvů.
@namespace
Pokud je direktiva obsažena_ViewImports.cshtml
, zadaný obor názvů poskytuje předponu pro vygenerovaný obor názvů na stránce, která importuje direktivu@namespace
. Zbytek vygenerovaného oboru názvů (část s příponou) je tečkovaná relativní cesta mezi složkou obsahující _ViewImports.cshtml
a složkou obsahující stránku.
PageModel
Například třída Pages/Customers/Edit.cshtml.cs
explicitně nastaví obor názvů:
namespace RazorPagesContacts.Pages
{
public class EditModel : PageModel
{
private readonly AppDbContext _db;
public EditModel(AppDbContext db)
{
_db = db;
}
// Code removed for brevity.
Soubor Pages/_ViewImports.cshtml
nastaví následující obor názvů:
@namespace RazorPagesContacts.Pages
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
Vygenerovaný obor názvů stránky Pages/Customers/Edit.cshtml
Razor je stejný jako PageModel
třída.
@namespace
funguje také s konvenčními Razor zobrazeními.
Pages/Create.cshtml
Zvažte soubor zobrazení:
@page
@model RazorPagesContacts.Pages.Customers.CreateModel
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
<p>Validation: customer name:</p>
<form method="post">
<div asp-validation-summary="ModelOnly"></div>
<span asp-validation-for="Customer.Name"></span>
Name:
<input asp-for="Customer.Name" />
<input type="submit" />
</form>
<script src="~/lib/jquery/dist/jquery.js"></script>
<script src="~/lib/jquery-validation/dist/jquery.validate.js"></script>
<script src="~/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.js"></script>
Aktualizovaný Pages/Create.cshtml
soubor zobrazení s předchozím souborem _ViewImports.cshtml
rozložení:
@page
@model CreateModel
<p>Enter a customer name:</p>
<form method="post">
Name:
<input asp-for="Customer.Name" />
<input type="submit" />
</form>
V předchozím kódu _ViewImports.cshtml
importoval obor názvů a pomocné rutiny značek. Soubor rozložení naimportoval soubory JavaScriptu.
Razor Úvodní projekt Pages obsahuje Pages/_ValidationScriptsPartial.cshtml
objekt , který připojí ověření na straně klienta.
Další informace o částečných zobrazeních najdete v tématu Částečná zobrazení v ASP.NET Core.
Generování adres URL pro stránky
Stránka Create
, která byla zobrazena dříve, používá RedirectToPage
:
public class CreateModel : PageModel
{
private readonly CustomerDbContext _context;
public CreateModel(CustomerDbContext context)
{
_context = context;
}
public IActionResult OnGet()
{
return Page();
}
[BindProperty]
public Customer Customer { get; set; }
public async Task<IActionResult> OnPostAsync()
{
if (!ModelState.IsValid)
{
return Page();
}
_context.Customers.Add(Customer);
await _context.SaveChangesAsync();
return RedirectToPage("./Index");
}
}
Aplikace má následující strukturu souborů a složek:
/Pages
Index.cshtml
Privacy.cshtml
/Customers
Create.cshtml
Edit.cshtml
Index.cshtml
Stránky Pages/Customers/Create.cshtml
a Pages/Customers/Edit.cshtml
stránky se přesměrovávají na Pages/Customers/Index.cshtml
po úspěšném dokončení. Řetězec ./Index
je relativní název stránky použitý pro přístup k předchozí stránce. Slouží k vygenerování adres URL na Pages/Customers/Index.cshtml
stránku. Například:
Url.Page("./Index", ...)
<a asp-page="./Index">Customers Index Page</a>
RedirectToPage("./Index")
Absolutní název /Index
stránky slouží k vygenerování adres URL na Pages/Index.cshtml
stránku. Například:
Url.Page("/Index", ...)
<a asp-page="/Index">Home Index Page</a>
RedirectToPage("/Index")
Název stránky je cesta k stránce z kořenové složky /Pages včetně úvodní /
(například /Index
). Předchozí ukázky generování adres URL nabízejí vylepšené možnosti a funkční funkce při pevném kódování adresy URL. Generování adres URL používá směrování a může generovat a kódovat parametry podle toho, jak je trasa definovaná v cílové cestě.
Generování adres URL pro stránky podporuje relativní názvy. Následující tabulka ukazuje, která stránka indexu je vybrána pomocí různých RedirectToPage
parametrů v Pages/Customers/Create.cshtml
.
RedirectToPage(x) | Stránka |
---|---|
RedirectToPage("/Index") | Stránky/index |
RedirectToPage("./Index"); | Stránky/ Zákazníci/ Index |
RedirectToPage(".. /Index") | Stránky/index |
RedirectToPage("Index") | Stránky/ Zákazníci/ Index |
RedirectToPage("Index")
, RedirectToPage("./Index")
a RedirectToPage("../Index")
jsou relativní názvy. Parametr RedirectToPage
je kombinován s cestou aktuální stránky k výpočtu názvu cílové stránky.
Propojení relativního názvu je užitečné při vytváření lokalit se složitou strukturou. Pokud se relativní názvy používají k propojení mezi stránkami ve složce:
- Přejmenování složky nezlomí relativní odkazy.
- Odkazy nejsou poškozené, protože neobsahují název složky.
Pokud chcete přesměrovat na stránku v jiné oblasti, zadejte oblast:
RedirectToPage("/Index", new { area = "Services" });
Další informace najdete v tématu Oblasti v ASP.NET Core a Razor konvencích tras a aplikací v ASP.NET Core.
Atribut ViewData
Data lze předat na stránku s ViewDataAttribute. Vlastnosti s atributem [ViewData]
mají své hodnoty uložené a načtené z objektu ViewDataDictionary.
V následujícím příkladu AboutModel
platí [ViewData]
atribut pro Title
vlastnost:
public class AboutModel : PageModel
{
[ViewData]
public string Title { get; } = "About";
public void OnGet()
{
}
}
Na stránce O aplikaci přejděte na Title
vlastnost jako vlastnost modelu:
<h1>@Model.Title</h1>
V rozložení se nadpis přečte ze slovníku ViewData:
<!DOCTYPE html>
<html lang="en">
<head>
<title>@ViewData["Title"] - WebApplication</title>
...
TempData
ASP.NET Core zveřejňuje TempData. Tato vlastnost ukládá data, dokud se nečte. Tyto Keep metody Peek lze použít k prozkoumání dat bez odstranění. TempData
je užitečná pro přesměrování, pokud jsou data potřebná pro více než jeden požadavek.
Následující kód nastaví hodnotu Message
použití TempData
:
public class CreateDotModel : PageModel
{
private readonly AppDbContext _db;
public CreateDotModel(AppDbContext db)
{
_db = db;
}
[TempData]
public string Message { get; set; }
[BindProperty]
public Customer Customer { get; set; }
public async Task<IActionResult> OnPostAsync()
{
if (!ModelState.IsValid)
{
return Page();
}
_db.Customers.Add(Customer);
await _db.SaveChangesAsync();
Message = $"Customer {Customer.Name} added";
return RedirectToPage("./Index");
}
}
Následující kód v Pages/Customers/Index.cshtml
souboru zobrazuje hodnotu Message
použití TempData
.
<h3>Msg: @Model.Message</h3>
Model Pages/Customers/Index.cshtml.cs
stránky použije [TempData]
atribut na Message
vlastnost.
[TempData]
public string Message { get; set; }
Další informace najdete v tématu TempData.
Více obslužných rutin na stránku
Následující stránka vygeneruje kód pro dva obslužné rutiny pomocí pomocné rutiny asp-page-handler
značek:
@page
@model CreateFATHModel
<html>
<body>
<p>
Enter your name.
</p>
<div asp-validation-summary="All"></div>
<form method="POST">
<div>Name: <input asp-for="Customer.Name" /></div>
<!-- <snippet_Handlers> -->
<input type="submit" asp-page-handler="JoinList" value="Join" />
<input type="submit" asp-page-handler="JoinListUC" value="JOIN UC" />
<!-- </snippet_Handlers> -->
</form>
</body>
</html>
Formulář v předchozím příkladu obsahuje dvě tlačítka pro odeslání, z nichž každý používá FormActionTagHelper
k odeslání jinou adresu URL. Atribut asp-page-handler
je průvodcem asp-page
. asp-page-handler
generuje adresy URL, které se odesílají do každé metody obslužné rutiny definované stránkou. asp-page
není zadán, protože ukázka odkazuje na aktuální stránku.
Model stránky:
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using RazorPagesContacts.Data;
namespace RazorPagesContacts.Pages.Customers
{
public class CreateFATHModel : PageModel
{
private readonly AppDbContext _db;
public CreateFATHModel(AppDbContext db)
{
_db = db;
}
[BindProperty]
public Customer Customer { get; set; }
public async Task<IActionResult> OnPostJoinListAsync()
{
if (!ModelState.IsValid)
{
return Page();
}
_db.Customers.Add(Customer);
await _db.SaveChangesAsync();
return RedirectToPage("/Index");
}
public async Task<IActionResult> OnPostJoinListUCAsync()
{
if (!ModelState.IsValid)
{
return Page();
}
Customer.Name = Customer.Name?.ToUpperInvariant();
return await OnPostJoinListAsync();
}
}
}
Předchozí kód používá pojmenované metody obslužné rutiny. Pojmenované metody obslužné rutiny se vytvářejí tak, že převezmou text v názvu za On<HTTP Verb>
a před Async
(pokud jsou k dispozici). V předchozím příkladu jsou metody stránky OnPostJoinListAsync a OnPostJoinListUCAsync. Při odebrání OnPost a Async jsou JoinList
názvy obslužných rutin a JoinListUC
.
<input type="submit" asp-page-handler="JoinList" value="Join" />
<input type="submit" asp-page-handler="JoinListUC" value="JOIN UC" />
Pomocí předchozího kódu je cesta URL, která se odešle.OnPostJoinListAsync
https://localhost:5001/Customers/CreateFATH?handler=JoinList
Cesta URL, která se odešle, OnPostJoinListUCAsync
je https://localhost:5001/Customers/CreateFATH?handler=JoinListUC
.
Vlastní trasy
Direktivu @page
použijte k:
- Zadejte vlastní trasu na stránku. Můžete například nastavit
/Some/Other/Path
@page "/Some/Other/Path"
trasu na stránku O produktu . - Připojte segmenty k výchozí trase stránky. Například segment "item" lze přidat do výchozí trasy stránky s
@page "item"
. - Připojte parametry k výchozí trase stránky. Například parametr ID ,
id
může být vyžadován pro stránku s@page "{id}"
.
Podporuje se kořenová relativní cesta určená vlnovkou (~
) na začátku cesty. Je například @page "~/Some/Other/Path"
stejný jako @page "/Some/Other/Path"
.
Pokud se vám řetězec ?handler=JoinList
dotazu v adrese URL nelíbí, změňte trasu tak, aby název obslužné rutiny vložil do části cesty adresy URL. Trasu lze přizpůsobit přidáním šablony trasy uzavřené do dvojitých uvozovek za direktivou @page
.
@page "{handler?}"
@model CreateRouteModel
<html>
<body>
<p>
Enter your name.
</p>
<div asp-validation-summary="All"></div>
<form method="POST">
<div>Name: <input asp-for="Customer.Name" /></div>
<input type="submit" asp-page-handler="JoinList" value="Join" />
<input type="submit" asp-page-handler="JoinListUC" value="JOIN UC" />
</form>
</body>
</html>
Pomocí předchozího kódu je cesta URL, která se odešle.OnPostJoinListAsync
https://localhost:5001/Customers/CreateFATH/JoinList
Cesta URL, která se odešle, OnPostJoinListUCAsync
je https://localhost:5001/Customers/CreateFATH/JoinListUC
.
Následující ?
handler
znamená, že parametr trasy je volitelný.
Pokročilá konfigurace a nastavení
Většina aplikací nevyžaduje konfiguraci a nastavení v následujících částech.
Pokud chcete konfigurovat pokročilé možnosti, použijte AddRazorPages přetížení, které konfiguruje RazorPagesOptions:
using Microsoft.EntityFrameworkCore;
using RazorPagesContacts.Data;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages(options =>
{
options.RootDirectory = "/MyPages";
options.Conventions.AuthorizeFolder("/MyPages/Admin");
});
builder.Services.AddDbContext<CustomerDbContext>(options =>
options.UseInMemoryDatabase("name"));
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthorization();
app.MapRazorPages();
app.Run();
RazorPagesOptions Slouží k nastavení kořenového adresáře pro stránky nebo přidání konvencí modelu aplikace pro stránky. Další informace o konvencích najdete v tématu Razor Konvence autorizace stránek.
Pokud chcete předkompilovat zobrazení, podívejte se na Razor kompilaci zobrazení.
Určení, že Razor stránky jsou v kořenovém adresáři obsahu
Ve výchozím nastavení Razor jsou stránky kořenové v adresáři /Pages . Přidejte WithRazorPagesAtContentRoot , abyste určili, že vaše Razor stránky jsou v kořenovém adresáři obsahu (ContentRootPath) aplikace:
using Microsoft.EntityFrameworkCore;
using RazorPagesContacts.Data;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages(options =>
{
options.Conventions.AuthorizeFolder("/MyPages/Admin");
})
.WithRazorPagesAtContentRoot();
builder.Services.AddDbContext<CustomerDbContext>(options =>
options.UseInMemoryDatabase("name"));
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthorization();
app.MapRazorPages();
app.Run();
Určení, že Razor stránky jsou ve vlastním kořenovém adresáři
Přidejte WithRazorPagesRoot k určení, že Razor stránky jsou ve vlastním kořenovém adresáři v aplikaci (zadejte relativní cestu):
using Microsoft.EntityFrameworkCore;
using RazorPagesContacts.Data;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages(options =>
{
options.Conventions.AuthorizeFolder("/MyPages/Admin");
})
.WithRazorPagesRoot("/path/to/razor/pages");
builder.Services.AddDbContext<CustomerDbContext>(options =>
options.UseInMemoryDatabase("name"));
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthorization();
app.MapRazorPages();
app.Run();
Další materiály
- Podívejte se na Začínáme se stránkamiRazor, které vycházejí z tohoto úvodu.
- Autorizace atributu a Razor stránek
- Stažení nebo zobrazení ukázkového kódu
- Přehled ASP.NET Core
- RazorReferenční informace k syntaxi pro ASP.NET Core
- Oblasti v ASP.NET Core
- Kurz: Začínáme se stránkami Razor v ASP.NET Core
- RazorZásady autorizace stránek v ASP.NET Core
- RazorZásady směrování stránek a aplikací v ASP.NET Core
- RazorTesty jednotek stránky v ASP.NET Core
- Částečná zobrazení v ASP.NET Core
- Prerender a integrace komponent ASP.NET Core Razor
Visual Studio 2019 16.4 nebo novější s úlohou vývoje pro ASP.NET a web
- Visual Studio 2019 16.8 nebo novější s úlohou ASP.NET a vývoje webu
- .NET 5.0 SDK
Razor Vytvoření projektu Stránky
Podrobné pokyny k vytvoření Razor projektu Pages najdete v Začínáme se stránkamiRazor.
Razor Stránky
Razor Stránky jsou povoleny v Startup.cs
:
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
public void ConfigureServices(IServiceCollection services)
{
services.AddRazorPages();
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapRazorPages();
});
}
}
@page
<h1>Hello, world!</h1>
<h2>The time on the server is @DateTime.Now</h2>
Předchozí kód vypadá hodně jako Razor soubor zobrazení používaný v aplikaci ASP.NET Core s kontrolery a zobrazeními. Čím se direktiva @page
liší. @page
vytvoří soubor do akce MVC – což znamená, že zpracovává požadavky přímo, aniž by procházel kontrolerem. @page
musí být první Razor direktivou na stránce. @page
ovlivňuje chování jiných Razor konstruktorů. Razor Názvy souborů stránek mají příponu .cshtml
.
Podobná stránka, která používá PageModel
třídu, je zobrazena v následujících dvou souborech. Soubor Pages/Index2.cshtml
:
@page
@using RazorPagesIntro.Pages
@model Index2Model
<h2>Separate page model</h2>
<p>
@Model.Message
</p>
Model Pages/Index2.cshtml.cs
stránky:
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.Extensions.Logging;
using System;
namespace RazorPagesIntro.Pages
{
public class Index2Model : PageModel
{
public string Message { get; private set; } = "PageModel in C#";
public void OnGet()
{
Message += $" Server time is { DateTime.Now }";
}
}
}
Podle konvence PageModel
má soubor třídy stejný název jako Razor stránkovací soubor s připojeným .cs
. Například předchozí Razor stránka je Pages/Index2.cshtml
. Soubor obsahující PageModel
třídu má název Pages/Index2.cshtml.cs
.
Přidružení cest URL na stránky jsou určena umístěním stránky v systému souborů. Následující tabulka ukazuje Razor cestu stránky a odpovídající adresu URL:
Název souboru a cesta | odpovídající adresa URL |
---|---|
/Pages/Index.cshtml |
/ nebo /Index |
/Pages/Contact.cshtml |
/Contact |
/Pages/Store/Contact.cshtml |
/Store/Contact |
/Pages/Store/Index.cshtml |
/Store nebo /Store/Index |
Poznámky:
- Modul runtime ve výchozím nastavení hledá Razor soubory Pages ve složce Pages .
Index
je výchozí stránka, pokud adresa URL neobsahuje stránku.
Zápis základního formuláře
Razor Stránky jsou navržené tak, aby se při vytváření aplikace snadno implementovaly běžné vzory používané ve webových prohlížečích. Vazby modelu, pomocné rutiny značek a pomocné rutiny HTML fungují jenom s vlastnostmi definovanými ve Razor třídě Page. Zvažte stránku, která implementuje základní formulář Contact
"kontaktujte nás":
Pro ukázky v tomto dokumentu DbContext
se inicializuje v souboru Startup.cs .
Databáze v paměti vyžaduje Microsoft.EntityFrameworkCore.InMemory
balíček NuGet.
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<CustomerDbContext>(options =>
options.UseInMemoryDatabase("name"));
services.AddRazorPages();
}
Datový model:
using System.ComponentModel.DataAnnotations;
namespace RazorPagesContacts.Models
{
public class Customer
{
public int Id { get; set; }
[Required, StringLength(10)]
public string Name { get; set; }
}
}
Kontext databáze:
using Microsoft.EntityFrameworkCore;
using RazorPagesContacts.Models;
namespace RazorPagesContacts.Data
{
public class CustomerDbContext : DbContext
{
public CustomerDbContext(DbContextOptions options)
: base(options)
{
}
public DbSet<Customer> Customers { get; set; }
}
}
Soubor Pages/Create.cshtml
zobrazení:
@page
@model RazorPagesContacts.Pages.Customers.CreateModel
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
<p>Enter a customer name:</p>
<form method="post">
Name:
<input asp-for="Customer.Name" />
<input type="submit" />
</form>
Model Pages/Create.cshtml.cs
stránky:
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using RazorPagesContacts.Data;
using RazorPagesContacts.Models;
using System.Threading.Tasks;
namespace RazorPagesContacts.Pages.Customers
{
public class CreateModel : PageModel
{
private readonly CustomerDbContext _context;
public CreateModel(CustomerDbContext context)
{
_context = context;
}
public IActionResult OnGet()
{
return Page();
}
[BindProperty]
public Customer Customer { get; set; }
public async Task<IActionResult> OnPostAsync()
{
if (!ModelState.IsValid)
{
return Page();
}
_context.Customers.Add(Customer);
await _context.SaveChangesAsync();
return RedirectToPage("./Index");
}
}
}
Podle konvence PageModel
se třída volá <PageName>Model
a je ve stejném oboru názvů jako stránka.
Třída PageModel
umožňuje oddělení logiky stránky od prezentace. Definuje obslužné rutiny stránek pro požadavky odeslané na stránku a data použitá k vykreslení stránky. Toto oddělení umožňuje:
- Správa závislostí stránek prostřednictvím injektáže závislostí
- Testování jednotek
Stránka má metodu OnPostAsync
obslužné rutiny, která běží na POST
požadavcích (když uživatel publikuje formulář). Metody obslužné rutiny pro jakékoli příkazy HTTP lze přidat. Nejběžnější obslužné rutiny jsou:
OnGet
pro inicializaci stavu potřebného pro stránku. V předchozím kódu seOnGet
v metodě zobrazíCreateModel.cshtml
Razor stránka.OnPost
pro zpracování odesílání formulářů.
Přípona názvu Async
je volitelná, ale často se podle konvence používá pro asynchronní funkce. Předchozí kód je typický pro Razor Stránky.
Pokud znáte ASP.NET aplikace pomocí kontrolerů a zobrazení:
- Kód
OnPostAsync
v předchozím příkladu vypadá podobně jako typický kód kontroleru. - Většina primitivních objektů MVC, jako jsou vazby modelu, ověření a výsledky akcí, fungují stejně s řadiči a Razor stránkami.
Předchozí OnPostAsync
metoda:
public async Task<IActionResult> OnPostAsync()
{
if (!ModelState.IsValid)
{
return Page();
}
_context.Customers.Add(Customer);
await _context.SaveChangesAsync();
return RedirectToPage("./Index");
}
Základní tok OnPostAsync
:
Zkontrolujte chyby ověření.
- Pokud nedošlo k žádným chybám, uložte data a přesměrujte je.
- Pokud dojde k chybám, zobrazte stránku znovu s ověřovacími zprávami. V mnoha případech by se v klientovi zjistily chyby ověřování a nikdy by se neodeslaly na server.
Soubor Pages/Create.cshtml
zobrazení:
@page
@model RazorPagesContacts.Pages.Customers.CreateModel
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
<p>Enter a customer name:</p>
<form method="post">
Name:
<input asp-for="Customer.Name" />
<input type="submit" />
</form>
Vykreslený kód HTML z Pages/Create.cshtml
:
<p>Enter a customer name:</p>
<form method="post">
Name:
<input type="text" data-val="true"
data-val-length="The field Name must be a string with a maximum length of 10."
data-val-length-max="10" data-val-required="The Name field is required."
id="Customer_Name" maxlength="10" name="Customer.Name" value="" />
<input type="submit" />
<input name="__RequestVerificationToken" type="hidden"
value="<Antiforgery token here>" />
</form>
V předchozím kódu publikujte formulář:
S platnými daty:
Metoda
OnPostAsync
obslužné rutiny volá pomocnou metodu RedirectToPage .RedirectToPage
vrací instanci RedirectToPageResult.RedirectToPage
:- Je výsledek akce.
RedirectToAction
Podobá se neboRedirectToRoute
(používá se v řadičích a zobrazeních).- Je přizpůsoben pro stránky. V předchozí ukázce se přesměruje na kořenovou stránku indexu (
/Index
).RedirectToPage
je podrobně popsáno v části Generování adres URL pro stránky .
Při ověřování chyb, které se předávají serveru:
- Metoda
OnPostAsync
obslužné rutiny volá pomocnou metodu Page .Page
vrací instanci PageResult.Page
Vrácení se podobá tomu, jak se vrátí akce v řadičíchView
.PageResult
je výchozí návratový typ pro metodu obslužné rutiny. Metoda obslužné rutiny, která vrátívoid
vykreslení stránky. - V předchozím příkladu publikování formuláře bez hodnoty způsobí , že ModelState.IsValid vrátí hodnotu false. V této ukázce se v klientovi nezobrazují žádné chyby ověření. Předání chyby ověření je popsané dále v tomto dokumentu.
public async Task<IActionResult> OnPostAsync() { if (!ModelState.IsValid) { return Page(); } _context.Customers.Add(Customer); await _context.SaveChangesAsync(); return RedirectToPage("./Index"); }
- Metoda
S chybami ověření zjištěnými ověřením na straně klienta:
- Data se na server neodesílala.
- Ověření na straně klienta je vysvětleno dále v tomto dokumentu.
Vlastnost Customer
používá [BindProperty]
atribut k vyjádření souhlasu s vazbou modelu:
public class CreateModel : PageModel
{
private readonly CustomerDbContext _context;
public CreateModel(CustomerDbContext context)
{
_context = context;
}
public IActionResult OnGet()
{
return Page();
}
[BindProperty]
public Customer Customer { get; set; }
public async Task<IActionResult> OnPostAsync()
{
if (!ModelState.IsValid)
{
return Page();
}
_context.Customers.Add(Customer);
await _context.SaveChangesAsync();
return RedirectToPage("./Index");
}
}
[BindProperty]
by se neměly používat u modelů obsahujících vlastnosti, které by klient neměl měnit. Další informace naleznete v tématu Overposting.
Razor Stránky ve výchozím nastavení sváže vlastnosti pouze s jinýmiGET
příkazy. Vazba na vlastnosti odebere nutnost zápisu kódu pro převod dat HTTP na typ modelu. Vazba omezuje kód pomocí stejné vlastnosti k vykreslení polí formuláře (<input asp-for="Customer.Name">
) a přijetí vstupu.
Upozornění
Z bezpečnostních důvodů se musíte přihlásit k vytvoření vazby GET
dat požadavku na vlastnosti modelu stránky. Před mapováním na vlastnosti ověřte vstup uživatele. Při přidělování scénářů, které se spoléhají na řetězec dotazu nebo hodnoty směrování, je vhodné vyjádřit výslovný souhlas s GET
vazbou.
Chcete-li vytvořit vazbu vlastnosti na GET
požadavky, nastavte vlastnost atributu [BindProperty]
SupportsGet
na true
:
[BindProperty(SupportsGet = true)]
Další informace najdete v tématu ASP.NET Core Community Standup: Bind on GET discussion (YouTube).
Pages/Create.cshtml
Kontrola souboru zobrazení:
@page
@model RazorPagesContacts.Pages.Customers.CreateModel
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
<p>Enter a customer name:</p>
<form method="post">
Name:
<input asp-for="Customer.Name" />
<input type="submit" />
</form>
- V předchozím kódu pomocné rutina
<input asp-for="Customer.Name" />
vstupní značky vytvoří vazbu elementu HTML<input>
naCustomer.Name
výraz modelu. @addTagHelper
zpřístupňuje pomocné rutiny značek.
Domovská stránka
Index.cshtml
je domovská stránka:
@page
@model RazorPagesContacts.Pages.Customers.IndexModel
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
<h1>Contacts home page</h1>
<form method="post">
<table class="table">
<thead>
<tr>
<th>ID</th>
<th>Name</th>
<th></th>
</tr>
</thead>
<tbody>
@foreach (var contact in Model.Customer)
{
<tr>
<td> @contact.Id </td>
<td>@contact.Name</td>
<td>
<!-- <snippet_Edit> -->
<a asp-page="./Edit" asp-route-id="@contact.Id">Edit</a> |
<!-- </snippet_Edit> -->
<!-- <snippet_Delete> -->
<button type="submit" asp-page-handler="delete" asp-route-id="@contact.Id">delete</button>
<!-- </snippet_Delete> -->
</td>
</tr>
}
</tbody>
</table>
<a asp-page="Create">Create New</a>
</form>
Přidružená PageModel
třída (Index.cshtml.cs
):
public class IndexModel : PageModel
{
private readonly CustomerDbContext _context;
public IndexModel(CustomerDbContext context)
{
_context = context;
}
public IList<Customer> Customer { get; set; }
public async Task OnGetAsync()
{
Customer = await _context.Customers.ToListAsync();
}
public async Task<IActionResult> OnPostDeleteAsync(int id)
{
var contact = await _context.Customers.FindAsync(id);
if (contact != null)
{
_context.Customers.Remove(contact);
await _context.SaveChangesAsync();
}
return RedirectToPage();
}
}
Soubor Index.cshtml
obsahuje následující revize:
<a asp-page="./Edit" asp-route-id="@contact.Id">Edit</a> |
Pomocný <a /a>
pomocník značky ukotveníasp-route-{value}
použil atribut k vygenerování odkazu na stránku Upravit. Odkaz obsahuje směrovací data s ID kontaktu. Například, https://localhost:5001/Edit/1
. Pomocné rutiny značek umožňují, aby se podíleli na vytváření a vykreslování elementů HTML v Razor souborech.
Soubor Index.cshtml
obsahuje kód pro vytvoření tlačítka pro odstranění pro každý kontakt zákazníka:
<button type="submit" asp-page-handler="delete" asp-route-id="@contact.Id">delete</button>
Vykreslený kód HTML:
<button type="submit" formaction="/Customers?id=1&handler=delete">delete</button>
Když se tlačítko pro odstranění vykreslí ve formátu HTML, jeho formaction obsahuje parametry pro:
- ID kontaktu zákazníka zadané atributem
asp-route-id
. - Vlastnost
handler
, určená atributemasp-page-handler
.
Po výběru tlačítka se na server odešle žádost o formulář POST
. Podle konvence je název metody obslužné rutiny vybrán na základě hodnoty handler
parametru podle schématu OnPost[handler]Async
.
Vzhledem k tomu, že handler
je delete
v tomto příkladu OnPostDeleteAsync
, metoda obslužné rutiny se používá ke zpracování POST
požadavku. asp-page-handler
Pokud je nastavena na jinou hodnotu, například remove
, je vybrána metoda obslužné rutiny s názvemOnPostRemoveAsync
.
public async Task<IActionResult> OnPostDeleteAsync(int id)
{
var contact = await _context.Customers.FindAsync(id);
if (contact != null)
{
_context.Customers.Remove(contact);
await _context.SaveChangesAsync();
}
return RedirectToPage();
}
Metoda OnPostDeleteAsync
:
id
Získá z řetězce dotazu.- Dotazuje databázi na kontakt zákazníka s
FindAsync
. - Pokud se najde kontakt zákazníka, odebere se a databáze se aktualizuje.
- Volání RedirectToPage přesměrování na kořenovou stránku indexu (
/Index
).
Soubor Edit.cshtml
@page "{id:int}"
@model RazorPagesContacts.Pages.Customers.EditModel
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
<h1>Edit Customer - @Model.Customer.Id</h1>
<form method="post">
<div asp-validation-summary="All"></div>
<input asp-for="Customer.Id" type="hidden" />
<div>
<label asp-for="Customer.Name"></label>
<div>
<input asp-for="Customer.Name" />
<span asp-validation-for="Customer.Name"></span>
</div>
</div>
<div>
<button type="submit">Save</button>
</div>
</form>
První řádek obsahuje direktivu @page "{id:int}"
. Omezení "{id:int}"
směrování informuje stránku, aby přijímala požadavky na stránku, která obsahuje int
směrovací data. Pokud požadavek na stránku neobsahuje směrovací data, která lze převést na , int
vrátí modul runtime chybu HTTP 404 (nenalezena). Pokud chcete, aby ID bylo volitelné, připojte ?
se k omezení trasy:
@page "{id:int?}"
Soubor Edit.cshtml.cs
:
public class EditModel : PageModel
{
private readonly CustomerDbContext _context;
public EditModel(CustomerDbContext context)
{
_context = context;
}
[BindProperty]
public Customer Customer { get; set; }
public async Task<IActionResult> OnGetAsync(int id)
{
Customer = await _context.Customers.FindAsync(id);
if (Customer == null)
{
return RedirectToPage("./Index");
}
return Page();
}
public async Task<IActionResult> OnPostAsync()
{
if (!ModelState.IsValid)
{
return Page();
}
_context.Attach(Customer).State = EntityState.Modified;
try
{
await _context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
throw new Exception($"Customer {Customer.Id} not found!");
}
return RedirectToPage("./Index");
}
}
Ověřování
Ověřovací pravidla:
- Jsou deklarativní zadané ve třídě modelu.
- Vynucují se všude v aplikaci.
Obor System.ComponentModel.DataAnnotations názvů poskytuje sadu předdefinovaných ověřovacích atributů, které se aplikují deklarativním způsobem na třídu nebo vlastnost. Objekty DataAnnotation také obsahují atributy formátování, jako [DataType]
je například formátování, a neposkytuje žádné ověření.
Customer
Zvažte model:
using System.ComponentModel.DataAnnotations;
namespace RazorPagesContacts.Models
{
public class Customer
{
public int Id { get; set; }
[Required, StringLength(10)]
public string Name { get; set; }
}
}
Pomocí následujícího Create.cshtml
souboru zobrazení:
@page
@model RazorPagesContacts.Pages.Customers.CreateModel
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
<p>Validation: customer name:</p>
<form method="post">
<div asp-validation-summary="ModelOnly"></div>
<span asp-validation-for="Customer.Name"></span>
Name:
<input asp-for="Customer.Name" />
<input type="submit" />
</form>
<script src="~/lib/jquery/dist/jquery.js"></script>
<script src="~/lib/jquery-validation/dist/jquery.validate.js"></script>
<script src="~/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.js"></script>
Předchozí kód:
Obsahuje ověřovací skripty jQuery a jQuery.
Pomocí pomocných rutin a
<span />
pomocných<div />
rutin značek povolíte:- Ověření na straně klienta
- Vykreslování chyby ověření
Vygeneruje následující kód HTML:
<p>Enter a customer name:</p> <form method="post"> Name: <input type="text" data-val="true" data-val-length="The field Name must be a string with a maximum length of 10." data-val-length-max="10" data-val-required="The Name field is required." id="Customer_Name" maxlength="10" name="Customer.Name" value="" /> <input type="submit" /> <input name="__RequestVerificationToken" type="hidden" value="<Antiforgery token here>" /> </form> <script src="/lib/jquery/dist/jquery.js"></script> <script src="/lib/jquery-validation/dist/jquery.validate.js"></script> <script src="/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.js"></script>
Publikování formuláře Vytvořit bez hodnoty názvu zobrazí chybovou zprávu "Pole Název je požadováno" ve formuláři. Pokud je v klientovi povolený JavaScript, zobrazí se v prohlížeči chyba bez publikování na server.
Atribut [StringLength(10)]
vygeneruje data-val-length-max="10"
vykreslený kód HTML. data-val-length-max
zabraňuje prohlížečům zadávat více než maximální zadanou délku. Pokud se nástroj, jako je Fiddler , používá k úpravám a přehrání příspěvku:
- S názvem delším než 10.
- Vrátí se chybová zpráva "Název pole musí být řetězec s maximální délkou 10".
Zvažte následující Movie
model:
using System;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace RazorPagesMovie.Models
{
public class Movie
{
public int ID { get; set; }
[StringLength(60, MinimumLength = 3)]
[Required]
public string Title { get; set; }
[Display(Name = "Release Date")]
[DataType(DataType.Date)]
public DateTime ReleaseDate { get; set; }
[Range(1, 100)]
[DataType(DataType.Currency)]
[Column(TypeName = "decimal(18, 2)")]
public decimal Price { get; set; }
[RegularExpression(@"^[A-Z]+[a-zA-Z\s]*$")]
[Required]
[StringLength(30)]
public string Genre { get; set; }
[RegularExpression(@"^[A-Z]+[a-zA-Z0-9""'\s-]*$")]
[StringLength(5)]
[Required]
public string Rating { get; set; }
}
}
Atributy ověření určují chování, které se má vynutit u vlastností modelu, na které se použijí:
MinimumLength
AtributyRequired
označují, že vlastnost musí mít hodnotu, ale nic nebrání uživateli v zadávání prázdného místa, aby toto ověření splnil.Atribut
RegularExpression
slouží k omezení toho, jaké znaky lze zadat. V předchozím kódu "Žánr":- Musí používat jenom písmena.
- První písmeno musí být velké. Prázdné znaky, čísla a speciální znaky nejsou povolené.
"
RegularExpression
Hodnocení":- Vyžaduje, aby první znak byl velkým písmenem.
- Umožňuje speciální znaky a čísla v následujících mezerách. "PG-13" je platné pro hodnocení, ale selže pro "Žánr".
Atribut
Range
omezuje hodnotu v konkrétním rozsahu.Atribut
StringLength
nastaví maximální délku vlastnosti řetězce a volitelně její minimální délku.Typy hodnot (například
decimal
, ,int
,float
DateTime
) jsou ze své podstaty povinné a nepotřebují[Required]
atribut.
Na stránce Vytvořit pro Movie
model se zobrazují chyby s neplatnými hodnotami:
Další informace naleznete v tématu:
Zpracování požadavků HEAD pomocí náhradní obslužné rutiny OnGet
HEAD
požadavky umožňují načtení hlaviček pro konkrétní prostředek. Na rozdíl od GET
požadavků HEAD
nevrací požadavky text odpovědi.
Obvykle se vytvoří obslužná rutina OnHead
a volá se pro HEAD
požadavky:
public void OnHead()
{
HttpContext.Response.Headers.Add("Head Test", "Handled by OnHead!");
}
Razor Stránky se vrátí zpět k volání OnGet
obslužné rutiny, pokud není definována žádná OnHead
obslužná rutina.
XSRF/CSRF a Razor stránky
Razor Stránky jsou chráněny ověřováním antiforgery. FormTagHelper vloží antiforgery tokeny do elementů formuláře HTML.
Použití rozložení, částečných, šablon a pomocných rutin značek se stránkami Razor
Stránky pracují se všemi možnostmi Razor modulu zobrazení. Rozložení, části, šablony, pomocné rutiny _ViewStart.cshtml
značek a _ViewImports.cshtml
fungují stejným způsobem jako u konvenčních Razor zobrazení.
Probereme tuto stránku tím, že využijeme některé z těchto možností.
Přidání stránky rozložení do Pages/Shared/_Layout.cshtml
:
<!DOCTYPE html>
<html>
<head>
<title>RP Sample</title>
<link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.css" />
</head>
<body>
<a asp-page="/Index">Home</a>
<a asp-page="/Customers/Create">Create</a>
<a asp-page="/Customers/Index">Customers</a> <br />
@RenderBody()
<script src="~/lib/jquery/dist/jquery.js"></script>
<script src="~/lib/jquery-validation/dist/jquery.validate.js"></script>
<script src="~/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.js"></script>
</body>
</html>
- Určuje rozložení každé stránky (pokud se stránka nevyhlásí z rozložení).
- Importuje struktury HTML, jako jsou JavaScript a šablony stylů.
- Obsah Razor stránky se vykresluje tam, kde
@RenderBody()
se volá.
Další informace najdete na stránce rozložení.
Vlastnost Layout je nastavena v Pages/_ViewStart.cshtml
:
@{
Layout = "_Layout";
}
Rozložení je ve složce Pages/Shared . Stránky hledají další zobrazení (rozložení, šablony, částečné) hierarchicky, počínaje stejnou složkou jako aktuální stránka. Rozložení ve složce Pages/Shared lze použít z libovolné Razor stránky ve složce Stránky .
Soubor rozložení by měl být ve složce Pages/Shared .
Doporučujeme, abyste soubor rozložení neuložili do složky Zobrazení nebo sdílené složky. Zobrazení nebo sdílení je vzor zobrazení MVC. Razor Stránky se mají spoléhat na hierarchii složek, nikoli na konvence cest.
Zobrazení hledání ze Razor stránky zahrnuje složku Stránky . Rozložení, šablony a části používané s řadiči MVC a konvenčními Razor zobrazeními fungují.
Pages/_ViewImports.cshtml
Přidejte soubor:
@namespace RazorPagesContacts.Pages
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
@namespace
je vysvětleno později v tomto kurzu. Direktiva @addTagHelper
přináší integrované pomocné rutiny značek na všechny stránky ve složce Pages .
Direktiva @namespace
nastavená na stránce:
@page
@namespace RazorPagesIntro.Pages.Customers
@model NameSpaceModel
<h2>Name space</h2>
<p>
@Model.Message
</p>
Direktiva @namespace
nastaví obor názvů stránky. Direktiva @model
nemusí zahrnovat obor názvů.
@namespace
Pokud je direktiva obsažena, _ViewImports.cshtml
zadaný obor názvů poskytuje předponu pro vygenerovaný obor názvů na stránce, která importuje direktivu@namespace
. Zbytek generovaného oboru názvů (část přípony) je tečkovaná relativní cesta mezi složkou obsahující _ViewImports.cshtml
a složkou obsahující stránku.
PageModel
Například třída Pages/Customers/Edit.cshtml.cs
explicitně nastaví obor názvů:
namespace RazorPagesContacts.Pages
{
public class EditModel : PageModel
{
private readonly AppDbContext _db;
public EditModel(AppDbContext db)
{
_db = db;
}
// Code removed for brevity.
Soubor Pages/_ViewImports.cshtml
nastaví následující obor názvů:
@namespace RazorPagesContacts.Pages
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
Vygenerovaný obor názvů stránky Pages/Customers/Edit.cshtml
Razor je stejný jako PageModel
třída.
@namespace
funguje také s konvenčními Razor zobrazeními.
Pages/Create.cshtml
Zvažte soubor zobrazení:
@page
@model RazorPagesContacts.Pages.Customers.CreateModel
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
<p>Validation: customer name:</p>
<form method="post">
<div asp-validation-summary="ModelOnly"></div>
<span asp-validation-for="Customer.Name"></span>
Name:
<input asp-for="Customer.Name" />
<input type="submit" />
</form>
<script src="~/lib/jquery/dist/jquery.js"></script>
<script src="~/lib/jquery-validation/dist/jquery.validate.js"></script>
<script src="~/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.js"></script>
Aktualizovaný Pages/Create.cshtml
soubor zobrazení s předchozím souborem _ViewImports.cshtml
rozložení:
@page
@model CreateModel
<p>Enter a customer name:</p>
<form method="post">
Name:
<input asp-for="Customer.Name" />
<input type="submit" />
</form>
V předchozím kódu _ViewImports.cshtml
importoval obor názvů a pomocné rutiny značek. Soubor rozložení naimportoval soubory JavaScriptu.
Razor Úvodní projekt Pages obsahuje Pages/_ValidationScriptsPartial.cshtml
objekt , který připojí ověření na straně klienta.
Další informace o částečných zobrazeních najdete v tématu Částečná zobrazení v ASP.NET Core.
Generování adres URL pro stránky
Stránka Create
, která byla zobrazena dříve, používá RedirectToPage
:
public class CreateModel : PageModel
{
private readonly CustomerDbContext _context;
public CreateModel(CustomerDbContext context)
{
_context = context;
}
public IActionResult OnGet()
{
return Page();
}
[BindProperty]
public Customer Customer { get; set; }
public async Task<IActionResult> OnPostAsync()
{
if (!ModelState.IsValid)
{
return Page();
}
_context.Customers.Add(Customer);
await _context.SaveChangesAsync();
return RedirectToPage("./Index");
}
}
Aplikace má následující strukturu souborů a složek:
/Pages
Index.cshtml
Privacy.cshtml
/Customers
Create.cshtml
Edit.cshtml
Index.cshtml
Stránky Pages/Customers/Create.cshtml
a Pages/Customers/Edit.cshtml
stránky se přesměrovávají na Pages/Customers/Index.cshtml
po úspěšném dokončení. Řetězec ./Index
je relativní název stránky použitý pro přístup k předchozí stránce. Slouží k vygenerování adres URL na Pages/Customers/Index.cshtml
stránku. Například:
Url.Page("./Index", ...)
<a asp-page="./Index">Customers Index Page</a>
RedirectToPage("./Index")
Absolutní název /Index
stránky slouží k vygenerování adres URL na Pages/Index.cshtml
stránku. Například:
Url.Page("/Index", ...)
<a asp-page="/Index">Home Index Page</a>
RedirectToPage("/Index")
Název stránky je cesta k stránce z kořenové složky /Pages včetně úvodní /
(například /Index
). Předchozí ukázky generování adres URL nabízejí vylepšené možnosti a funkční funkce při pevném kódování adresy URL. Generování adres URL používá směrování a může generovat a kódovat parametry podle toho, jak je trasa definovaná v cílové cestě.
Generování adres URL pro stránky podporuje relativní názvy. Následující tabulka ukazuje, která stránka indexu je vybrána pomocí různých RedirectToPage
parametrů v Pages/Customers/Create.cshtml
.
RedirectToPage(x) | Stránka |
---|---|
RedirectToPage("/Index") | Stránky/index |
RedirectToPage("./Index"); | Stránky/ Zákazníci/ Index |
RedirectToPage(".. /Index") | Stránky/index |
RedirectToPage("Index") | Stránky/ Zákazníci/ Index |
RedirectToPage("Index")
, RedirectToPage("./Index")
a RedirectToPage("../Index")
jsou relativní názvy. Parametr RedirectToPage
je kombinován s cestou aktuální stránky k výpočtu názvu cílové stránky.
Propojení relativního názvu je užitečné při vytváření lokalit se složitou strukturou. Pokud se relativní názvy používají k propojení mezi stránkami ve složce:
- Přejmenování složky nezlomí relativní odkazy.
- Odkazy nejsou poškozené, protože neobsahují název složky.
Pokud chcete přesměrovat na stránku v jiné oblasti, zadejte oblast:
RedirectToPage("/Index", new { area = "Services" });
Další informace najdete v tématu Oblasti v ASP.NET Core a Razor konvencích tras a aplikací v ASP.NET Core.
Atribut ViewData
Data lze předat na stránku s ViewDataAttribute. Vlastnosti s atributem [ViewData]
mají své hodnoty uložené a načtené z objektu ViewDataDictionary.
V následujícím příkladu AboutModel
platí [ViewData]
atribut pro Title
vlastnost:
public class AboutModel : PageModel
{
[ViewData]
public string Title { get; } = "About";
public void OnGet()
{
}
}
Na stránce O aplikaci přejděte na Title
vlastnost jako vlastnost modelu:
<h1>@Model.Title</h1>
V rozložení se nadpis přečte ze slovníku ViewData:
<!DOCTYPE html>
<html lang="en">
<head>
<title>@ViewData["Title"] - WebApplication</title>
...
TempData
ASP.NET Core zveřejňuje TempData. Tato vlastnost ukládá data, dokud se nečte. Tyto Keep metody Peek lze použít k prozkoumání dat bez odstranění. TempData
je užitečný pro přesměrování, pokud jsou data potřebná pro více než jeden požadavek.
Následující kód nastaví hodnotu Message
použití TempData
:
public class CreateDotModel : PageModel
{
private readonly AppDbContext _db;
public CreateDotModel(AppDbContext db)
{
_db = db;
}
[TempData]
public string Message { get; set; }
[BindProperty]
public Customer Customer { get; set; }
public async Task<IActionResult> OnPostAsync()
{
if (!ModelState.IsValid)
{
return Page();
}
_db.Customers.Add(Customer);
await _db.SaveChangesAsync();
Message = $"Customer {Customer.Name} added";
return RedirectToPage("./Index");
}
}
Následující kód v Pages/Customers/Index.cshtml
souboru zobrazuje hodnotu Message
použití TempData
.
<h3>Msg: @Model.Message</h3>
Model Pages/Customers/Index.cshtml.cs
stránky použije [TempData]
atribut na Message
vlastnost.
[TempData]
public string Message { get; set; }
Další informace najdete v tématu TempData.
Více obslužných rutin na stránku
Na následující stránce se vygenerují značky pro dva obslužné rutiny pomocí pomocné rutiny asp-page-handler
značek:
@page
@model CreateFATHModel
<html>
<body>
<p>
Enter your name.
</p>
<div asp-validation-summary="All"></div>
<form method="POST">
<div>Name: <input asp-for="Customer.Name" /></div>
<!-- <snippet_Handlers> -->
<input type="submit" asp-page-handler="JoinList" value="Join" />
<input type="submit" asp-page-handler="JoinListUC" value="JOIN UC" />
<!-- </snippet_Handlers> -->
</form>
</body>
</html>
Formulář v předchozím příkladu obsahuje dvě tlačítka pro odeslání, z nichž každý používá FormActionTagHelper
k odeslání na jinou adresu URL. Atribut asp-page-handler
je společníkem asp-page
. asp-page-handler
generuje adresy URL, které se odesílají do každé metody obslužné rutiny definované stránkou. asp-page
není zadán, protože ukázka odkazuje na aktuální stránku.
Model stránky:
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using RazorPagesContacts.Data;
namespace RazorPagesContacts.Pages.Customers
{
public class CreateFATHModel : PageModel
{
private readonly AppDbContext _db;
public CreateFATHModel(AppDbContext db)
{
_db = db;
}
[BindProperty]
public Customer Customer { get; set; }
public async Task<IActionResult> OnPostJoinListAsync()
{
if (!ModelState.IsValid)
{
return Page();
}
_db.Customers.Add(Customer);
await _db.SaveChangesAsync();
return RedirectToPage("/Index");
}
public async Task<IActionResult> OnPostJoinListUCAsync()
{
if (!ModelState.IsValid)
{
return Page();
}
Customer.Name = Customer.Name?.ToUpperInvariant();
return await OnPostJoinListAsync();
}
}
}
Předchozí kód používá pojmenované metody obslužné rutiny. Pojmenované metody obslužné rutiny jsou vytvořeny tak, že po a před Async
(pokud existují) text v názvuOn<HTTP Verb>
. V předchozím příkladu jsou metody stránky OnPostJoinListAsync a OnPostJoinListUCAsync. Při odebrání OnPost a Async jsou JoinList
názvy obslužných rutin a JoinListUC
.
<input type="submit" asp-page-handler="JoinList" value="Join" />
<input type="submit" asp-page-handler="JoinListUC" value="JOIN UC" />
Pomocí předchozího kódu je cesta URL, která se odešle.OnPostJoinListAsync
https://localhost:5001/Customers/CreateFATH?handler=JoinList
Cesta URL, která se odešle, OnPostJoinListUCAsync
je https://localhost:5001/Customers/CreateFATH?handler=JoinListUC
.
Vlastní trasy
Direktivu použijte k @page
:
- Zadejte vlastní trasu na stránku. Můžete například nastavit
/Some/Other/Path
@page "/Some/Other/Path"
trasu na stránku O aplikaci . - Připojte segmenty k výchozí trase stránky. Například segment "item" lze přidat do výchozí trasy stránky s
@page "item"
. - Připojte parametry k výchozí trase stránky. Například parametr
id
ID , může být vyžadován pro stránku s@page "{id}"
.
Podporuje se kořenová relativní cesta určená vlnovkou (~
) na začátku cesty. Například @page "~/Some/Other/Path"
je stejný jako @page "/Some/Other/Path"
.
Pokud se vám řetězec ?handler=JoinList
dotazu v adrese URL nelíbí, změňte trasu tak, aby název obslužné rutiny vložil do části cesty adresy URL. Trasu lze přizpůsobit přidáním šablony trasy uzavřené do dvojitých uvozovek za direktivu @page
.
@page "{handler?}"
@model CreateRouteModel
<html>
<body>
<p>
Enter your name.
</p>
<div asp-validation-summary="All"></div>
<form method="POST">
<div>Name: <input asp-for="Customer.Name" /></div>
<input type="submit" asp-page-handler="JoinList" value="Join" />
<input type="submit" asp-page-handler="JoinListUC" value="JOIN UC" />
</form>
</body>
</html>
Pomocí předchozího kódu je cesta URL, která se odešle.OnPostJoinListAsync
https://localhost:5001/Customers/CreateFATH/JoinList
Cesta URL, která se odešle, OnPostJoinListUCAsync
je https://localhost:5001/Customers/CreateFATH/JoinListUC
.
Následující ?
handler
znamená, že parametr trasy je volitelný.
Pokročilá konfigurace a nastavení
Většina aplikací nevyžaduje konfiguraci a nastavení v následujících částech.
Pokud chcete konfigurovat pokročilé možnosti, použijte AddRazorPages přetížení, které konfiguruje RazorPagesOptions:
public void ConfigureServices(IServiceCollection services)
{
services.AddRazorPages(options =>
{
options.RootDirectory = "/MyPages";
options.Conventions.AuthorizeFolder("/MyPages/Admin");
});
}
RazorPagesOptions Použijte k nastavení kořenového adresáře pro stránky nebo přidání konvencí aplikačního modelu pro stránky. Další informace o konvencích najdete v tématu Razor Konvence autorizace stránek.
Pokud chcete předkompilovat zobrazení, podívejte se Razor na kompilaci zobrazení.
Určete, že Razor stránky jsou v kořenovém adresáři obsahu.
Ve výchozím nastavení Razor jsou stránky kořenové v adresáři /Pages . Přidejte WithRazorPagesAtContentRoot , abyste určili, že vaše Razor stránky jsou v kořenovém adresáři obsahu (ContentRootPath) aplikace:
public void ConfigureServices(IServiceCollection services)
{
services.AddRazorPages(options =>
{
options.Conventions.AuthorizeFolder("/MyPages/Admin");
})
.WithRazorPagesAtContentRoot();
}
Určení, že Razor stránky jsou ve vlastním kořenovém adresáři
Přidejte WithRazorPagesRoot , abyste určili, že Razor stránky jsou ve vlastním kořenovém adresáři v aplikaci (zadejte relativní cestu):
public void ConfigureServices(IServiceCollection services)
{
services.AddRazorPages(options =>
{
options.Conventions.AuthorizeFolder("/MyPages/Admin");
})
.WithRazorPagesRoot("/path/to/razor/pages");
}
Další materiály
- Viz Začínáme se stránkamiRazor, které vycházejí z tohoto úvodu.
- Autorizace atributu a Razor stránek
- Stažení nebo zobrazení ukázkového kódu
- Přehled ASP.NET Core
- RazorReferenční informace k syntaxi pro ASP.NET Core
- Oblasti v ASP.NET Core
- Kurz: Začínáme se stránkami Razor v ASP.NET Core
- RazorZásady autorizace stránek v ASP.NET Core
- RazorSměrování stránek a konvence aplikací v ASP.NET Core
- RazorTesty jednotek stránek v ASP.NET Core
- Částečná zobrazení v ASP.NET Core
- Prerender a integrace komponent ASP.NET Core Razor