Megosztás a következőn keresztül:


A ASP.NET Core Razor lapjainak bemutatása

Rick Anderson, Dave Brock, és Kirk Larkin

Jegyzet

Ez nem a cikk legújabb verziója. Az aktuális kiadás megtekintéséhez lásd a cikk .NET 9-es verzióját .

Figyelmeztetés

A ASP.NET Core ezen verziója már nem támogatott. További információ: .NET és .NET Core támogatási szabályzat. Az aktuális kiadást lásd ennek a cikknek a .NET 9-es verziójában .

Fontos

Ezek az információk egy olyan előzetes termékre vonatkoznak, amelyet a kereskedelmi forgalomba kerülés előtt jelentősen módosíthatnak. A Microsoft nem vállal kifejezett vagy hallgatólagos szavatosságot az itt megadott információkra vonatkozóan.

Az aktuális kiadáshoz lásd a jelen cikk .NET 9-es verzióját .

Razor Lapok egyszerűbbé és hatékonyabbá teheti a lapközpontú forgatókönyvek kódolását, mint a vezérlők és nézetek használata.

Ha olyan oktatóanyagot keres, amely a Model-View-Controller megközelítést használja, tekintse meg Az első lépések ASP.NET Core MVCcímű témakört.

Ez a dokumentum bevezetést nyújt a Razor oldalakhoz. Ez nem lépésenkénti oktatóanyag. Ha néhány szakaszt túl bonyolultnak talál, tekintse meg a Kezdje a Razor Lapokcímmel. A ASP.NET Core áttekintését a ASP.NET Corebevezetési útmutatója ismerteti.

Előfeltételek

Razor Pages-projekt létrehozása

A Razor Pages-projekt létrehozásának részletes útmutatását A LapokRazor használatának első lépései című témakörben találja.

Razor lapok

Razor Lapok engedélyezve van a 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();

Az előző kódban:

Fontolja meg az alapoldalt:

@page

<h1>Hello, world!</h1>
<h2>The time on the server is @DateTime.Now</h2>

Az előző kód nagyon hasonlít a vezérlőkkel és nézetekkel rendelkező ASP.NET Core-alkalmazásokban használt Razor nézetfájlra,. A @page irányelv az, amitől ez más. @page MVC-műveletté teszi a fájlt, ami azt jelenti, hogy közvetlenül kezeli a kéréseket, anélkül, hogy egy vezérlőn keresztülmennék. @page kell lennie az első Razor irányelvnek egy lapon. @page hatással van más Razor szerkezetek viselkedésére. Razor Lapok fájlnevek .cshtml utótagot tartalmaz.

A következő két fájlban egy hasonló lap jelenik meg, amely egy PageModel osztályt használ. A Pages/Index2.cshtml fájl:

@page
@using RazorPagesIntro.Pages
@model Index2Model

<h2>Separate page model</h2>
<p>
    @Model.Message
</p>

A Pages/Index2.cshtml.cs oldalmodell:

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 }";
        }
    }
}

Konvenció szerint a PageModel osztályfájl neve megegyezik a Razor lapfájl nevével, .cs hozzáfűzve. Az előző Razor oldal például Pages/Index2.cshtml. A PageModel osztályt tartalmazó fájl neve Pages/Index2.cshtml.cs.

A lapok URL-útvonalainak társítását a lap fájlrendszerbeli helye határozza meg. Az alábbi táblázat egy Razor oldal elérési útját és a megfelelő URL-címet mutatja:

Fájlnév és elérési út egyező URL-cím
/Pages/Index.cshtml / vagy /Index
/Pages/Contact.cshtml /Contact
/Pages/Store/Contact.cshtml /Store/Contact
/Pages/Store/Index.cshtml /Store vagy /Store/Index

Megjegyzések:

  • A futtatókörnyezet alapértelmezés szerint Razor Pages-fájlokat keres a Pages mappában.
  • Index az alapértelmezett lap, ha egy URL-cím nem tartalmaz lapot.

Egyszerű űrlap írása

Razor Pages úgy lett kialakítva, hogy könnyen implementálhatóvá tegye a webböngészőkben használt gyakori mintákat egy alkalmazás létrehozásakor. Modellkötési, Címkesegítőés HTML-segédek a Razor Laposztályban meghatározott tulajdonságokkal működnek együtt. Fontolja meg a Contact modell alapszintű "kapcsolatfelvétel" űrlapjának implementálását ismertető oldalt:

A dokumentumban szereplő minták esetében a DbContext inicializálódik a Program.cs fájlban.

A memóriában lévő adatbázishoz szükség van a Microsoft.EntityFrameworkCore.InMemory NuGet-csomagra.

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();

Az adatmodell:

using System.ComponentModel.DataAnnotations;

namespace RazorPagesContacts.Models
{
    public class Customer
    {
        public int Id { get; set; }

        [Required, StringLength(10)]
        public string? Name { get; set; }
    }
}

Az adatbázis környezet:

using Microsoft.EntityFrameworkCore;

namespace RazorPagesContacts.Data
{
    public class CustomerDbContext : DbContext
    {
        public CustomerDbContext (DbContextOptions<CustomerDbContext> options)
            : base(options)
        {
        }

        public DbSet<RazorPagesContacts.Models.Customer> Customer => Set<RazorPagesContacts.Models.Customer>();
    }
}

A Pages/Customers/Create.cshtml nézetfájl:

@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>

A Pages/Customers/Create.cshtml.cs oldalmodell:

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();
        }

        if (Customer != null) _context.Customer.Add(Customer);
        await _context.SaveChangesAsync();

        return RedirectToPage("./Index");
    }
}

Konvenció szerint a PageModel osztály neve <PageName>Model, és ugyanabban a névtérben van, mint a lap.

A PageModel osztály lehetővé teszi a lap logikájának elválasztását a bemutatótól. Meghatározza a lapra küldött kérelmek és a lap rendereléséhez használt adatok lapkezelőit. Ez az elkülönítés a következőt teszi lehetővé:

A lap egy OnPostAsynckezelőmetódussal rendelkezik, amely POST kérelmeken fut (amikor egy felhasználó közzéteszi az űrlapot). Bármely HTTP-ige kezelő metódusai hozzáadhatók. A leggyakoribb kezelők a következők:

  • OnGet az oldalhoz szükséges állapot inicializálásához. Az előző kódban a OnGet metódus megjeleníti a Create.cshtmlRazor lapot.
  • OnPost az űrlapbeküldések kezeléséhez.

A Async elnevezési utótag nem kötelező, de a gyakorlatban gyakran alkalmazzák az aszinkron függvényekhez. Az előző kód Razor lapokra jellemző.

Ha ismeri ASP.NET vezérlőket és nézeteket használó alkalmazásokat:

  • Az előző példában szereplő OnPostAsync kód a tipikus vezérlőkódhoz hasonlóan néz ki.
  • Az MVC prmitívek többsége, mint például a modell-összerendelés, érvényesítés, és a műveleteredmények, ugyanúgy működnek a vezérlőknél és Razor oldalaknál.

Az előző OnPostAsync metódus:

[BindProperty]
public Customer? Customer { get; set; }

public async Task<IActionResult> OnPostAsync()
{
    if (!ModelState.IsValid)
    {
        return Page();
    }

    if (Customer != null) _context.Customer.Add(Customer);
    await _context.SaveChangesAsync();

    return RedirectToPage("./Index");
}

A OnPostAsyncalapfolyamata:

Ellenőrizze az érvényesítési hibákat.

  • Ha nincsenek hibák, mentse az adatokat és az átirányítást.
  • Ha hibák merülnek fel, a lapot ismét megjelenítheti érvényesítési üzenetekkel. A rendszer sok esetben érvényesítési hibákat észlel az ügyfélen, és soha nem küldi el a kiszolgálónak.

A Pages/Customers/Create.cshtml fájl nézete:

@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>

A Pages/Customers/Create.cshtmláltal készített 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>

Az előző kódban található űrlap beküldése:

  • Érvényes adatokkal:

    • A OnPostAsync kezelő metódus meghívja a RedirectToPage segédmetódust. RedirectToPage a RedirectToPageResultegy példányát adja vissza. RedirectToPage:

      • Ez egy művelet eredménye.
      • Hasonló a RedirectToAction vagy a RedirectToRoute (vezérlőkben és nézetekben használatos).
      • Az oldalakat testre szabva van. Az előző példában átirányítja a gyökérindex lapra (/Index). a Lapok szakasz URL-címének generálása című szakaszban található.
  • Az érvényesítési hibák, amelyeket a kiszolgálónak továbbítottak:

    • A OnPostAsync kezelő metódus meghívja a Page segédmetódust. Page a PageResultegy példányát adja vissza. A Page visszatérése hasonló a vezérlők műveleteinek Viewvisszatéréséhez. PageResult egy kezelőmetódus alapértelmezett visszatérési típusa. Egy olyan kezelőmetódus, amely void-t visszaad, rendereli a lapot.
    • Az előző példában az űrlap érték nélküli elküldése ModelState.IsValid hamis értéket ad vissza. Ebben a mintában nem jelennek meg érvényesítési hibák az ügyfélen. Az érvényesítési hibakezelésről a dokumentum későbbi részében lesz szó.
    [BindProperty]
    public Customer? Customer { get; set; }
    
    public async Task<IActionResult> OnPostAsync()
    {
        if (!ModelState.IsValid)
        {
            return Page();
        }
    
        if (Customer != null) _context.Customer.Add(Customer);
        await _context.SaveChangesAsync();
    
        return RedirectToPage("./Index");
    }
    
  • Az ügyféloldali ellenőrzés által észlelt érvényesítési hibák esetén:

    • Az adatok nem közzétéve a kiszolgálóra.
    • Az ügyféloldali érvényesítést a dokumentum későbbi részében ismertetik.

A Customer tulajdonság [BindProperty] attribútum használatával vesz részt a modellkötésben.

[BindProperty]
public Customer? Customer { get; set; }

public async Task<IActionResult> OnPostAsync()
{
    if (!ModelState.IsValid)
    {
        return Page();
    }

    if (Customer != null) _context.Customer.Add(Customer);
    await _context.SaveChangesAsync();

    return RedirectToPage("./Index");
}

[BindProperty] nem kellene használni olyan modelleken, amelyek olyan tulajdonságokat tartalmaznak, amelyeket az ügyfél nem módosíthat. További információért lásd a Túlposztolásrészt.

Razor lapok alapértelmezés szerint csak nemGET igékkel kötik össze a tulajdonságokat. A tulajdonságokhoz való kötés nem igényli a HTTP-adatok modelltípussá alakításához szükséges kód írását. A kötés azzal csökkenti a kódot, hogy ugyanazt a tulajdonságot használja az űrlapmezők rendereléséhez (<input asp-for="Customer.Name">), és elfogadja a bemenetet.

Figyelmeztetés

Biztonsági okokból be kell kapcsolnia a GET lekérési adat oldalmodell tulajdonságokhoz kötését. Ellenőrizze a felhasználói bemenetet, mielőtt tulajdonságokra megfelelteti. A GET kötés használata akkor hasznos, ha olyan forgatókönyveket kezel, amelyek lekérdezési sztringre vagy útvonalértékekre támaszkodnak.

Ha egy tulajdonságot GET kérelmekhez szeretne kötni, állítsa a [BindProperty] attribútum SupportsGet tulajdonságát true:

[BindProperty(SupportsGet = true)]

További információért lásd: ASP.NET Core Community Standup: Bind on GET beszélgetés (YouTube).

A Pages/Customers/Create.cshtml nézetfájl áttekintése:

@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>
  • Az előző kódban a bemeneti címke segédje<input asp-for="Customer.Name" /> a HTML-<input> elemet a Customer.Name modellkifejezéshez köti.
  • @addTagHelper elérhetővé teszi a címkesegítőket.

A kezdőlap

Index.cshtml a kezdőlap:

@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>
        @if (Model.Customers != null)
        {
            foreach (var contact in Model.Customers)
            {
                <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>

A társított PageModel osztály (Index.cshtml.cs):

public class IndexModel : PageModel
{
    private readonly Data.CustomerDbContext _context;
    public IndexModel(Data.CustomerDbContext context)
    {
        _context = context;
    }

    public IList<Customer>? Customers { get; set; }

    public async Task OnGetAsync()
    {
        Customers = await _context.Customer.ToListAsync();
    }

    public async Task<IActionResult> OnPostDeleteAsync(int id)
    {
        var contact = await _context.Customer.FindAsync(id);

        if (contact != null)
        {
            _context.Customer.Remove(contact);
            await _context.SaveChangesAsync();
        }

        return RedirectToPage();
    }
}

A Index.cshtml fájl a következő jelöléseket tartalmazza:

<a asp-page="./Edit" asp-route-id="@contact.Id">Edit</a> |

A <a /a>horgonycímke-segéd a asp-route-{value} attribútumot használta a Szerkesztés lapra mutató hivatkozás létrehozásához. A hivatkozás útvonaladatokat tartalmaz a kapcsolati azonosítóval. Például https://localhost:5001/Edit/1. A címkesegédek lehetővé teszik, hogy a kiszolgálóoldali kód részt vegyen a HTML-elemek Razor fájlokban történő létrehozásában és megjelenítésében.

A Index.cshtml fájl jelöléseket tartalmaz a törlési gomb létrehozásához minden ügyfél-kapcsolattartóhoz.

<button type="submit" asp-page-handler="delete" asp-route-id="@contact.Id">delete</button>

A megjelenített HTML:

<button type="submit" formaction="/Customers?id=1&amp;handler=delete">delete</button>

Ha a törlés gombot HTML-ben jelenítik meg, a formaction tartalmazza a következő paramétereket:

  • A asp-route-id attribútum által megadott ügyfélkapcsolati azonosító.
  • handler, amelyet a asp-page-handler attribútum határoz meg.

Ha a gomb ki van jelölve, a rendszer egy űrlapot POST kérést küld a kiszolgálónak. Konvenció szerint a kezelőmetódus neve a handler paraméter értéke alapján van kiválasztva a séma OnPost[handler]Asyncszerint.

Mivel a handler ebben a példában delete, a OnPostDeleteAsync kezelőmetódus a POST kérés feldolgozására szolgál. Ha a asp-page-handler más értékre van állítva, például remove, akkor a rendszer kiválaszt egy OnPostRemoveAsync nevű kezelőmetódust.

public async Task<IActionResult> OnPostDeleteAsync(int id)
{
    var contact = await _context.Customer.FindAsync(id);

    if (contact != null)
    {
        _context.Customer.Remove(contact);
        await _context.SaveChangesAsync();
    }

    return RedirectToPage();
}

A OnPostDeleteAsync módszer:

  • Lekéri a id az lekérdezési sztringből.
  • Lekérdezi az adatbázisból az FindAsyncazonosítójú ügyfélkapcsolatot.
  • Ha az ügyfél kapcsolattartója megtalálható, az el lesz távolítva, és az adatbázis frissül.
  • Meghívja RedirectToPage, hogy átirányítsa az index gyökéroldalára (/Index).

Az Edit.cshtml fájl

@page "{id:int}"
@model RazorPagesContacts.Pages.Customers.EditModel

@{
    ViewData["Title"] = "Edit";
}

<h1>Edit</h1>

<h4>Customer</h4>
<hr />
<div class="row">
    <div class="col-md-4">
        <form method="post">
            <div asp-validation-summary="ModelOnly" class="text-danger"></div>
            <input type="hidden" asp-for="Customer!.Id" />
            <div class="form-group">
                <label asp-for="Customer!.Name" class="control-label"></label>
                <input asp-for="Customer!.Name" class="form-control" />
                <span asp-validation-for="Customer!.Name" class="text-danger"></span>
            </div>
            <div class="form-group">
                <input type="submit" value="Save" class="btn btn-primary" />
            </div>
        </form>
    </div>
</div>

<div>
    <a asp-page="./Index">Back to List</a>
</div>

@section Scripts {
    @{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}

Az első sor tartalmazza a @page "{id:int}" irányelvet. Az útválasztási korlátozás "{id:int}" arra utasítja a lapot, hogy fogadja el az int útvonaladatokat tartalmazó lapra irányuló kéréseket. Ha a lapra irányuló kérések nem tartalmaznak intkonvertálható útvonaladatokat, a futtatókörnyezet HTTP 404-es (nem található) hibát ad vissza. Ha az azonosítót nem kötelező megadni, fűzze hozzá ? az útvonalkorlátozáshoz:

@page "{id:int?}"

A Edit.cshtml.cs fájl:

public class EditModel : PageModel
{
    private readonly RazorPagesContacts.Data.CustomerDbContext _context;

    public EditModel(RazorPagesContacts.Data.CustomerDbContext context)
    {
        _context = context;
    }

    [BindProperty]
    public Customer? Customer { get; set; }

    public async Task<IActionResult> OnGetAsync(int? id)
    {
        if (id == null)
        {
            return NotFound();
        }

        Customer = await _context.Customer.FirstOrDefaultAsync(m => m.Id == id);
        
        if (Customer == null)
        {
            return NotFound();
        }
        return Page();
    }

    // To protect from overposting attacks, enable the specific properties you want to bind to.
    // For more details, see https://aka.ms/RazorPagesCRUD.
    public async Task<IActionResult> OnPostAsync()
    {
        if (!ModelState.IsValid)
        {
            return Page();
        }

        if (Customer != null)
        {
            _context.Attach(Customer).State = EntityState.Modified;

            try
            {
                await _context.SaveChangesAsync();
            }
            catch (DbUpdateConcurrencyException)
            {
                if (!CustomerExists(Customer.Id))
                {
                    return NotFound();
                }
                else
                {
                    throw;
                }
            }
        }

        return RedirectToPage("./Index");
    }

    private bool CustomerExists(int id)
    {
        return _context.Customer.Any(e => e.Id == id);
    }
}

Érvényesítés

Érvényesítési szabályok:

  • Deklaratív módon vannak megadva a modellosztályban.
  • Az alkalmazásban mindenhol érvényesítve vannak.

A System.ComponentModel.DataAnnotations névtér olyan beépített érvényesítési attribútumokat biztosít, amelyeket deklaratív módon alkalmaz egy osztályra vagy tulajdonságra. A DataAnnotations olyan formázási attribútumokat is tartalmaz, mint a [DataType], amelyek segítenek a formázásban, és nem biztosítanak semmilyen ellenőrzést.

Fontolja meg a Customer modellt:

using System.ComponentModel.DataAnnotations;

namespace RazorPagesContacts.Models
{
    public class Customer
    {
        public int Id { get; set; }

        [Required, StringLength(10)]
        public string? Name { get; set; }
    }
}

A következő Create.cshtml nézetfájl használata:

@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>

Az előző kód:

  • JQuery- és jQuery-érvényesítési szkripteket tartalmaz.

  • A <div /> és a <span />Címkesegítő használatával lehetővé teszi a következő funkciókat:

    • Ügyféloldali ellenőrzés.
    • Érvényesítési hiba megjelenítés során.
  • A következő HTML-t hozza létre:

    <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>
    

Ha névérték nélkül küldi el a Létrehozás űrlapot, az "A Név mező kötelező" hibaüzenet jelenik meg az űrlapon. Ha a JavaScript engedélyezve van az ügyfélen, a böngésző a kiszolgálóra való közzététel nélkül jeleníti meg a hibát.

A [StringLength(10)] attribútum a renderelt HTML-ben hoz létre data-val-length-max="10". data-val-length-max megakadályozza, hogy a böngészők a megadott maximális hossznál többet adjanak meg. Ha olyan eszközt használ, mint Fiddler a bejegyzés szerkesztésére és lejátszására:

  • Tíz karakternél hosszabb névvel.
  • A következő hibaüzenet jelenik meg: "A mezőnévnek legfeljebb 10 hosszúságú sztringnek kell lennie".

Fontolja meg a következő Movie modellt:

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; }
    }
}

Az érvényesítési attribútumok a következő modelltulajdonságokon érvényesítendő viselkedést adják meg:

  • A Required és MinimumLength attribútumok azt jelzik, hogy egy tulajdonságnak rendelkeznie kell értékkel, de semmi sem akadályozza meg, hogy a felhasználó üres területre lépjen az ellenőrzés teljesítéséhez.

  • A RegularExpression attribútummal korlátozható, hogy mely karakterek adhatóak meg. Az előző kódban a "Műfaj":

    • Csak betűket szabad használni.
    • Az első betűnek nagybetűsnek kell lennie. A szóköz, a számok és a speciális karakterek nem engedélyezettek.
  • A RegularExpression "Értékelés":

    • Az első karakternek nagybetűsnek kell lennie.
    • Lehetővé teszi a speciális karaktereket és számokat a következő szóközökben. A "PG-13" érvényes egy minősítésre, de nem felel meg a "Műfaj" kifejezésnek.
  • A Range attribútum egy adott tartományon belülre korlátozza az értéket.

  • A StringLength attribútum egy sztringtulajdonság maximális hosszát és opcionálisan minimális hosszát állítja be.

  • Az értéktípusokra (például decimal, int, float, DateTime) alapvetően szükség van, és nincs szükség a [Required] attribútumra.

A Movie modell Létrehozás lapja érvénytelen értékeket tartalmazó hibákat jelenít meg:

Több jQuery ügyféloldali érvényesítési hibával rendelkező filmnézet-űrlap

További információ:

CSS-elkülönítés

A CSS-stílusok elkülönítése az egyes lapokra, nézetekre és összetevőkre a csökkentés vagy az elkerülése érdekében:

  • A globális stílusokkal kapcsolatos függőségek, amelyek fenntartása nehézkes lehet.
  • Stílusütközések beágyazott tartalomban.

Ha egy hatókörű CSS-fájlt szeretne hozzáadni egy laphoz vagy nézethez, helyezze el a CSS-stílusokat a .cshtml fájl nevének megfelelő .cshtml.css társfájlba. Az alábbi példában egy Index.cshtml.css fájl olyan CSS-stílusokat biztosít, amelyek csak a Index.cshtml lapra vagy nézetre vonatkoznak.

Pages/Index.cshtml.css (Razor oldalak) vagy Views/Index.cshtml.css (MVC):

h1 {
    color: red;
}

A CSS elkülönítése a létrehozáskor történik. A keretrendszer újraírja a CSS-választókat, hogy megfeleljenek az alkalmazás oldalai vagy nézetei által megjelenített korrektúrának. Az újraírt CSS-stílusok kötegelve vannak, és statikus objektumként jönnek létre, {APP ASSEMBLY}.styles.css. A helyőrző {APP ASSEMBLY} a projekt szerelvényneve. A csomagban lévő CSS-stílusokra mutató hivatkozás az alkalmazás elrendezésébe kerül.

Az alkalmazás <head>Pages/Shared/_Layout.cshtml (Razor Oldalak) vagy Views/Shared/_Layout.cshtml (MVC) tartalmában adja hozzá vagy erősítse meg a csatolt CSS-stílusokra mutató hivatkozás jelenlétét:

<link rel="stylesheet" href="~/{APP ASSEMBLY}.styles.css" />

Az alábbi példában az alkalmazás szerelvényazonosítója WebApp:

<link rel="stylesheet" href="WebApp.styles.css" />

A hatókörrel rendelkező CSS-fájlban definiált stílusok csak az egyező fájl renderelt kimenetére lesznek alkalmazva. Az előző példában az alkalmazásban máshol definiált h1 CSS-deklarációk nem ütköznek a Indexcímsorstílusával. A CSS-stílus kaszkádolt és öröklési szabályai továbbra is érvényben maradnak a hatókörön belüli CSS-fájlok esetében. Például a Index.cshtml fájl egy <h1> elemére alkalmazott stílusok felülbírálják a hatókörű CSS-fájl stílusait Index.cshtml.css.

Jegyzet

Annak érdekében, hogy a CSS-stílusok elkülönítése biztosítható legyen az összekapcsolás során, a CSS importálása Razor kódblokkokban nem támogatott.

A CSS-elkülönítés csak HTML-elemekre vonatkozik. A CSS elkülönítése nem támogatott tagsegítőkesetén.

A csomagolt CSS-fájlban minden lap, nézet vagy Razor összetevő egy hatókörazonosítóhoz van társítva b-{STRING}formátumban, ahol a {STRING} helyőrző egy tíz karakterből álló sztring, amelyet a keretrendszer hoz létre. Az alábbi példa egy Razor Pages-alkalmazás Index lapjának előző <h1> elemének stílusát ismerteti:

/* /Pages/Index.cshtml.rz.scp.css */
h1[b-3xxtam6d07] {
    color: red;
}

Azon Index lapon, amelyen a CSS-stílust alkalmazza a csomagban lévő fájlból, a hatókörazonosító HTML-attribútumként van hozzáfűzve:

<h1 b-3xxtam6d07>

Az azonosító egyedi az alkalmazás számára. A létrehozás során egy projektcsomag jön létre a konvencióval {STATIC WEB ASSETS BASE PATH}/Project.lib.scp.css, ahol a helyőrző {STATIC WEB ASSETS BASE PATH} a statikus webeszközök alapelérési útja.

Ha más projekteket használ, például NuGet-csomagokat vagy Razor osztálykódtárakat, a csomagban lévő fájl:

  • CsS-importálást használó stílusokra hivatkozik.
  • Nem a stílusokat használó alkalmazás statikus webes objektumaként van közzétéve.

CSS-előfeldolgozó támogatása

A CSS-előfeldolgozók olyan funkciók használatával fejlesztik a CSS-fejlesztést, mint a változók, a beágyazás, a modulok, a mixins és az öröklés. Bár a CSS-elkülönítés natív módon nem támogatja a CSS-előfeldolgozókat( például Sass vagy Less), a CSS-előfeldolgozók integrálása zökkenőmentes, amíg az előfeldolgozó összeállítása még azelőtt történik, hogy a keretrendszer újraírja a CSS-választókat a buildelési folyamat során. A Visual Studio használatával, például konfigurálja a meglévő előprocesszor-fordítást a Build előtti feladatként a Visual Studio Feladatfuttató Böngészőjében.

Számos külső NuGet-csomag, például AspNetCore.SassCompiler, képes SASS-/SCSS-fájlokat fordítani a buildelési folyamat elején, mielőtt a CSS elkülönítése megtörténik, és nincs szükség további konfigurációra.

CSS-elkülönítés konfigurálása

A CSS-elkülönítés lehetővé teszi bizonyos speciális forgatókönyvek konfigurálásának engedélyezését, például ha függőségek vannak a meglévő eszközöktől vagy munkafolyamatoktól.

Hatókörazonosító formátumának testreszabása

Ebben a szakaszban a {Pages|Views} helyőrző vagy Pages a Razor Pages-alkalmazásokhoz, vagy Views az MVC-alkalmazásokhoz.

A hatókörazonosítók alapértelmezés szerint a b-{STRING}formátumot használják, ahol a {STRING} helyőrző a keretrendszer által létrehozott tíz karakterből áll. A hatókörazonosító formátumának testreszabásához frissítse a projektfájlt egy kívánt mintára:

<ItemGroup>
  <None Update="{Pages|Views}/Index.cshtml.css" CssScope="custom-scope-identifier" />
</ItemGroup>

Az előző példában a Index.cshtml.css számára generált CSS a tartományazonosítót b-{STRING}-ről custom-scope-identifier-re módosítja.

Hatókörazonosítók használatával érje el az öröklést hatókörrel rendelkező CSS-fájlokkal. A következő projektfájl-példában egy BaseView.cshtml.css fájl a nézetek gyakori stílusát tartalmazza. Egy DerivedView.cshtml.css fájl örökli ezeket a stílusokat.

<ItemGroup>
  <None Update="{Pages|Views}/BaseView.cshtml.css" CssScope="custom-scope-identifier" />
  <None Update="{Pages|Views}/DerivedView.cshtml.css" CssScope="custom-scope-identifier" />
</ItemGroup>

A helyettesítő karakter (*) operátorral több fájlban oszthat meg hatókör-azonosítókat:

<ItemGroup>
  <None Update="{Pages|Views}/*.cshtml.css" CssScope="custom-scope-identifier" />
</ItemGroup>

Statikus webes objektumok alapútvonalának módosítása

A hatókörbe tartozó CSS-fájl az alkalmazás gyökerénél jön létre. A projektfájlban használja a StaticWebAssetBasePath tulajdonságot az alapértelmezett elérési út módosításához. Az alábbi példa a hatókörön belüli CSS-fájlt és az alkalmazás többi objektumát a _content elérési útra helyezi:

<PropertyGroup>
  <StaticWebAssetBasePath>_content/$(PackageId)</StaticWebAssetBasePath>
</PropertyGroup>

Automatikus kötegelés letiltása

Ha nem szeretné, hogy a keretrendszer futásidőben tegye közzé és betöltse a hatókörben lévő fájlokat, használja a DisableScopedCssBundling tulajdonságot. A tulajdonság használatakor más eszközök vagy folyamatok felelősek az izolált CSS-fájlok obj könyvtárból való levételéért, valamint azok futtatókörnyezetben való közzétételéért és betöltéséért:

<PropertyGroup>
  <DisableScopedCssBundling>true</DisableScopedCssBundling>
</PropertyGroup>

Razor osztálykódtár (RCL) támogatása

Ha egy Razor osztálykönyvtár (RCL) izolált stílusokat nyújt, a <link> címke href attribútuma {STATIC WEB ASSET BASE PATH}/{PACKAGE ID}.bundle.scp.css-re mutat, ahol a helyőrzők a következők:

  • {STATIC WEB ASSET BASE PATH}: A statikus webes erőforrás alapútvonala.
  • {PACKAGE ID}: A kódtár csomagazonosítója. A csomagazonosító alapértelmezés szerint a projekt szerelvényneve, ha a csomagazonosító nincs megadva a projektfájlban.

Az alábbi példában:

  • A statikus webes objektumok alap elérési útja a _content/ClassLib.
  • Az osztálykönyvtár összeállításának neve ClassLib.

Pages/Shared/_Layout.cshtml (Razor oldalak) vagy Views/Shared/_Layout.cshtml (MVC):

<link href="_content/ClassLib/ClassLib.bundle.scp.css" rel="stylesheet">

Az RCL-ekkel kapcsolatos további információkért tekintse meg a következő cikkeket:

Az Blazor CSS-elkülönítésről további információt a ASP.NET Core Blazor CSS elkülönítésicímű cikkben talál.

HEAD-kérelmek kezelése OnGet-kezelő tartalékkal

HEAD kérések lehetővé teszik egy adott erőforrás fejléceinek lekérését. A GET kérésekkel ellentétben a HEAD kérések nem adnak vissza választörzset.

Általában egy OnHead kezelő jön létre, és HEAD kéréseket kér:

public void OnHead()
{
    HttpContext.Response.Headers.Add("Head Test", "Handled by OnHead!");
}

Razor Pages alapértelmezetten visszatér a OnGet kezelőhöz, ha nincs definiálva OnHead kezelő.

XSRF/CSRF és Razor oldalak

Razor Oldalakat védi a hamisítás elleni ellenőrzés. A FormTagHelper antiforgery tokeneket épít be a HTML űrlap elemekbe.

Elrendezések, részrészek, sablonok és címkesegédek használata Razor oldalakkal

A lapok a Razor nézetmotor összes funkciójával működnek. Az elrendezések, részleges elemek, sablonok, címkesegítők, _ViewStart.cshtmlés _ViewImports.cshtml ugyanúgy működnek, mint a hagyományos Razor nézetek esetében.

Rendezzük át ezt az oldalt úgy, hogy kihasználjuk néhány képességét.

Adjon hozzá egy elrendezéslapotPages/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>

A elrendezés:

  • Az egyes lapok elrendezését szabályozza (kivéve, ha a lap lemond az elrendezésről).
  • HTML-struktúrák, például JavaScript és stíluslapok importálása.
  • A Razor lap tartalma ott jelenik meg, ahol a @RenderBody() meghívásra kerül.

További információ: elrendezési oldal.

A Elrendezés tulajdonság Pages/_ViewStart.cshtmlvan beállítva:

@{
    Layout = "_Layout";
}

Az elrendezés a Lapok/Megosztott mappában található. A lapok hierarchikusan keresnek más nézeteket (elrendezéseket, sablonokat, részeket) az aktuális oldallal megegyező mappában. A Lapok/Megosztott mappa elrendezése az Lapok mappa bármely Razor oldaláról használható.

Az elrendezés-fájlnak a Lapok/Megosztott mappába kell kerülnie.

Javasoljuk, ne helyezze az elrendezésfájlt a Nézetek/Megosztott mappába. Views/Shared az MVC nézeti minta. Razor lapok mappahierarchiára, nem elérésiút-konvenciókra épülnek.

A Razor lap keresési nézete tartalmazza a Pages mappát. Az MVC-vezérlőkkel és a hagyományos nézetekkel használt elrendezések, sablonok és részleges elemek csakműködnek .

Adjon hozzá egy Pages/_ViewImports.cshtml fájlt:

@namespace RazorPagesContacts.Pages
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers

@namespace az oktatóanyag későbbi részében lesz kifejtve. A @addTagHelper irányelv beépített címkesegítőket a Lapok mappában lévő összes lapra.

Az adott lapon beállított @namespace irányelv:

@page
@namespace RazorPagesIntro.Pages.Customers

@model NameSpaceModel

<h2>Name space</h2>
<p>
    @Model.Message
</p>

A @namespace irányelv beállítja a lap névterét. A @model irányelvnek nem kell tartalmaznia a névteret.

Ha a @namespace irányelv a _ViewImports.cshtml-ben található, a megadott névtér biztosítja az előtagot a létrehozott névtérhez az @namespace irányelvet importáló oldalon. A létrehozott névtér többi része (az utótag része) a _ViewImports.cshtml-t tartalmazó mappa és a lapot tartalmazó mappa közötti ponttal elválasztott relatív elérési útvonal.

Például a PageModel osztály Pages/Customers/Edit.cshtml.cs explicit módon beállítja a névteret:

namespace RazorPagesContacts.Pages
{
    public class EditModel : PageModel
    {
        private readonly AppDbContext _db;

        public EditModel(AppDbContext db)
        {
            _db = db;
        }

        // Code removed for brevity.

A Pages/_ViewImports.cshtml fájl a következő névteret állítja be:

@namespace RazorPagesContacts.Pages
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers

A Pages/Customers/Edit.cshtmlRazor lap generált névtere megegyezik a PageModel osztályával.

@namespace a hagyományos Razor nézetekkel is működik.

Fontolja meg a Pages/Customers/Create.cshtml nézetfájlt:

@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>

A frissített Pages/Customers/Create.cshtml nézetfájl _ViewImports.cshtml-gyel és az azt megelőző elrendezésfájllal:

@page
@model CreateModel

<p>Enter a customer name:</p>

<form method="post">
    Name:
    <input asp-for="Customer!.Name" />
    <input type="submit" />
</form>

Az előző kódban a _ViewImports.cshtml importálta a névteret és a címkesegítőket. Az elrendezésfájl importálta a JavaScript-fájlokat.

A Razor Pages kezdőprojekt tartalmazza az ügyféloldali ellenőrzést biztosító Pages/_ValidationScriptsPartial.cshtml.

A részleges nézetekről további információkért lásd Részleges nézetek az ASP.NET Core-ban.

URL-cím létrehozása lapokhoz

A korábban bemutatott Create lap RedirectToPagehasznál:

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();
        }

        if (Customer != null) _context.Customer.Add(Customer);
        await _context.SaveChangesAsync();

        return RedirectToPage("./Index");
    }
}

Az alkalmazás a következő fájl-/mappastruktúrával rendelkezik:

  • /Pages

    • Index.cshtml

    • Privacy.cshtml

    • /Ügyfelek

      • Create.cshtml
      • Edit.cshtml
      • Index.cshtml

A Pages/Customers/Create.cshtml és Pages/Customers/Edit.cshtml oldalakat siker esetén Pages/Customers/Index.cshtml oldalra irányítják át. A ./Index, az előző lap eléréséhez használt relatív oldalnév. A Pages/Customers/Index.cshtml lap URL-címeinek létrehozására szolgál. Például:

  • Url.Page("./Index", ...)
  • <a asp-page="./Index">Customers Index Page</a>
  • RedirectToPage("./Index")

Az abszolút lapnév /Index a Pages/Index.cshtml lap URL-címeinek létrehozására szolgál. Például:

  • Url.Page("/Index", ...)
  • <a asp-page="/Index">Home Index Page</a>
  • RedirectToPage("/Index")

A lap neve a lap elérési útja a gyökér /Pages mappából, beleértve a bevezető / (például /Index). Az előző URL-létrehozási minták továbbfejlesztett lehetőségeket és funkcionális képességeket kínálnak az URL-címek kemény kódolásával szemben. Az URL-generálás a útválasztási-t használja, és paramétereket hozhat létre és kódolhat annak megfelelően, hogy az útvonal hogyan van definiálva a célútvonal szerint.

A lapok URL-generálása támogatja a relatív neveket. Az alábbi táblázat bemutatja, hogy a különböző RedirectToPage paraméterek használatával melyik index oldal van kiválasztva a Pages/Customers/Create.cshtml-ben.

RedirectToPage(x) Oldal
RedirectToPage("/Index") Lapok/Tartalomjegyzék
Irányítás az oldalra("./Index"); Lapok/Ügyfelek/Kezdőlap
RedirectToPage("../Index") Lapok/Index
RedirectToPage("Index") Lapok/Ügyfelek/Index

RedirectToPage("Index"), RedirectToPage("./Index")és RedirectToPage("../Index") a relatív nevek. A RedirectToPage paraméter kombinálva az aktuális oldal elérési útjával a céllap nevének kiszámításához.

A relatív név használata akkor hasznos, ha összetett szerkezetű webhelyeket hoz létre. Ha relatív neveket használ a mappa lapjai közötti hivatkozáshoz:

  • A mappák átnevezése nem szakítja meg a relatív hivatkozásokat.
  • A hivatkozások nem hibásak, mert nem tartalmazzák a mappa nevét.

Ha másik Területlapjára szeretne átirányítani, adja meg a területet:

RedirectToPage("/Index", new { area = "Services" });

További információ: ASP.NET Core és Razor Lapok útvonal- és alkalmazáskonvenciái ASP.NET Core.

ViewData attribútum

Az adatok továbbíthatók egy ViewDataAttribute-et tartalmazó lapra. A [ViewData] attribútummal rendelkező tulajdonságok értékeit a ViewDataDictionarytárolja és tölti be.

Az alábbi példában a AboutModel a [ViewData] attribútumot alkalmazza a Title tulajdonságra:

public class AboutModel : PageModel
{
    [ViewData]
    public string Title { get; } = "About";

    public void OnGet()
    {
    }
}

A Névjegy lapon a Title tulajdonságot érheti el modelltulajdonságként:

<h1>@Model.Title</h1>

Az elrendezésben a cím a ViewData szótárból olvasható:

<!DOCTYPE html>
<html lang="en">
<head>
    <title>@ViewData["Title"] - WebApplication</title>
    ...

TempData

ASP.NET Core elérhetővé teszi a TempData. Ez a tulajdonság addig tárolja az adatokat, amíg el nem olvassa. A Keep és Peek metódusokkal törlés nélkül vizsgálhatja meg az adatokat. TempData akkor hasznos az átirányításhoz, ha több kérelemhez is szükség van adatokra.

Az alábbi kód a Message értékét állítja be TempDatahasználatával:

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");
    }
}

A Pages/Customers/Index.cshtml fájlban az alábbi korrektúra a Message értékét jeleníti meg TempDatahasználatával.

<h3>Msg: @Model.Message</h3>

A Pages/Customers/Index.cshtml.cs oldalmodell a [TempData] attribútumot alkalmazza a Message tulajdonságra.

[TempData]
public string Message { get; set; }

További információ: TempData.

Több feldolgozó oldalanként

Az alábbi oldal két kezelő számára generál jelölőkódot a asp-page-handler Tag Helper használatával.

@page
@model CreateFATHModel

<html>
<body>
    <p>
        Enter your name.
    </p>
    <div asp-validation-summary="All"></div>
    <form method="POST">
        <div><label>Name: <input asp-for="Customer.Name" /></label></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>

Az előző példában szereplő űrlapon két küldési gomb található, mindegyik a FormActionTagHelper használatával küldi el egy másik URL-címre. A asp-page-handler attribútum a asp-pagetársa. asp-page-handler olyan URL-címeket hoz létre, amelyek a lap által definiált kezelői metódusok mindegyikére elküldve lesznek. asp-page nincs megadva, mert a minta az aktuális lapra hivatkozik.

Az oldalmodell:

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();
        }
    }
}

Az előző kód a nevű kezelőmetódusokat használja. A kezelői metódusok nevét úgy hozzuk létre, hogy a szöveget a névben On<HTTP Verb> után és Async előtt vesszük (ha van ilyen). Az előző példában a lap metódusai az OnPostJoinListAsync és az OnPostJoinListUCAsync. Ha eltávolították a OnPost-t és a Async-t, a kezelők nevei JoinList és JoinListUC.

<input type="submit" asp-page-handler="JoinList" value="Join" />
<input type="submit" asp-page-handler="JoinListUC" value="JOIN UC" />

Az előző kód használatával a https://localhost:5001/Customers/CreateFATH?handler=JoinListURL-útvonal a OnPostJoinListAsync címre küld be. A OnPostJoinListUCAsync elküldendő URL-cím https://localhost:5001/Customers/CreateFATH?handler=JoinListUC.

Egyéni útvonalak

A @page irányelv használatával:

  • Adjon meg egy egyéni útvonalat egy laphoz. A Névjegy lapra vezető útvonal például beállítható úgy, hogy /Some/Other/Path@page "/Some/Other/Path".
  • Szegmensek hozzáfűzése egy lap alapértelmezett útvonalához. Egy "elem" szegmens például hozzáadható egy lap alapértelmezett útvonalához @page "item".
  • Paraméterek hozzáfűzése egy lap alapértelmezett útvonalához. Például egy idazonosító paraméterre lehet szükség egy olyan oldalhoz, ami @page "{id}".

Az elérési út elején egy tilde (~) által kijelölt gyökér-relatív elérési út támogatott. A @page "~/Some/Other/Path" például ugyanaz, mint @page "/Some/Other/Path".

Ha nem tetszik a lekérdezési sztring ?handler=JoinList az URL-címben, változtassa meg az útvonalat úgy, hogy a kezelő neve az URL elérési út szakaszába kerüljön. Az útvonal testre szabható úgy, hogy a @page irányelv után dupla idézőjelek közé foglalt útvonalsablont ad hozzá.

@page "{handler?}"
@model CreateRouteModel

<html>
<body>
    <p>
        Enter your name.
    </p>
    <div asp-validation-summary="All"></div>
    <form method="POST">
        <div><label>Name: <input asp-for="Customer.Name" /></label></div>
        <input type="submit" asp-page-handler="JoinList" value="Join" />
        <input type="submit" asp-page-handler="JoinListUC" value="JOIN UC" />
    </form>
</body>
</html>

Az előző kód használatával a https://localhost:5001/Customers/CreateFATH/JoinListformájú URL útvonal a OnPostJoinListAsync-hoz küldhető. A OnPostJoinListUCAsync elküldendő URL-cím https://localhost:5001/Customers/CreateFATH/JoinListUC.

Az alábbi ?handler azt jelenti, hogy az útvonalparaméter nem kötelező.

JavaScript fájlok (JS) elrendezése

A JavaScript -fájlok (JS) oldalakhoz és nézetekhez való rendezése kényelmes módszer a szkriptek alkalmazásbeli rendszerezésére.

JS fájlok rendezése a következő fájlnévkiterjesztési konvenciók használatával:

  • A Razor Pages-alkalmazások és az MVC-alkalmazások nézetei: .cshtml.js. Példák:
    • A Pages/Index.cshtmltalálható Razor Pages-alkalmazás Index lapjára Pages/Index.cshtml.js.
    • Views/Home/Index.cshtml.js egy MVC-alkalmazás Index nézetéhez a Views/Home/Index.cshtml.

Az csoportosított JS fájlok nyilvánosan címezhetők a projekt fájljának elérési útján:

  • Lapok és nézetek egy csoportosított szkriptfájlból az alkalmazásban:

    {PATH}/{PAGE, VIEW, OR COMPONENT}.{EXTENSION}.js

    • A {PATH} helyőrző az oldal, nézet vagy összetevő elérési útja.
    • A {PAGE, VIEW, OR COMPONENT} helyőrző az oldal, a nézet vagy a komponens.
    • A {EXTENSION} helyőrző megegyezik a lap, nézet vagy összetevő kiterjesztésével, razor vagy cshtml.

    példa Razor lapokra:

    A Index lap JS fájlja a Index lap (Pages/Index.cshtml) melletti Pages mappába (Pages/Index.cshtml.js) kerül. A Index lapon a szkript a Pages mappában található elérési úton található:

    @section Scripts {
      <script src="~/Pages/Index.cshtml.js"></script>
    }
    

Az alapértelmezett elrendezési Pages/Shared/_Layout.cshtml úgy konfigurálhatók, hogy csoportosított JS fájlokat tartalmazzanak, így nincs szükség az egyes lapok egyenkénti konfigurálására:

<script asp-src-include="@(ViewContext.View.Path).js"></script>

A mintaletöltési az előző kódrészletet használja, hogy az alapértelmezett elrendezésbe csoportosított JS fájlokat is belefoglaljon.

Az alkalmazás közzétételekor a keretrendszer automatikusan áthelyezi a szkriptet a webgyökérbe. Az előző példában a szkript áthelyezésre kerül a bin\Release\{TARGET FRAMEWORK MONIKER}\publish\wwwroot\Pages\Index.cshtml.jshelyre, ahol a {TARGET FRAMEWORK MONIKER} helyőrző a célkeretrendszer-megnevezés (TFM). A szkript relatív URL-címében nincs szükség módosításra a Index lapon.

Az alkalmazás közzétételekor a keretrendszer automatikusan áthelyezi a szkriptet a web gyökérkönyvtárába. Az előző példában a szkript áthelyezésre kerül a bin\Release\{TARGET FRAMEWORK MONIKER}\publish\wwwroot\Components\Pages\Index.razor.jspozícióra, ahol a {TARGET FRAMEWORK MONIKER} helyőrző a cél-keretrendszer megnevezést (TFM) jelöli. Nincs szükség módosításra a szkript relatív URL-címében a Index összetevőben.

  • Razor osztálykódtár (RCL) által biztosított szkriptek esetén:

    _content/{PACKAGE ID}/{PATH}/{PAGE, VIEW, OR COMPONENT}.{EXTENSION}.js

    • A {PACKAGE ID} helyőrző az RCL csomagazonosítója (vagy az alkalmazás által hivatkozott osztálytár könyvtárneve).
    • A {PATH} helyőrző az oldal, nézet vagy összetevő elérési útja. Ha egy Razor összetevő az RCL gyökerénél található, az elérésiút-szegmens nem lesz benne.
    • A {PAGE, VIEW, OR COMPONENT} helyőrző az oldal, a nézet vagy az összetevő.
    • A {EXTENSION} helyőrző megegyezik a lap, nézet vagy összetevő kiterjesztésével, razor vagy cshtml.

Speciális konfiguráció és beállítások

A legtöbb alkalmazás nem igényli a konfigurációt és a beállításokat a következő szakaszokban.

A speciális beállítások konfigurálásához használja a AddRazorPages túlterhelést, amely konfigurálja a RazorPagesOptions-et.

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();

A RazorPagesOptions-t használja a lapok gyökérkönyvtárának beállításához, vagy adjon hozzá alkalmazásmodell-konvenciókat a lapokhoz. További információ a konvenciókról: Razor Oldalak engedélyezési konvenciói.

A nézetek előre fordításához lásd a(z) Razor nézetek előfordítása.

Adja meg, hogy Razor lapok a tartalom gyökerénél legyenek

Alapértelmezés szerint a Razor lapok a /Pages könyvtárban gyökereznek. Adja hozzá a WithRazorPagesAtContentRoot-t annak megadásához, hogy a Razor lapok az alkalmazás tartalomgyökerénál (ContentRootPath) találhatók.

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();

Adja meg, hogy a Razor oldalak egyéni gyökérkönyvtárban legyenek

Adjon hozzá WithRazorPagesRoot annak megadásához, hogy Razor lapok egy egyéni gyökérkönyvtárban találhatók az alkalmazásban (adjon meg egy relatív elérési utat):

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();

További erőforrások

Razor Pages-projekt létrehozása

A Razor Pages-projekt létrehozásának részletes útmutatóját a Razor Lapok használatának első lépései című témakörben találja.

Razor lapok

Razor Oldalak engedélyezve vannak a 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();
        });
    }
}

Gondolj egy alapoldalra:

@page

<h1>Hello, world!</h1>
<h2>The time on the server is @DateTime.Now</h2>

Az előző kód nagyon hasonlít a vezérlőkkel és nézetekkel rendelkező ASP.NET Core-alkalmazásokban használt Razor nézetfájlra,. A @page irányelv az, amitől ez más. @page MVC-műveletté alakítja a fájlt, ami azt jelenti, hogy közvetlenül, vezérlő használata nélkül kezeli a kéréseket. @page kell lennie az első Razor irányelvnek egy lapon. @page hatással van más Razor szerkezetek viselkedésére. Razor Lapok fájlnevek .cshtml utótagot tartalmaz.

A következő két fájlban egy hasonló lap jelenik meg, amely egy PageModel osztályt használ. A Pages/Index2.cshtml fájl:

@page
@using RazorPagesIntro.Pages
@model Index2Model

<h2>Separate page model</h2>
<p>
    @Model.Message
</p>

A Pages/Index2.cshtml.cs oldalmodell:

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 }";
        }
    }
}

Konvenció szerint a PageModel osztályfájl neve megegyezik a Razor lapfájl nevével, .cs hozzáfűzve. Az előző Razor lap például Pages/Index2.cshtml. A PageModel osztályt tartalmazó fájl neve Pages/Index2.cshtml.cs.

A lapok URL-útvonalainak társítását a lap fájlrendszerbeli helye határozza meg. Az alábbi táblázat egy Razor oldal elérési útját és a megfelelő URL-címet mutatja:

Fájlnév és elérési út egyező URL-cím
/Pages/Index.cshtml / vagy /Index
/Pages/Contact.cshtml /Contact
/Pages/Store/Contact.cshtml /Store/Contact
/Pages/Store/Index.cshtml /Store vagy /Store/Index

Jegyzetek:

  • A futtatókörnyezet alapértelmezés szerint Razor Pages-fájlokat keres a Pages mappában.
  • Index az alapértelmezett lap, ha egy URL-cím nem tartalmaz lapot.

Egyszerű űrlap írása

Razor Pages úgy lett kialakítva, hogy könnyen implementálhatóvá tegye a webböngészőkben használt gyakori mintákat egy alkalmazás létrehozásakor. Modellkötési, Címkesegítőés HTML-segítők csak a Razor Laposztályban meghatározott tulajdonságokkal dolgoznak. Fontolja meg a Contact modell alapszintű "kapcsolatfelvétel" űrlapjának implementálását ismertető oldalt:

A dokumentumban szereplő minták esetében a DbContext inicializálva van a Startup.cs fájlban.

A memóriában lévő adatbázishoz szükség van a Microsoft.EntityFrameworkCore.InMemory NuGet-csomagra.

public void ConfigureServices(IServiceCollection services)
{
    services.AddDbContext<CustomerDbContext>(options =>
                      options.UseInMemoryDatabase("name"));
    services.AddRazorPages();
}

Az adatmodell:

using System.ComponentModel.DataAnnotations;

namespace RazorPagesContacts.Models
{
    public class Customer
    {
        public int Id { get; set; }

        [Required, StringLength(10)]
        public string Name { get; set; }
    }
}

Az adatbázis-környezet:

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; }
    }
}

A Pages/Create.cshtml nézetfájl:

@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>

A Pages/Create.cshtml.cs lapmodell:

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");
        }
    }
}

Konvenció szerint a PageModel osztály neve <PageName>Model, és ugyanabban a névtérben van, mint a lap.

A PageModel osztály lehetővé teszi a lap logikájának elválasztását a bemutatótól. Meghatározza a lapra küldött kérelmek és a lap rendereléséhez használt adatok lapkezelőit. Ez az elkülönítés a következőt teszi lehetővé:

A lap egy OnPostAsynckezelőmetódussal rendelkezik, amely POST kérelmeken fut (amikor egy felhasználó közzéteszi az űrlapot). Bármely HTTP-ige kezelő metódusai hozzáadhatók. A leggyakoribb kezelők a következők:

  • OnGet az oldalhoz szükséges állapot inicializálásához. Az előző kódban a OnGet metódus megjeleníti a CreateModel.cshtmlRazor lapot.
  • OnPost az űrlapbeküldések kezeléséhez.

A Async elnevezési utótag nem kötelező, de gyakran használják konvencióként az aszinkron függvényekhez. Az előző kód Razor lapokra jellemző.

Ha ismeri ASP.NET vezérlőket és nézeteket használó alkalmazásokat:

  • Az előző példában szereplő OnPostAsync kód a tipikus vezérlőkódhoz hasonlóan néz ki.
  • Az MVC-primitívek többsége, például modellkötési, érvényesítési, és a műveleteredmények ugyanúgy működnek a vezérlőkkel és Razor oldalakkal.

Az előző OnPostAsync metódus:

public async Task<IActionResult> OnPostAsync()
{
    if (!ModelState.IsValid)
    {
        return Page();
    }

    _context.Customers.Add(Customer);
    await _context.SaveChangesAsync();

    return RedirectToPage("./Index");
}

A OnPostAsyncalapfolyamata:

Ellenőrizze az érvényesítési hibákat.

  • Ha nincsenek hibák, mentse az adatokat és az átirányítást.
  • Ha hibák merülnek fel, a lapot ismét megjelenítheti érvényesítési üzenetekkel. A rendszer sok esetben érvényesítési hibákat észlel az ügyfélen, és soha nem küldi el a kiszolgálónak.

A Pages/Create.cshtml nézetfájl:

@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>

A renderelt HTML a Pages/Create.cshtmlkódból:

<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>

Az előző kódban az űrlap beküldése:

  • Érvényes adatokkal:

    • A OnPostAsync kezelő metódus meghívja a RedirectToPage segédmetódust. RedirectToPage a RedirectToPageResultegy példányát adja vissza. RedirectToPage:

      • Ez egy művelet eredménye.
      • Hasonló RedirectToAction vagy RedirectToRoute (vezérlőkben és nézetekben használatos).
      • Az oldalakhoz van testreszabva. Az előző példában átirányítja a gyökérindex lapra (/Index). a Lapok szakasz URL-címének generálása című szakaszban található.
  • A kiszolgálónak átadott érvényesítési hibákkal:

    • A OnPostAsync kezelő metódus meghívja a Page segédmetódust. Page a PageResultegy példányát adja vissza. A Page visszatérése hasonló ahhoz, ahogyan a vezérlők műveletei Viewtérnek vissza. PageResult egy kezelőmetódus alapértelmezett visszatérési típusa. Olyan kezelőmetódus, ami a void értéket adja vissza, megjeleníti az oldalt.
    • Az előző példában, ha az űrlapot érték nélkül adjuk be, a ModelState.IsValid hamis értéket ad vissza. Ebben a mintában nem jelennek meg érvényesítési hibák az ügyfélen. Az érvényesítési hibakezelésről a dokumentum későbbi részében lesz szó.
    public async Task<IActionResult> OnPostAsync()
    {
        if (!ModelState.IsValid)
        {
            return Page();
        }
    
        _context.Customers.Add(Customer);
        await _context.SaveChangesAsync();
    
        return RedirectToPage("./Index");
    }
    
  • Az ügyféloldali ellenőrzés által észlelt érvényesítési hibák esetén:

    • Az adatok nincsenek feltöltve a kiszolgálóra.
    • Az ügyféloldali érvényesítést a dokumentum későbbi részében ismertetik.

A Customer tulajdonság a [BindProperty] attribútum használatával választja a modellikötést.

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");
    }
}

A [BindProperty]nem szabad olyan tulajdonságokat tartalmazó modelleken használni, amelyeket az ügyfél nem módosíthat. További információkért lásd: Túltöltés.

Razor lapok alapértelmezés szerint csak nemGET igékkel kötik össze a tulajdonságokat. A tulajdonságokhoz való kötés nem igényli a HTTP-adatok modelltípussá alakításához szükséges kód írását. A kötés azzal csökkenti a kódot, hogy ugyanazt a tulajdonságot használja az űrlapmezők rendereléséhez (<input asp-for="Customer.Name">), és elfogadja a bemenetet.

Figyelmeztetés

Biztonsági okokból kifejezetten engedélyeznie kell a GET lekérdezési adatok oldalmodell tulajdonságaihoz kötését. Ellenőrizze a felhasználói bemenetet, mielőtt tulajdonságokra megfelelteti. A GET kötés használata akkor hasznos, ha olyan forgatókönyveket kezel, amelyek lekérdezési sztringre vagy útvonalértékekre támaszkodnak.

Ha egy tulajdonságot GET kérelmekhez szeretne kötni, állítsa a [BindProperty] attribútum SupportsGet tulajdonságát true:

[BindProperty(SupportsGet = true)]

További információ: ASP.NET Core Community Standup: Bind on GET beszélgetés (YouTube).

A Pages/Create.cshtml nézetfájl áttekintése:

@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>
  • Az előző kódban a bemeneti címke segédje<input asp-for="Customer.Name" /> a HTML-<input> elemet a Customer.Name modellkifejezéshez köti.
  • @addTagHelper elérhetővé teszi a címkesegítőket.

A kezdőlap

Index.cshtml a kezdőlap:

@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>

A társított PageModel osztály (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();
    }
}

A Index.cshtml fájl a következő jelölést tartalmazza:

<a asp-page="./Edit" asp-route-id="@contact.Id">Edit</a> |

A <a /a>horgonycímke-segéd a asp-route-{value} attribútumot használta a Szerkesztés lapra mutató hivatkozás létrehozásához. A hivatkozás útvonaladatokat tartalmaz a kapcsolatazonosítóval. Például https://localhost:5001/Edit/1. Címkesegédek lehetővé teszik a kiszolgálóoldali kód számára, hogy részt vegyen a HTML-elemek létrehozásában és renderelésében Razor fájlokban.

A Index.cshtml fájl jelölést tartalmaz a törlőgomb létrehozásához minden ügyfélkapcsolathoz.

<button type="submit" asp-page-handler="delete" asp-route-id="@contact.Id">delete</button>

A renderelt HTML:

<button type="submit" formaction="/Customers?id=1&amp;handler=delete">delete</button>

Amikor a törlés gomb HTML-ben jelenik meg, a formaction a következő paramétereket tartalmazza:

  • A asp-route-id attribútum által megadott ügyfélkapcsolati azonosító.
  • A handler, amelyet a asp-page-handler attribútum határoz meg.

Ha a gomb ki van jelölve, a rendszer egy űrlapot POST kérést küld a kiszolgálónak. Konvenció szerint a kezelőmetódus neve a handler paraméter értéke alapján van kiválasztva a séma OnPost[handler]Asyncszerint.

Mivel a handler ebben a példában delete, a OnPostDeleteAsync kezelőmetódus a POST kérés feldolgozására szolgál. Ha a asp-page-handler más értékre van állítva, például remove, akkor a rendszer kiválaszt egy OnPostRemoveAsync nevű kezelőmetódust.

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();
}

A OnPostDeleteAsync módszer:

  • Lekéri a id-t a lekérdezési sztringből.
  • Lekérdezi az adatbázist az ügyfélkapcsolat FindAsync-t.
  • Ha az ügyfél kapcsolattartója megtalálható, az el lesz távolítva, és az adatbázis frissül.
  • Meghívja RedirectToPage, hogy átirányítsa az index gyökéroldalára (/Index).

Az Edit.cshtml fájl

@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>

Az első sor tartalmazza a @page "{id:int}" irányelvet. Az útválasztási korlátozás "{id:int}" arra utasítja a lapot, hogy fogadja el az int útvonaladatokat tartalmazó lapra irányuló kéréseket. Ha a lapra irányuló kérések nem tartalmaznak intkonvertálható útvonaladatokat, a futtatókörnyezet HTTP 404-es (nem található) hibát ad vissza. Ha az azonosítót nem kötelező megadni, fűzze hozzá ? az útvonalkorlátozáshoz:

@page "{id:int?}"

A Edit.cshtml.cs fájl:

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");
    }

}

Érvényesítés

Érvényesítési szabályok:

  • Deklaratív módon vannak megadva a modellosztályban.
  • Az alkalmazásban mindenhol érvényesítve vannak.

A System.ComponentModel.DataAnnotations névtér olyan beépített érvényesítési attribútumokat biztosít, amelyeket deklaratív módon alkalmaz egy osztályra vagy tulajdonságra. A DataAnnotations olyan formázási attribútumokat is tartalmaz, mint a [DataType], amelyek segítenek a formázásban, és nem biztosítanak semmilyen ellenőrzést.

Fontolja meg a Customer modellt:

using System.ComponentModel.DataAnnotations;

namespace RazorPagesContacts.Models
{
    public class Customer
    {
        public int Id { get; set; }

        [Required, StringLength(10)]
        public string Name { get; set; }
    }
}

A következő Create.cshtml nézetfájl használata:

@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>

Az előző kód:

  • JQuery- és jQuery-érvényesítési szkripteket tartalmaz.

  • A <div /> és a <span />Tag Helper használatával engedélyezi a következőket:

    • Ügyféloldali ellenőrzés.
    • Érvényesítési hiba megjelenítése.
  • A következő HTML-t hozza létre:

    <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>
    

Ha névérték nélkül küldi el a Létrehozás űrlapot, az "A Név mező kötelező" hibaüzenet jelenik meg az űrlapon. Ha a JavaScript engedélyezve van az ügyfélen, a böngésző a kiszolgálóra való közzététel nélkül jeleníti meg a hibát.

A(z) [StringLength(10)] attribútum data-val-length-max="10"-et hoz létre a renderelt HTML-ben. data-val-length-max megakadályozza, hogy a böngészők a megadott maximális hossznál többet adjanak meg. Ha olyan eszközt használ, mint Fiddler a bejegyzés szerkesztésére és lejátszására:

  • 10-nél hosszabb névvel.
  • A következő hibaüzenet jelenik meg: "A mezőnévnek legfeljebb 10 hosszúságú sztringnek kell lennie".

Fontolja meg a következő Movie modellt:

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; }
    }
}

Az érvényesítési attribútumok a következő modelltulajdonságokon érvényesítendő viselkedést adják meg:

  • A Required és MinimumLength attribútumok azt jelzik, hogy egy tulajdonságnak rendelkeznie kell értékkel, de semmi sem akadályozza meg, hogy a felhasználó üres területre lépjen az ellenőrzés teljesítéséhez.

  • A RegularExpression attribútummal korlátozható, hogy mely karakterek adhatóak meg. Az előző kódban a "Műfaj":

    • Csak betűket szabad használni.
    • Az első betűnek nagybetűsnek kell lennie. A szóköz, a számok és a speciális karakterek nem engedélyezettek.
  • A RegularExpression "Értékelés":

    • Az első karakternek nagybetűsnek kell lennie.
    • Lehetővé teszi a speciális karaktereket és számokat a következő szóközökben. A "PG-13" érvényes egy minősítésre, de nem felel meg a "Műfaj" kifejezésnek.
  • A Range attribútum egy adott tartományon belülre korlátozza az értéket.

  • A StringLength attribútum egy sztringtulajdonság maximális hosszát és opcionálisan minimális hosszát állítja be.

  • Az értéktípusokra (például decimal, int, float, DateTime) alapvetően szükség van, és nincs szükség a [Required] attribútumra.

A Movie modell Létrehozás lapja érvénytelen értékeket tartalmazó hibákat jelenít meg:

Több jQuery ügyféloldali érvényesítési hibával rendelkező filmnézet-űrlap

További információ:

HEAD-kérelmek kezelése OnGet-kezelő tartalékkal

HEAD kérések lehetővé teszik egy adott erőforrás fejléceinek lekérését. A GET kérésekkel ellentétben a HEAD kérések nem adnak vissza választörzset.

Általában egy OnHead kezelő jön létre, és HEAD kéréseket kér:

public void OnHead()
{
    HttpContext.Response.Headers.Add("Head Test", "Handled by OnHead!");
}

Razor Pages visszatér a OnGet kezelő hívására, ha nincs definiálva OnHead kezelő.

XSRF/CSRF és Razor oldalak

Razor Az oldalakat az Antiforgery hitelesítésvédi. A FormTagHelper antiforgery tokeneket injektál HTML-űrlapelemekbe.

Elrendezések, részrészek, sablonok és címkesegédek használata Razor oldalakkal

A lapok a Razor nézetmotor összes funkciójával működnek. Az elrendezések, részleges elemek, sablonok, címkesegítők, _ViewStart.cshtmlés _ViewImports.cshtml ugyanúgy működnek, mint a hagyományos Razor nézetek esetében.

Szellőztessük át ezt az oldalt azáltal, hogy kiaknázunk néhány lehetőséget.

Adj hozzá egy elrendezéslapot a elemhez 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>

Az elrendezés :

  • Az egyes lapok elrendezését szabályozza (kivéve, ha a lap úgy dönt, hogy nem alkalmazza az elrendezést).
  • HTML-struktúrák, például JavaScript és stíluslapok importálása.
  • A Razor oldal tartalma ott jelenik meg, ahol a @RenderBody()-et meghívják.

További információ: elrendezéslap.

A Elrendezés tulajdonság be van állítva a Pages/_ViewStart.cshtml:

@{
    Layout = "_Layout";
}

Az elrendezés a Lapok/Megosztott mappában található. A lapok hierarchikusan keresnek más nézeteket (elrendezéseket, sablonokat, részeket) az aktuális oldallal megegyező mappában. A Lapok/Megosztott mappa elrendezése az Lapok mappa bármely Razor oldaláról használható.

Az elrendezési fájlnak a Lapok/Megosztott mappába kell kerülnie.

Javasoljuk, ne helyezze az elrendezésfájlt a Nézetek/Megosztott mappába. Views/Shared egy MVC-nézetminta. Razor lapok mappahierarchiára, nem elérésiút-konvenciókra épülnek.

A Razor lapról végzett keresési nézet tartalmazza a Pages mappát. Az MVC-vezérlőkkel és a hagyományos Razor nézetekkel használt elrendezések, sablonok és részleges elemek zökkenőmentesen működnek.

Adjon hozzá egy Pages/_ViewImports.cshtml fájlt:

@namespace RazorPagesContacts.Pages
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers

@namespace az oktatóanyag későbbi részében lesz bemutatva. A @addTagHelper irányelv beépített címkesegítőket a Lapok mappában lévő összes lapra.

Az oldalon meghatározott @namespace irányelv:

@page
@namespace RazorPagesIntro.Pages.Customers

@model NameSpaceModel

<h2>Name space</h2>
<p>
    @Model.Message
</p>

A @namespace irányelv beállítja a lap névterét. A @model irányelvnek nem kell tartalmaznia a névteret.

Ha a @namespace irányelv megtalálható a _ViewImports.cshtml-ben, a megadott névtér adja meg a létrehozott névtérhez szükséges előtagot a @namespace irányelvet importáló lapon. A létrehozott névtér többi része (az utótag része) a _ViewImports.cshtml tartalmazó mappa és a lapot tartalmazó mappa közötti ponthatárolt relatív elérési út.

Például a PageModel osztály Pages/Customers/Edit.cshtml.cs explicit módon beállítja a névteret:

namespace RazorPagesContacts.Pages
{
    public class EditModel : PageModel
    {
        private readonly AppDbContext _db;

        public EditModel(AppDbContext db)
        {
            _db = db;
        }

        // Code removed for brevity.

A Pages/_ViewImports.cshtml fájl a következő névteret állítja be:

@namespace RazorPagesContacts.Pages
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers

A Pages/Customers/Edit.cshtmlRazor lap generált névtere megegyezik a PageModel osztályával.

@namespace a hagyományos Razor nézetekkel is működik.

Fontolja meg a Pages/Create.cshtml nézetfájlt:

@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>

A frissített Pages/Create.cshtml nézetfájl a _ViewImports.cshtml és az előbbi elrendezésfájl kombinációjával:

@page
@model CreateModel

<p>Enter a customer name:</p>

<form method="post">
    Name:
    <input asp-for="Customer.Name" />
    <input type="submit" />
</form>

Az előző kódban a _ViewImports.cshtml importálta a névteret és a címkesegítőket. Az elrendezésfájl importálta a JavaScript-fájlokat.

A Razor Pages kezdőprojekt tartalmazza az ügyféloldali ellenőrzést biztosító Pages/_ValidationScriptsPartial.cshtml.

További információért a részleges nézetek az ASP.NET Core-ban lásd Részleges nézetek.

URL-cím létrehozása lapokhoz

A korábban bemutatott Create lap RedirectToPagehasznál:

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");
    }
}

Az alkalmazás a következő fájl-/mappastruktúrával rendelkezik:

  • /Pages

    • Index.cshtml

    • Privacy.cshtml

    • /Ügyfelek

      • Create.cshtml
      • Edit.cshtml
      • Index.cshtml

Sikeres átirányítás esetén a Pages/Customers/Create.cshtml és Pages/Customers/Edit.cshtml oldalak a Pages/Customers/Index.cshtml-re irányulnak át. A ./Index karakterlánc egy relatív oldalnév, amelyet az előző oldal elérésére használnak. A Pages/Customers/Index.cshtml lap URL-címeinek létrehozására szolgál. Például:

  • Url.Page("./Index", ...)
  • <a asp-page="./Index">Customers Index Page</a>
  • RedirectToPage("./Index")

Az abszolút lapnév /Index a Pages/Index.cshtml lap URL-címeinek létrehozására szolgál. Például:

  • Url.Page("/Index", ...)
  • <a asp-page="/Index">Home Index Page</a>
  • RedirectToPage("/Index")

A lap neve a lap elérési útja a gyökér /Pages mappából, beleértve a bevezető / (például /Index). Az előző URL-létrehozási minták továbbfejlesztett lehetőségeket és funkcionális képességeket kínálnak az URL-címek kemény kódolásával szemben. Az URL-generálás útválasztást használ, és az útvonal célútvonalon való definiálása szerint hozhat létre és kódolhat paramétereket.

A lapok URL-generálása támogatja a relatív neveket. Az alábbi táblázat azt mutatja, hogy melyik indexoldal van kiválasztva a RedirectToPage különböző paramétereivel a Pages/Customers/Create.cshtml-ben.

UgrásAzOldalra(x) Oldal
RedirectToPage("/Index") Lapok/Index
RedirectToPage("./Index"); Lapok/Ügyfelek/Index
RedirectToPage("../Index") Lapok/Index
IrányítsonAzOldalra("Index") Oldalak/Ügyfelek/Index

RedirectToPage("Index"), RedirectToPage("./Index")és RedirectToPage("../Index")rokoni nevek. A RedirectToPage paraméter kombinálva az aktuális oldal elérési útjával a céllap nevének kiszámításához.

A relatív név kapcsolása akkor hasznos, amikor összetett szerkezetű webhelyek építéséről van szó. Ha relatív neveket használ a mappa lapjai közötti hivatkozáshoz:

  • A mappák átnevezése nem szakítja meg a relatív hivatkozásokat.
  • A hivatkozások nem hibásak, mert nem tartalmazzák a mappa nevét.

Ha másik Területlapjára szeretne átirányítani, adja meg a területet:

RedirectToPage("/Index", new { area = "Services" });

További információ: ASP.NET Core és Razor Lapok útvonal- és alkalmazáskonvenciái ASP.NET Core.

ViewData attribútum

Az adatok továbbíthatók egy ViewDataAttribute-ás lapra. A [ViewData] attribútummal rendelkező tulajdonságok értékeit a ViewDataDictionarytárolja és tölti be.

Az alábbi példában a AboutModel a [ViewData] attribútumot alkalmazza a Title tulajdonságra:

public class AboutModel : PageModel
{
    [ViewData]
    public string Title { get; } = "About";

    public void OnGet()
    {
    }
}

A Névjegy lapon a Title tulajdonságot érheti el modelltulajdonságként:

<h1>@Model.Title</h1>

Az elrendezésben a cím a ViewData szótárból olvasható:

<!DOCTYPE html>
<html lang="en">
<head>
    <title>@ViewData["Title"] - WebApplication</title>
    ...

TempData

ASP.NET Core elérhetővé teszi a TempData. Ez a tulajdonság addig tárolja az adatokat, amíg el nem olvassa. A Keep és Peek metódusokkal törlés nélkül vizsgálhatja meg az adatokat. TempData akkor hasznos az átirányításhoz, ha több kérelemhez is szükség van adatokra.

Az alábbi kód a Message értékét állítja be TempDatahasználatával:

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");
    }
}

A Pages/Customers/Index.cshtml fájlban az alábbi korrektúra a Message értékét jeleníti meg TempDatahasználatával.

<h3>Msg: @Model.Message</h3>

A Pages/Customers/Index.cshtml.cs oldalmodell a [TempData] attribútumot alkalmazza a Message tulajdonságra.

[TempData]
public string Message { get; set; }

További információ: TempData.

Egy oldalon több kezelő

Az alábbi oldal két kezelő számára hoz létre korrektúrát a asp-page-handler Címke súgójának használatával:

@page
@model CreateFATHModel

<html>
<body>
    <p>
        Enter your name.
    </p>
    <div asp-validation-summary="All"></div>
    <form method="POST">
        <div><label>Name: <input asp-for="Customer.Name" /></label></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>

Az előző példában szereplő űrlapon két küldési gomb található, mindegyik a FormActionTagHelper használatával küldi el egy másik URL-címre. A asp-page-handler attribútum a asp-pagetársa. asp-page-handler olyan URL-címeket hoz létre, amelyek a lap által definiált kezelői metódusok mindegyikére elküldve lesznek. asp-page nincs megadva, mert a minta az aktuális lapra hivatkozik.

Az oldalmodell:

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();
        }
    }
}

Az előző kód a következő elnevezett kezelési metódusokat használ: ,. A névvel ellátott kezelő metódusokat úgy hozzuk létre, hogy a névben található szöveget On<HTTP Verb> után és Async előtt (ha létezik) vesszük. Az előző példában a lap metódusai az OnPostJoinListAsync és az OnPostJoinListUCAsync. Ha OnPost és Async el lettek távolítva, a kezelők nevei JoinList és JoinListUC.

<input type="submit" asp-page-handler="JoinList" value="Join" />
<input type="submit" asp-page-handler="JoinListUC" value="JOIN UC" />

Az előző kód használatával a OnPostJoinListAsync-ra küldött URL-útvonal a https://localhost:5001/Customers/CreateFATH?handler=JoinList. A OnPostJoinListUCAsync-hoz benyújtandó URL-útvonal https://localhost:5001/Customers/CreateFATH?handler=JoinListUC.

Egyéni útvonalak

A @page irányelv használatával:

  • Adjon meg egy egyéni útvonalat egy laphoz. A Névjegy oldalra vezető útvonal például beállítható /Some/Other/Path és @page "/Some/Other/Path"használatával.
  • Szegmensek hozzáfűzése egy lap alapértelmezett útvonalához. Egy "elem" szegmens például hozzáadható egy lap alapértelmezett útvonalához @page "item".
  • Paraméterek hozzáfűzése egy lap alapértelmezett útvonalához. Például egy idazonosítóparaméterre lehet szükség egy @page "{id}"-el rendelkező oldalhoz.

Az elérési út elején egy tilde (~) által kijelölt gyökér-relatív elérési út támogatott. A @page "~/Some/Other/Path" például ugyanaz, mint @page "/Some/Other/Path".

Ha nem tetszik a lekérdezési karakterlánc ?handler=JoinList az URL-címben, módosítsa az útvonalat úgy, hogy a kezelő neve az URL elérési út részében legyen. Az útvonal testre szabható úgy, hogy a @page irányelv után dupla idézőjelek közé foglalt útvonalsablont ad hozzá.

@page "{handler?}"
@model CreateRouteModel

<html>
<body>
    <p>
        Enter your name.
    </p>
    <div asp-validation-summary="All"></div>
    <form method="POST">
        <div><label>Name: <input asp-for="Customer.Name" /></label></div>
        <input type="submit" asp-page-handler="JoinList" value="Join" />
        <input type="submit" asp-page-handler="JoinListUC" value="JOIN UC" />
    </form>
</body>
</html>

Az előző kód használatával a https://localhost:5001/Customers/CreateFATH/JoinListURL-útvonal a OnPostJoinListAsync-hoz kerül beküldésre. Az URL-útvonal, amely a OnPostJoinListUCAsync-hoz kerül elküldésre, a https://localhost:5001/Customers/CreateFATH/JoinListUC.

Az alábbi ?handler azt jelenti, hogy az útvonalparaméter nem kötelező.

Speciális konfiguráció és beállítások

A legtöbb alkalmazás nem igényli a konfigurációt és a beállításokat a következő szakaszokban.

A speciális beállítások konfigurálásához használja a AddRazorPages túlterhelést, ami konfigurálja a RazorPagesOptions-et.

public void ConfigureServices(IServiceCollection services)
{            
    services.AddRazorPages(options =>
    {
        options.RootDirectory = "/MyPages";
        options.Conventions.AuthorizeFolder("/MyPages/Admin");
    });
}

A RazorPagesOptions a lapok gyökérkönyvtárának beállításához, illetve a lapok alkalmazásmodell-konvencióinak hozzáadásához. A konvenciókról további információkat a Razor oldalak engedélyezési konvencióirészben talál.

Az előre fordított nézetek összeállításához lásd a(z) Razor nézetkompilációbekezdést.

Adja meg, hogy Razor lapok a tartalom gyökerénél legyenek

Alapértelmezés szerint a Razor lapok a /Pages könyvtárban gyökereznek. Adja hozzá a WithRazorPagesAtContentRoot elemet annak megadására, hogy a Razor lapok az alkalmazás tartalomgyökerében a (ContentRootPath) találhatók.

public void ConfigureServices(IServiceCollection services)
{            
    services.AddRazorPages(options =>
        {
            options.Conventions.AuthorizeFolder("/MyPages/Admin");
        })
        .WithRazorPagesAtContentRoot();
}

Adja meg, hogy a Razor Pages egy egyéni gyökérkönyvtárban találhatók.

Adjon hozzá WithRazorPagesRoot annak megadásához, hogy Razor lapok egy egyéni gyökérkönyvtárban találhatók az alkalmazásban (adjon meg egy relatív elérési utat):

public void ConfigureServices(IServiceCollection services)
{            
    services.AddRazorPages(options =>
        {
            options.Conventions.AuthorizeFolder("/MyPages/Admin");
        })
        .WithRazorPagesRoot("/path/to/razor/pages");
}

További erőforrások