3부. ASP.NET Core의 스캐폴드된 Razor Pages
참고 항목
이 문서의 최신 버전은 아닙니다. 현재 릴리스는 이 문서의 .NET 8 버전을 참조 하세요.
Important
이 정보는 상업적으로 출시되기 전에 실질적으로 수정될 수 있는 시험판 제품과 관련이 있습니다. Microsoft는 여기에 제공된 정보에 대해 어떠한 명시적, 또는 묵시적인 보증을 하지 않습니다.
현재 릴리스는 이 문서의 .NET 8 버전을 참조 하세요.
작성자: Rick Anderson
이 자습서에서는 이전 자습서에서 스캐폴딩을 통해 만든 Razor 페이지를 살펴봅니다.
만들기, 삭제, 세부 정보 및 편집 페이지
Pages/Movies/Index.cshtml.cs
페이지 모델을 살펴봅니다.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.EntityFrameworkCore;
using RazorPagesMovie.Data;
using RazorPagesMovie.Models;
using Microsoft.AspNetCore.Mvc.Rendering;
namespace RazorPagesMovie.Pages.Movies
{
public class IndexModel : PageModel
{
private readonly RazorPagesMovie.Data.RazorPagesMovieContext _context;
public IndexModel(RazorPagesMovie.Data.RazorPagesMovieContext context)
{
_context = context;
}
public IList<Movie> Movie { get;set; } = default!;
public async Task OnGetAsync()
{
Movie = await _context.Movie.ToListAsync();
}
}
}
Razor Pages는 PageModel에서 파생됩니다. 일반적으로 PageModel
파생 클래스의 이름은 PageNameModel
로 지정됩니다. 예를 들어 인덱스 페이지의 이름은 IndexModel
로 지정됩니다.
생성자는 종속성 주입을 사용하여 RazorPagesMovieContext
를 페이지에 추가합니다.
public class IndexModel : PageModel
{
private readonly RazorPagesMovie.Data.RazorPagesMovieContext _context;
public IndexModel(RazorPagesMovie.Data.RazorPagesMovieContext context)
{
_context = context;
}
Entity Framework로 비동기 프로그래밍에 대한 자세한 내용은 비동기 코드를 참조하세요.
페이지에 대한 GET
요청을 만들면 OnGetAsync
메서드가 Razor Page에 동영상 목록을 반환합니다. Razor 페이지에서 OnGetAsync
또는 OnGet
을 호출하여 페이지 상태를 초기화합니다. 이 경우 OnGetAsync
는 동영상 목록을 가져와 표시합니다.
OnGet
이 void
를 반환하거나 OnGetAsync
가 Task
를 반환하면 return 문이 사용되지 않은 것입니다. 예를 들어 Privacy 페이지를 검토합니다.
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
namespace RazorPagesMovie.Pages
{
public class PrivacyModel : PageModel
{
private readonly ILogger<PrivacyModel> _logger;
public PrivacyModel(ILogger<PrivacyModel> logger)
{
_logger = logger;
}
public void OnGet()
{
}
}
}
반환 형식이 IActionResult 또는 Task<IActionResult>
이면 반환 문을 제공해야 합니다. 예를 들어 Pages/Movies/Create.cshtml.cs OnPostAsync
메서드입니다.
public async Task<IActionResult> OnPostAsync()
{
if (!ModelState.IsValid)
{
return Page();
}
_context.Movie.Add(Movie);
await _context.SaveChangesAsync();
return RedirectToPage("./Index");
}
Pages/Movies/Index.cshtml
Razor페이지를 살펴봅니다.
@page
@model RazorPagesMovie.Pages.Movies.IndexModel
@{
ViewData["Title"] = "Index";
}
<h1>Index</h1>
<p>
<a asp-page="Create">Create New</a>
</p>
<table class="table">
<thead>
<tr>
<th>
@Html.DisplayNameFor(model => model.Movie[0].Title)
</th>
<th>
@Html.DisplayNameFor(model => model.Movie[0].ReleaseDate)
</th>
<th>
@Html.DisplayNameFor(model => model.Movie[0].Genre)
</th>
<th>
@Html.DisplayNameFor(model => model.Movie[0].Price)
</th>
<th></th>
</tr>
</thead>
<tbody>
@foreach (var item in Model.Movie) {
<tr>
<td>
@Html.DisplayFor(modelItem => item.Title)
</td>
<td>
@Html.DisplayFor(modelItem => item.ReleaseDate)
</td>
<td>
@Html.DisplayFor(modelItem => item.Genre)
</td>
<td>
@Html.DisplayFor(modelItem => item.Price)
</td>
<td>
<a asp-page="./Edit" asp-route-id="@item.Id">Edit</a> |
<a asp-page="./Details" asp-route-id="@item.Id">Details</a> |
<a asp-page="./Delete" asp-route-id="@item.Id">Delete</a>
</td>
</tr>
}
</tbody>
</table>
Razor는 HTML에서 C# 또는 Razor 관련 태그로 전환될 수 있습니다. @
기호 뒤에 Razor 예약 키워드가 사용되면 이 기호는 Razor 관련 태그로 전환됩니다. 이외의 경우에는 C#으로 전환됩니다.
@page 지시문
@page
Razor 지시문은 파일을 MVC 작업으로 만듭니다. 이는 요청을 처리할 수 있음을 의미합니다. @page
는 페이지의 첫 번째 Razor 지시문이어야 합니다. @page
및 @model
은 Razor 관련 태그로 전환되는 예입니다. 자세한 내용은 Razor 구문을 참조하세요.
@model 지시문
@page
@model RazorPagesMovie.Pages.Movies.IndexModel
@model
지시문은 Razor Page에 전달되는 모델 형식을 지정합니다. 위의 예제에서 @model
줄은 Razor Page에서 PageModel
파생 클래스를 사용할 수 있게 만듭니다. 모델은 페이지에서 @Html.DisplayNameFor
및 @Html.DisplayFor
HTML 도우미에서 사용됩니다.
다음 HTML 도우미에서 사용되는 람다 식을 살펴봅니다.
@Html.DisplayNameFor(model => model.Movie[0].Title)
DisplayNameFor HTML 도우미는 람다 식에서 참조되는 Title
속성을 검사하여 표시 이름을 확인합니다. 람다 식은 계산되는 것이 아니라 검사됩니다. 즉, model
, model.Movie
또는 model.Movie[0]
가 null
이거나 비어 있을 경우 액세스 위반이 없습니다. 람다 식이 계산될 경우(예: @Html.DisplayFor(modelItem => item.Title)
사용) 모델의 속성 값이 계산됩니다.
레이아웃 페이지
RazorPagesMovieHomePrivacy 및 . 각 페이지는 동일한 메뉴 레이아웃을 표시합니다. 메뉴 레이아웃은 파일에서 Pages/Shared/_Layout.cshtml
구현됩니다.
Pages/Shared/_Layout.cshtml
파일을 열어 검사합니다.
레이아웃 템플릿을 사용하여 HTML 컨테이너 레이아웃을 다음과 같이 지정할 수 있습니다.
- 한 위치에 지정됩니다.
- 사이트의 여러 페이지에 적용됩니다.
@RenderBody()
줄을 찾습니다. RenderBody
는 사용자가 만드는 모든 페이지 특정 보기가 표시되는 자리 표시자이며 레이아웃 페이지에서 래핑됩니다. 예를 들어 링크를 선택하면 Privacy 보기가 Pages/Privacy.cshtml
메서드 내부에 RenderBody
렌더링됩니다.
ViewData 및 레이아웃
파일에서 다음 태그를 고려합니다.Pages/Movies/Index.cshtml
@page
@model RazorPagesMovie.Pages.Movies.IndexModel
@{
ViewData["Title"] = "Index";
}
강조 표시된 이전 태그는 C#으로 전환되는 Razor의 예제입니다. {
및 }
문자로 C# 코드 블록을 묶습니다.
PageModel
기본 클래스에는 데이터를 뷰에 전달하는 데 사용할 수 있는 ViewData
사전 속성이 있습니다. 키 값 패턴을 사용하여 개체가 ViewData
사전에 추가됩니다. 이전 샘플에서는 Title
속성이 ViewData
사전에 추가됩니다.
Title
속성이 Pages/Shared/_Layout.cshtml
파일에서 사용됩니다. 다음 태그는 파일의 처음 몇 줄을 보여 줍니다 _Layout.cshtml
.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>@ViewData["Title"] - RazorPagesMovie</title>
<link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.css" />
<link rel="stylesheet" href="~/css/site.css" asp-append-version="true" />
<link rel="stylesheet" href="~/RazorPagesMovie.styles.css" asp-append-version="true" />
레이아웃 업데이트
<title>
RazorPagesMovie 대신 Movie를Pages/Shared/_Layout.cshtml
표시하도록 파일의 요소를 변경합니다.<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>@ViewData["Title"] - Movie</title>
파일에서 다음 앵커 요소를 찾습니다
Pages/Shared/_Layout.cshtml
.<a class="navbar-brand" asp-area="" asp-page="/Index">RazorPagesMovie</a>
이전 요소를 다음 태그로 바꿉니다.
<a class="navbar-brand" asp-page="/Movies/Index">RpMovie</a>
이전 앵커 요소는 태그 도우미입니다. 이 경우에는 앵커 태그 도우미입니다.
asp-page="/Movies/Index"
태그 도우미 특성 및 값으로/Movies/Index
Razor 페이지의 링크를 만듭니다.asp-area
특성 값이 비어 있으므로 영역은 링크에서 사용되지 않습니다. 자세한 내용은 영역을 참조하세요.변경 내용을 저장하고 RpMovie 링크를 선택하여 앱을 테스트합니다. 문제가 있는 경우 GitHub에서 _Layout.cshtml 파일을 참조하세요.
Home, RpMovie, 만들기, 편집 및 삭제 링크를 테스트합니다. 각 페이지는 브라우저 탭에서 볼 수 있는 제목을 설정합니다. 페이지에 책갈피를 지정하면 책갈피에 제목이 사용됩니다.
참고 항목
Price
필드에 소수점을 입력하지 못할 수도 있습니다. 소수점으로 쉼표(",")를 사용하는 비영어 로캘 및 비미국 영어 날짜 형식에 대해 jQuery 유효성 검사를 지원하려면 앱을 세계화하는 단계를 수행해야 합니다. 소수점 추가에 대한 지침은 이 GitHub 문제 4076을 참조하세요.
Layout
속성은 Pages/_ViewStart.cshtml
파일에서 설정됩니다.
@{
Layout = "_Layout";
}
위의 태그는 Pages 폴더의 모든 Razor 파일에 대해 레이아웃 파일로 Pages/Shared/_Layout.cshtml
로 설정합니다. 자세한 내용은 레이아웃을 참조하세요.
Create 페이지 모델
페이지 모델을 검사합니다 Pages/Movies/Create.cshtml.cs
.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.AspNetCore.Mvc.Rendering;
using RazorPagesMovie.Data;
using RazorPagesMovie.Models;
namespace RazorPagesMovie.Pages.Movies
{
public class CreateModel : PageModel
{
private readonly RazorPagesMovie.Data.RazorPagesMovieContext _context;
public CreateModel(RazorPagesMovie.Data.RazorPagesMovieContext context)
{
_context = context;
}
public IActionResult OnGet()
{
return Page();
}
[BindProperty]
public Movie Movie { get; set; } = default!;
// To protect from overposting attacks, see https://aka.ms/RazorPagesCRUD
public async Task<IActionResult> OnPostAsync()
{
if (!ModelState.IsValid)
{
return Page();
}
_context.Movie.Add(Movie);
await _context.SaveChangesAsync();
return RedirectToPage("./Index");
}
}
}
OnGet
메서드는 페이지에 필요한 상태를 초기화합니다. 만들기 페이지에는 초기화할 상태가 없습니다. 따라서 Page
가 반환됩니다. 자습서의 뒷부분에서 상태를 초기화하는 OnGet
의 예가 나와 있습니다. 메서드는 Page
페이지를 렌더링하는 개체를 Create.cshtml
만듭니다PageResult
.
Movie
속성은 BindProperty 특성을 사용하여 모델 바인딩을 옵트인합니다. 만들기 폼이 폼 값을 게시하면 ASP.NET Core 런타임이 게시된 값을 Movie
모델에 바인딩합니다.
페이지에 폼 데이터가 게시되면 OnPostAsync
메서드가 실행됩니다.
public async Task<IActionResult> OnPostAsync()
{
if (!ModelState.IsValid)
{
return Page();
}
_context.Movie.Add(Movie);
await _context.SaveChangesAsync();
return RedirectToPage("./Index");
}
모델 오류가 있는 경우 폼과 게시된 모든 폼 데이터가 다시 표시됩니다. 대부분의 모델 오류는 폼이 게시되기 전에 클라이언트 쪽에서 catch할 수 있습니다. 예를 들어 데이터로 변환될 수 없는 날짜 필드에 대한 값을 게시하는 모델 오류가 발생할 수 있습니다. 클라이언트 쪽 유효성 검사 및 모델 유효성 검사는 자습서의 뒷부분에서 설명합니다.
모델 오류가 없는 경우:
- 데이터가 저장됩니다.
- 브라우저가 인덱스 페이지로 리디렉션됩니다.
Create Razor Page
Pages/Movies/Create.cshtml
Razor Page 파일을 살펴봅니다.
@page
@model RazorPagesMovie.Pages.Movies.CreateModel
@{
ViewData["Title"] = "Create";
}
<h1>Create</h1>
<h4>Movie</h4>
<hr />
<div class="row">
<div class="col-md-4">
<form method="post">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="Movie.Title" class="control-label"></label>
<input asp-for="Movie.Title" class="form-control" />
<span asp-validation-for="Movie.Title" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Movie.ReleaseDate" class="control-label"></label>
<input asp-for="Movie.ReleaseDate" class="form-control" />
<span asp-validation-for="Movie.ReleaseDate" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Movie.Genre" class="control-label"></label>
<input asp-for="Movie.Genre" class="form-control" />
<span asp-validation-for="Movie.Genre" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Movie.Price" class="control-label"></label>
<input asp-for="Movie.Price" class="form-control" />
<span asp-validation-for="Movie.Price" class="text-danger"></span>
</div>
<div class="form-group">
<input type="submit" value="Create" class="btn btn-primary" />
</div>
</form>
</div>
</div>
<div>
<a asp-page="Index">Back to List</a>
</div>
@section Scripts {
@{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}
Visual Studio에서는 다음 태그를 태그 도우미에 사용되는 독특한 굵은 글꼴로 표시합니다.
<form method="post">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<label asp-for="Movie.Title" class="control-label"></label>
<input asp-for="Movie.Title" class="form-control" />
<span asp-validation-for="Movie.Title" class="text-danger"></span>
<form method="post">
요소는 폼 태그 도우미입니다. 폼 태그 도우미에는 위조 방지 토큰이 자동으로 포함됩니다.
스캐폴딩 엔진은 ID를 제외하고 다음과 비슷한 모델에서 필드마다 Razor 태그를 만듭니다.
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="Movie.Title" class="control-label"></label>
<input asp-for="Movie.Title" class="form-control" />
<span asp-validation-for="Movie.Title" class="text-danger"></span>
</div>
유효성 검사 태그 도우미 (<div asp-validation-summary
및 <span asp-validation-for
) 는 유효성 검사 오류를 표시합니다. 유효성 검사는 이 시리즈의 뒷부분에서 자세히 설명합니다.
레이블 태그 도우미(<label asp-for="Movie.Title" class="control-label"></label>
)는 Title
속성에 대한 레이블 캡션 및 [for]
특성을 생성합니다.
입력 태그 도우미(<input asp-for="Movie.Title" class="form-control">
)는 DataAnnotations 특성을 사용하고 클라이언트 쪽의 jQuery 유효성 검사에 필요한 HTML 특성을 생성합니다.
태그 도우미(예: <form method="post">
)에 대한 자세한 내용은 ASP.NET Core의 태그 도우미를 참조하세요.
다음 단계
만들기, 삭제, 세부 정보 및 편집 페이지
Pages/Movies/Index.cshtml.cs
페이지 모델을 살펴봅니다.
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.EntityFrameworkCore;
using RazorPagesMovie.Models;
namespace RazorPagesMovie.Pages.Movies;
public class IndexModel : PageModel
{
private readonly RazorPagesMovie.Data.RazorPagesMovieContext _context;
public IndexModel(RazorPagesMovie.Data.RazorPagesMovieContext context)
{
_context = context;
}
public IList<Movie> Movie { get;set; } = default!;
public async Task OnGetAsync()
{
if (_context.Movie != null)
{
Movie = await _context.Movie.ToListAsync();
}
}
}
Razor Pages는 PageModel에서 파생됩니다. 일반적으로 PageModel
파생 클래스의 이름은 PageNameModel
로 지정됩니다. 예를 들어 인덱스 페이지의 이름은 IndexModel
로 지정됩니다.
생성자는 종속성 주입을 사용하여 RazorPagesMovieContext
를 페이지에 추가합니다.
public class IndexModel : PageModel
{
private readonly RazorPagesMovie.Data.RazorPagesMovieContext _context;
public IndexModel(RazorPagesMovie.Data.RazorPagesMovieContext context)
{
_context = context;
}
Entity Framework로 비동기 프로그래밍에 대한 자세한 내용은 비동기 코드를 참조하세요.
페이지에 대한 GET
요청을 만들면 OnGetAsync
메서드가 Razor Page에 동영상 목록을 반환합니다. Razor 페이지에서 OnGetAsync
또는 OnGet
을 호출하여 페이지 상태를 초기화합니다. 이 경우 OnGetAsync
는 동영상 목록을 가져와 표시합니다.
OnGet
이 void
를 반환하거나 OnGetAsync
가 Task
를 반환하면 return 문이 사용되지 않은 것입니다. 예를 들어 Privacy 페이지를 검토합니다.
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
namespace RazorPagesMovie.Pages
{
public class PrivacyModel : PageModel
{
private readonly ILogger<PrivacyModel> _logger;
public PrivacyModel(ILogger<PrivacyModel> logger)
{
_logger = logger;
}
public void OnGet()
{
}
}
}
반환 형식이 IActionResult 또는 Task<IActionResult>
이면 반환 문을 제공해야 합니다. 예를 들어 Pages/Movies/Create.cshtml.cs OnPostAsync
메서드입니다.
public async Task<IActionResult> OnPostAsync()
{
if (!ModelState.IsValid)
{
return Page();
}
_context.Movie.Add(Movie);
await _context.SaveChangesAsync();
return RedirectToPage("./Index");
}
Pages/Movies/Index.cshtml
Razor페이지를 살펴봅니다.
@page
@model RazorPagesMovie.Pages.Movies.IndexModel
@{
ViewData["Title"] = "Index";
}
<h1>Index</h1>
<p>
<a asp-page="Create">Create New</a>
</p>
<table class="table">
<thead>
<tr>
<th>
@Html.DisplayNameFor(model => model.Movie[0].Title)
</th>
<th>
@Html.DisplayNameFor(model => model.Movie[0].ReleaseDate)
</th>
<th>
@Html.DisplayNameFor(model => model.Movie[0].Genre)
</th>
<th>
@Html.DisplayNameFor(model => model.Movie[0].Price)
</th>
<th></th>
</tr>
</thead>
<tbody>
@foreach (var item in Model.Movie) {
<tr>
<td>
@Html.DisplayFor(modelItem => item.Title)
</td>
<td>
@Html.DisplayFor(modelItem => item.ReleaseDate)
</td>
<td>
@Html.DisplayFor(modelItem => item.Genre)
</td>
<td>
@Html.DisplayFor(modelItem => item.Price)
</td>
<td>
<a asp-page="./Edit" asp-route-id="@item.Id">Edit</a> |
<a asp-page="./Details" asp-route-id="@item.Id">Details</a> |
<a asp-page="./Delete" asp-route-id="@item.Id">Delete</a>
</td>
</tr>
}
</tbody>
</table>
Razor는 HTML에서 C# 또는 Razor 관련 태그로 전환될 수 있습니다. @
기호 뒤에 Razor 예약 키워드가 사용되면 이 기호는 Razor 관련 태그로 전환됩니다. 이외의 경우에는 C#으로 전환됩니다.
@page 지시문
@page
Razor 지시문은 파일을 MVC 작업으로 만듭니다. 이는 요청을 처리할 수 있음을 의미합니다. @page
는 페이지의 첫 번째 Razor 지시문이어야 합니다. @page
및 @model
은 Razor 관련 태그로 전환되는 예입니다. 자세한 내용은 Razor 구문을 참조하세요.
@model 지시문
@page
@model RazorPagesMovie.Pages.Movies.IndexModel
@model
지시문은 Razor Page에 전달되는 모델 형식을 지정합니다. 위의 예제에서 @model
줄은 Razor Page에서 PageModel
파생 클래스를 사용할 수 있게 만듭니다. 모델은 페이지에서 @Html.DisplayNameFor
및 @Html.DisplayFor
HTML 도우미에서 사용됩니다.
다음 HTML 도우미에서 사용되는 람다 식을 살펴봅니다.
@Html.DisplayNameFor(model => model.Movie[0].Title)
DisplayNameFor HTML 도우미는 람다 식에서 참조되는 Title
속성을 검사하여 표시 이름을 확인합니다. 람다 식은 계산되는 것이 아니라 검사됩니다. 즉, model
, model.Movie
또는 model.Movie[0]
가 null
이거나 비어 있을 경우 액세스 위반이 없습니다. 람다 식이 계산될 경우(예: @Html.DisplayFor(modelItem => item.Title)
사용) 모델의 속성 값이 계산됩니다.
레이아웃 페이지
RazorPagesMovieHomePrivacy 및 . 각 페이지는 동일한 메뉴 레이아웃을 표시합니다. 메뉴 레이아웃은 파일에서 Pages/Shared/_Layout.cshtml
구현됩니다.
Pages/Shared/_Layout.cshtml
파일을 열어 검사합니다.
레이아웃 템플릿을 사용하여 HTML 컨테이너 레이아웃을 다음과 같이 지정할 수 있습니다.
- 한 위치에 지정됩니다.
- 사이트의 여러 페이지에 적용됩니다.
@RenderBody()
줄을 찾습니다. RenderBody
는 사용자가 만드는 모든 페이지 특정 보기가 표시되는 자리 표시자이며 레이아웃 페이지에서 래핑됩니다. 예를 들어 링크를 선택하면 Privacy 보기가 Pages/Privacy.cshtml
메서드 내부에 RenderBody
렌더링됩니다.
ViewData 및 레이아웃
파일에서 다음 태그를 고려합니다.Pages/Movies/Index.cshtml
@page
@model RazorPagesMovie.Pages.Movies.IndexModel
@{
ViewData["Title"] = "Index";
}
강조 표시된 이전 태그는 C#으로 전환되는 Razor의 예제입니다. {
및 }
문자로 C# 코드 블록을 묶습니다.
PageModel
기본 클래스에는 데이터를 뷰에 전달하는 데 사용할 수 있는 ViewData
사전 속성이 있습니다. 키 값 패턴을 사용하여 개체가 ViewData
사전에 추가됩니다. 이전 샘플에서는 Title
속성이 ViewData
사전에 추가됩니다.
Title
속성이 Pages/Shared/_Layout.cshtml
파일에서 사용됩니다. 다음 태그는 파일의 처음 몇 줄을 보여 줍니다 _Layout.cshtml
.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>@ViewData["Title"] - RazorPagesMovie</title>
<link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.min.css" />
<link rel="stylesheet" href="~/css/site.css" asp-append-version="true" />
<link rel="stylesheet" href="~/RazorPagesMovie.styles.css" asp-append-version="true" />
레이아웃 업데이트
<title>
RazorPagesMovie 대신 Movie를Pages/Shared/_Layout.cshtml
표시하도록 파일의 요소를 변경합니다.<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>@ViewData["Title"] - Movie</title>
파일에서 다음 앵커 요소를 찾습니다
Pages/Shared/_Layout.cshtml
.<a class="navbar-brand" asp-area="" asp-page="/Index">RazorPagesMovie</a>
이전 요소를 다음 태그로 바꿉니다.
<a class="navbar-brand" asp-page="/Movies/Index">RpMovie</a>
이전 앵커 요소는 태그 도우미입니다. 이 경우에는 앵커 태그 도우미입니다.
asp-page="/Movies/Index"
태그 도우미 특성 및 값으로/Movies/Index
Razor 페이지의 링크를 만듭니다.asp-area
특성 값이 비어 있으므로 영역은 링크에서 사용되지 않습니다. 자세한 내용은 영역을 참조하세요.변경 내용을 저장하고 RpMovie 링크를 선택하여 앱을 테스트합니다. 문제가 있는 경우 GitHub에서 _Layout.cshtml 파일을 참조하세요.
Home, RpMovie, 만들기, 편집 및 삭제 링크를 테스트합니다. 각 페이지는 브라우저 탭에서 볼 수 있는 제목을 설정합니다. 페이지에 책갈피를 지정하면 책갈피에 제목이 사용됩니다.
참고 항목
Price
필드에 소수점을 입력하지 못할 수도 있습니다. 소수점으로 쉼표(",")를 사용하는 비영어 로캘 및 비미국 영어 날짜 형식에 대해 jQuery 유효성 검사를 지원하려면 앱을 세계화하는 단계를 수행해야 합니다. 소수점 추가에 대한 지침은 이 GitHub 문제 4076을 참조하세요.
Layout
속성은 Pages/_ViewStart.cshtml
파일에서 설정됩니다.
@{
Layout = "_Layout";
}
위의 태그는 Pages 폴더의 모든 Razor 파일에 대해 레이아웃 파일로 Pages/Shared/_Layout.cshtml
로 설정합니다. 자세한 내용은 레이아웃을 참조하세요.
Create 페이지 모델
페이지 모델을 검사합니다 Pages/Movies/Create.cshtml.cs
.
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using RazorPagesMovie.Models;
namespace RazorPagesMovie.Pages.Movies
{
public class CreateModel : PageModel
{
private readonly RazorPagesMovie.Data.RazorPagesMovieContext _context;
public CreateModel(RazorPagesMovie.Data.RazorPagesMovieContext context)
{
_context = context;
}
public IActionResult OnGet()
{
return Page();
}
[BindProperty]
public Movie Movie { get; set; } = default!;
// To protect from overposting attacks, see https://aka.ms/RazorPagesCRUD
public async Task<IActionResult> OnPostAsync()
{
if (!ModelState.IsValid || _context.Movie == null || Movie == null)
{
return Page();
}
_context.Movie.Add(Movie);
await _context.SaveChangesAsync();
return RedirectToPage("./Index");
}
}
}
OnGet
메서드는 페이지에 필요한 상태를 초기화합니다. 만들기 페이지에는 초기화할 상태가 없습니다. 따라서 Page
가 반환됩니다. 자습서의 뒷부분에서 상태를 초기화하는 OnGet
의 예가 나와 있습니다. 메서드는 Page
페이지를 렌더링하는 개체를 Create.cshtml
만듭니다PageResult
.
Movie
속성은 BindProperty 특성을 사용하여 모델 바인딩을 옵트인합니다. 만들기 폼이 폼 값을 게시하면 ASP.NET Core 런타임이 게시된 값을 Movie
모델에 바인딩합니다.
페이지에 폼 데이터가 게시되면 OnPostAsync
메서드가 실행됩니다.
public async Task<IActionResult> OnPostAsync()
{
if (!ModelState.IsValid)
{
return Page();
}
_context.Movie.Add(Movie);
await _context.SaveChangesAsync();
return RedirectToPage("./Index");
}
모델 오류가 있는 경우 폼과 게시된 모든 폼 데이터가 다시 표시됩니다. 대부분의 모델 오류는 폼이 게시되기 전에 클라이언트 쪽에서 catch할 수 있습니다. 예를 들어 데이터로 변환될 수 없는 날짜 필드에 대한 값을 게시하는 모델 오류가 발생할 수 있습니다. 클라이언트 쪽 유효성 검사 및 모델 유효성 검사는 자습서의 뒷부분에서 설명합니다.
모델 오류가 없는 경우:
- 데이터가 저장됩니다.
- 브라우저가 인덱스 페이지로 리디렉션됩니다.
Create Razor Page
Pages/Movies/Create.cshtml
Razor Page 파일을 살펴봅니다.
@page
@model RazorPagesMovie.Pages.Movies.CreateModel
@{
ViewData["Title"] = "Create";
}
<h1>Create</h1>
<h4>Movie</h4>
<hr />
<div class="row">
<div class="col-md-4">
<form method="post">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="Movie.Title" class="control-label"></label>
<input asp-for="Movie.Title" class="form-control" />
<span asp-validation-for="Movie.Title" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Movie.ReleaseDate" class="control-label"></label>
<input asp-for="Movie.ReleaseDate" class="form-control" />
<span asp-validation-for="Movie.ReleaseDate" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Movie.Genre" class="control-label"></label>
<input asp-for="Movie.Genre" class="form-control" />
<span asp-validation-for="Movie.Genre" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Movie.Price" class="control-label"></label>
<input asp-for="Movie.Price" class="form-control" />
<span asp-validation-for="Movie.Price" class="text-danger"></span>
</div>
<div class="form-group">
<input type="submit" value="Create" class="btn btn-primary" />
</div>
</form>
</div>
</div>
<div>
<a asp-page="Index">Back to List</a>
</div>
@section Scripts {
@{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}
Visual Studio에서는 다음 태그를 태그 도우미에 사용되는 독특한 굵은 글꼴로 표시합니다.
<form method="post">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<label asp-for="Movie.Title" class="control-label"></label>
<input asp-for="Movie.Title" class="form-control" />
<span asp-validation-for="Movie.Title" class="text-danger"></span>
<form method="post">
요소는 폼 태그 도우미입니다. 폼 태그 도우미에는 위조 방지 토큰이 자동으로 포함됩니다.
스캐폴딩 엔진은 ID를 제외하고 다음과 비슷한 모델에서 필드마다 Razor 태그를 만듭니다.
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="Movie.Title" class="control-label"></label>
<input asp-for="Movie.Title" class="form-control" />
<span asp-validation-for="Movie.Title" class="text-danger"></span>
</div>
유효성 검사 태그 도우미 (<div asp-validation-summary
및 <span asp-validation-for
) 는 유효성 검사 오류를 표시합니다. 유효성 검사는 이 시리즈의 뒷부분에서 자세히 설명합니다.
레이블 태그 도우미(<label asp-for="Movie.Title" class="control-label"></label>
)는 Title
속성에 대한 레이블 캡션 및 [for]
특성을 생성합니다.
입력 태그 도우미(<input asp-for="Movie.Title" class="form-control">
)는 DataAnnotations 특성을 사용하고 클라이언트 쪽의 jQuery 유효성 검사에 필요한 HTML 특성을 생성합니다.
태그 도우미(예: <form method="post">
)에 대한 자세한 내용은 ASP.NET Core의 태그 도우미를 참조하세요.
다음 단계
만들기, 삭제, 세부 정보 및 편집 페이지
Pages/Movies/Index.cshtml.cs
페이지 모델을 살펴봅니다.
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.EntityFrameworkCore;
using RazorPagesMovie.Models;
namespace RazorPagesMovie.Pages.Movies;
public class IndexModel : PageModel
{
private readonly RazorPagesMovie.Data.RazorPagesMovieContext _context;
public IndexModel(RazorPagesMovie.Data.RazorPagesMovieContext context)
{
_context = context;
}
public IList<Movie> Movie { get;set; } = default!;
public async Task OnGetAsync()
{
if (_context.Movie != null)
{
Movie = await _context.Movie.ToListAsync();
}
}
}
Razor Pages는 PageModel에서 파생됩니다. 일반적으로 PageModel
파생 클래스의 이름은 PageNameModel
로 지정됩니다. 예를 들어 인덱스 페이지의 이름은 IndexModel
로 지정됩니다.
생성자는 종속성 주입을 사용하여 RazorPagesMovieContext
를 페이지에 추가합니다.
public class IndexModel : PageModel
{
private readonly RazorPagesMovie.Data.RazorPagesMovieContext _context;
public IndexModel(RazorPagesMovie.Data.RazorPagesMovieContext context)
{
_context = context;
}
Entity Framework로 비동기 프로그래밍에 대한 자세한 내용은 비동기 코드를 참조하세요.
페이지에 대한 GET
요청을 만들면 OnGetAsync
메서드가 Razor Page에 동영상 목록을 반환합니다. Razor 페이지에서 OnGetAsync
또는 OnGet
을 호출하여 페이지 상태를 초기화합니다. 이 경우 OnGetAsync
는 동영상 목록을 가져와 표시합니다.
OnGet
이 void
를 반환하거나 OnGetAsync
가 Task
를 반환하면 return 문이 사용되지 않은 것입니다. 예를 들어 Privacy 페이지를 검토합니다.
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
namespace RazorPagesMovie.Pages
{
public class PrivacyModel : PageModel
{
private readonly ILogger<PrivacyModel> _logger;
public PrivacyModel(ILogger<PrivacyModel> logger)
{
_logger = logger;
}
public void OnGet()
{
}
}
}
반환 형식이 IActionResult 또는 Task<IActionResult>
이면 반환 문을 제공해야 합니다. 예를 들어 Pages/Movies/Create.cshtml.cs OnPostAsync
메서드입니다.
public async Task<IActionResult> OnPostAsync()
{
if (!ModelState.IsValid)
{
return Page();
}
_context.Movie.Add(Movie);
await _context.SaveChangesAsync();
return RedirectToPage("./Index");
}
Pages/Movies/Index.cshtml
Razor페이지를 살펴봅니다.
@page
@model RazorPagesMovie.Pages.Movies.IndexModel
@{
ViewData["Title"] = "Index";
}
<h1>Index</h1>
<p>
<a asp-page="Create">Create New</a>
</p>
<table class="table">
<thead>
<tr>
<th>
@Html.DisplayNameFor(model => model.Movie[0].Title)
</th>
<th>
@Html.DisplayNameFor(model => model.Movie[0].ReleaseDate)
</th>
<th>
@Html.DisplayNameFor(model => model.Movie[0].Genre)
</th>
<th>
@Html.DisplayNameFor(model => model.Movie[0].Price)
</th>
<th></th>
</tr>
</thead>
<tbody>
@foreach (var item in Model.Movie) {
<tr>
<td>
@Html.DisplayFor(modelItem => item.Title)
</td>
<td>
@Html.DisplayFor(modelItem => item.ReleaseDate)
</td>
<td>
@Html.DisplayFor(modelItem => item.Genre)
</td>
<td>
@Html.DisplayFor(modelItem => item.Price)
</td>
<td>
<a asp-page="./Edit" asp-route-id="@item.Id">Edit</a> |
<a asp-page="./Details" asp-route-id="@item.Id">Details</a> |
<a asp-page="./Delete" asp-route-id="@item.Id">Delete</a>
</td>
</tr>
}
</tbody>
</table>
Razor는 HTML에서 C# 또는 Razor 관련 태그로 전환될 수 있습니다. @
기호 뒤에 Razor 예약 키워드가 사용되면 이 기호는 Razor 관련 태그로 전환됩니다. 이외의 경우에는 C#으로 전환됩니다.
@page 지시문
@page
Razor 지시문은 파일을 MVC 작업으로 만듭니다. 이는 요청을 처리할 수 있음을 의미합니다. @page
는 페이지의 첫 번째 Razor 지시문이어야 합니다. @page
및 @model
은 Razor 관련 태그로 전환되는 예입니다. 자세한 내용은 Razor 구문을 참조하세요.
@model 지시문
@page
@model RazorPagesMovie.Pages.Movies.IndexModel
@model
지시문은 Razor Page에 전달되는 모델 형식을 지정합니다. 위의 예제에서 @model
줄은 Razor Page에서 PageModel
파생 클래스를 사용할 수 있게 만듭니다. 모델은 페이지에서 @Html.DisplayNameFor
및 @Html.DisplayFor
HTML 도우미에서 사용됩니다.
다음 HTML 도우미에서 사용되는 람다 식을 살펴봅니다.
@Html.DisplayNameFor(model => model.Movie[0].Title)
DisplayNameFor HTML 도우미는 람다 식에서 참조되는 Title
속성을 검사하여 표시 이름을 확인합니다. 람다 식은 계산되는 것이 아니라 검사됩니다. 즉, model
, model.Movie
또는 model.Movie[0]
가 null
이거나 비어 있을 경우 액세스 위반이 없습니다. 람다 식이 계산될 경우(예: @Html.DisplayFor(modelItem => item.Title)
사용) 모델의 속성 값이 계산됩니다.
레이아웃 페이지
RazorPagesMovieHomePrivacy 및 . 각 페이지는 동일한 메뉴 레이아웃을 표시합니다. 메뉴 레이아웃은 파일에서 Pages/Shared/_Layout.cshtml
구현됩니다.
Pages/Shared/_Layout.cshtml
파일을 열어 검사합니다.
레이아웃 템플릿을 사용하여 HTML 컨테이너 레이아웃을 다음과 같이 지정할 수 있습니다.
- 한 위치에 지정됩니다.
- 사이트의 여러 페이지에 적용됩니다.
@RenderBody()
줄을 찾습니다. RenderBody
는 사용자가 만드는 모든 페이지 특정 보기가 표시되는 자리 표시자이며 레이아웃 페이지에서 래핑됩니다. 예를 들어 링크를 선택하면 Privacy 보기가 Pages/Privacy.cshtml
메서드 내부에 RenderBody
렌더링됩니다.
ViewData 및 레이아웃
파일에서 다음 태그를 고려합니다.Pages/Movies/Index.cshtml
@page
@model RazorPagesMovie.Pages.Movies.IndexModel
@{
ViewData["Title"] = "Index";
}
강조 표시된 이전 태그는 C#으로 전환되는 Razor의 예제입니다. {
및 }
문자로 C# 코드 블록을 묶습니다.
PageModel
기본 클래스에는 데이터를 뷰에 전달하는 데 사용할 수 있는 ViewData
사전 속성이 있습니다. 키 값 패턴을 사용하여 개체가 ViewData
사전에 추가됩니다. 이전 샘플에서는 Title
속성이 ViewData
사전에 추가됩니다.
Title
속성이 Pages/Shared/_Layout.cshtml
파일에서 사용됩니다. 다음 태그는 파일의 처음 몇 줄을 보여 줍니다 _Layout.cshtml
.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>@ViewData["Title"] - RazorPagesMovie</title>
<link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.min.css" />
<link rel="stylesheet" href="~/css/site.css" asp-append-version="true" />
<link rel="stylesheet" href="~/RazorPagesMovie.styles.css" asp-append-version="true" />
@*Markup removed for brevity.*@
줄은 Razor 주석입니다. HTML 주석 <!-- -->
과 달리 Razor 주석은 클라이언트에 전송되지 않습니다. 자세한 내용은 MDN 웹 문서: HTML 시작을 참조하세요.
레이아웃 업데이트
<title>
RazorPagesMovie 대신 Movie를Pages/Shared/_Layout.cshtml
표시하도록 파일의 요소를 변경합니다.<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>@ViewData["Title"] - Movie</title>
파일에서 다음 앵커 요소를 찾습니다
Pages/Shared/_Layout.cshtml
.<a class="navbar-brand" asp-area="" asp-page="/Index">RazorPagesMovie</a>
이전 요소를 다음 태그로 바꿉니다.
<a class="navbar-brand" asp-page="/Movies/Index">RpMovie</a>
이전 앵커 요소는 태그 도우미입니다. 이 경우에는 앵커 태그 도우미입니다.
asp-page="/Movies/Index"
태그 도우미 특성 및 값으로/Movies/Index
Razor 페이지의 링크를 만듭니다.asp-area
특성 값이 비어 있으므로 영역은 링크에서 사용되지 않습니다. 자세한 내용은 영역을 참조하세요.변경 내용을 저장하고 RpMovie 링크를 선택하여 앱을 테스트합니다. 문제가 있는 경우 GitHub에서 _Layout.cshtml 파일을 참조하세요.
Home, RpMovie, 만들기, 편집 및 삭제 링크를 테스트합니다. 각 페이지는 브라우저 탭에서 볼 수 있는 제목을 설정합니다. 페이지에 책갈피를 지정하면 책갈피에 제목이 사용됩니다.
참고 항목
Price
필드에 소수점을 입력하지 못할 수도 있습니다. 소수점으로 쉼표(",")를 사용하는 비영어 로캘 및 비미국 영어 날짜 형식에 대해 jQuery 유효성 검사를 지원하려면 앱을 세계화하는 단계를 수행해야 합니다. 소수점 추가에 대한 지침은 이 GitHub 문제 4076을 참조하세요.
Layout
속성은 Pages/_ViewStart.cshtml
파일에서 설정됩니다.
@{
Layout = "_Layout";
}
위의 태그는 Pages 폴더의 모든 Razor 파일에 대해 레이아웃 파일로 Pages/Shared/_Layout.cshtml
로 설정합니다. 자세한 내용은 레이아웃을 참조하세요.
Create 페이지 모델
페이지 모델을 검사합니다 Pages/Movies/Create.cshtml.cs
.
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using RazorPagesMovie.Models;
namespace RazorPagesMovie.Pages.Movies
{
public class CreateModel : PageModel
{
private readonly RazorPagesMovie.Data.RazorPagesMovieContext _context;
public CreateModel(RazorPagesMovie.Data.RazorPagesMovieContext context)
{
_context = context;
}
public IActionResult OnGet()
{
return Page();
}
[BindProperty]
public Movie Movie { get; set; } = default!;
// To protect from overposting attacks, see https://aka.ms/RazorPagesCRUD
public async Task<IActionResult> OnPostAsync()
{
if (!ModelState.IsValid || _context.Movie == null || Movie == null)
{
return Page();
}
_context.Movie.Add(Movie);
await _context.SaveChangesAsync();
return RedirectToPage("./Index");
}
}
}
OnGet
메서드는 페이지에 필요한 상태를 초기화합니다. 만들기 페이지에는 초기화할 상태가 없습니다. 따라서 Page
가 반환됩니다. 자습서의 뒷부분에서 상태를 초기화하는 OnGet
의 예가 나와 있습니다. 메서드는 Page
페이지를 렌더링하는 개체를 Create.cshtml
만듭니다PageResult
.
Movie
속성은 BindProperty 특성을 사용하여 모델 바인딩을 옵트인합니다. 만들기 폼이 폼 값을 게시하면 ASP.NET Core 런타임이 게시된 값을 Movie
모델에 바인딩합니다.
페이지에 폼 데이터가 게시되면 OnPostAsync
메서드가 실행됩니다.
public async Task<IActionResult> OnPostAsync()
{
if (!ModelState.IsValid)
{
return Page();
}
_context.Movie.Add(Movie);
await _context.SaveChangesAsync();
return RedirectToPage("./Index");
}
모델 오류가 있는 경우 폼과 게시된 모든 폼 데이터가 다시 표시됩니다. 대부분의 모델 오류는 폼이 게시되기 전에 클라이언트 쪽에서 catch할 수 있습니다. 예를 들어 데이터로 변환될 수 없는 날짜 필드에 대한 값을 게시하는 모델 오류가 발생할 수 있습니다. 클라이언트 쪽 유효성 검사 및 모델 유효성 검사는 자습서의 뒷부분에서 설명합니다.
모델 오류가 없는 경우:
- 데이터가 저장됩니다.
- 브라우저가 인덱스 페이지로 리디렉션됩니다.
Create Razor Page
Pages/Movies/Create.cshtml
Razor Page 파일을 살펴봅니다.
@page
@model RazorPagesMovie.Pages.Movies.CreateModel
@{
ViewData["Title"] = "Create";
}
<h1>Create</h1>
<h4>Movie</h4>
<hr />
<div class="row">
<div class="col-md-4">
<form method="post">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="Movie.Title" class="control-label"></label>
<input asp-for="Movie.Title" class="form-control" />
<span asp-validation-for="Movie.Title" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Movie.ReleaseDate" class="control-label"></label>
<input asp-for="Movie.ReleaseDate" class="form-control" />
<span asp-validation-for="Movie.ReleaseDate" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Movie.Genre" class="control-label"></label>
<input asp-for="Movie.Genre" class="form-control" />
<span asp-validation-for="Movie.Genre" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Movie.Price" class="control-label"></label>
<input asp-for="Movie.Price" class="form-control" />
<span asp-validation-for="Movie.Price" class="text-danger"></span>
</div>
<div class="form-group">
<input type="submit" value="Create" class="btn btn-primary" />
</div>
</form>
</div>
</div>
<div>
<a asp-page="Index">Back to List</a>
</div>
@section Scripts {
@{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}
Visual Studio에서는 다음 태그를 태그 도우미에 사용되는 독특한 굵은 글꼴로 표시합니다.
<form method="post">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<label asp-for="Movie.Title" class="control-label"></label>
<input asp-for="Movie.Title" class="form-control" />
<span asp-validation-for="Movie.Title" class="text-danger"></span>
<form method="post">
요소는 폼 태그 도우미입니다. 폼 태그 도우미에는 위조 방지 토큰이 자동으로 포함됩니다.
스캐폴딩 엔진은 ID를 제외하고 다음과 비슷한 모델에서 필드마다 Razor 태그를 만듭니다.
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="Movie.Title" class="control-label"></label>
<input asp-for="Movie.Title" class="form-control" />
<span asp-validation-for="Movie.Title" class="text-danger"></span>
</div>
유효성 검사 태그 도우미 (<div asp-validation-summary
및 <span asp-validation-for
) 는 유효성 검사 오류를 표시합니다. 유효성 검사는 이 시리즈의 뒷부분에서 자세히 설명합니다.
레이블 태그 도우미(<label asp-for="Movie.Title" class="control-label"></label>
)는 Title
속성에 대한 레이블 캡션 및 [for]
특성을 생성합니다.
입력 태그 도우미(<input asp-for="Movie.Title" class="form-control">
)는 DataAnnotations 특성을 사용하고 클라이언트 쪽의 jQuery 유효성 검사에 필요한 HTML 특성을 생성합니다.
태그 도우미(예: <form method="post">
)에 대한 자세한 내용은 ASP.NET Core의 태그 도우미를 참조하세요.
다음 단계
만들기, 삭제, 세부 정보 및 편집 페이지
Pages/Movies/Index.cshtml.cs
페이지 모델을 살펴봅니다.
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.EntityFrameworkCore;
using RazorPagesMovie.Models;
namespace RazorPagesMovie.Pages.Movies
{
public class IndexModel : PageModel
{
private readonly RazorPagesMovie.Data.RazorPagesMovieContext _context;
public IndexModel(RazorPagesMovie.Data.RazorPagesMovieContext context)
{
_context = context;
}
public IList<Movie> Movie { get;set; } = default!;
public async Task OnGetAsync()
{
if (_context.Movie != null)
{
Movie = await _context.Movie.ToListAsync();
}
}
}
}
Razor Pages는 PageModel에서 파생됩니다. 일반적으로 PageModel
파생 클래스의 이름은 PageNameModel
로 지정됩니다. 예를 들어 인덱스 페이지의 이름은 IndexModel
로 지정됩니다.
생성자는 종속성 주입을 사용하여 RazorPagesMovieContext
를 페이지에 추가합니다.
public class IndexModel : PageModel
{
private readonly RazorPagesMovie.Data.RazorPagesMovieContext _context;
public IndexModel(RazorPagesMovie.Data.RazorPagesMovieContext context)
{
_context = context;
}
Entity Framework로 비동기 프로그래밍에 대한 자세한 내용은 비동기 코드를 참조하세요.
페이지에 대한 요청을 만들면 OnGetAsync
메서드가 Razor Page에 동영상 목록을 반환합니다. Razor 페이지에서 OnGetAsync
또는 OnGet
을 호출하여 페이지 상태를 초기화합니다. 이 경우 OnGetAsync
는 동영상 목록을 가져와 표시합니다.
OnGet
이 void
를 반환하거나 OnGetAsync
가 Task
를 반환하면 return 문이 사용되지 않은 것입니다. 예를 들어 Privacy 페이지를 검토합니다.
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
namespace RazorPagesMovie.Pages
{
public class PrivacyModel : PageModel
{
private readonly ILogger<PrivacyModel> _logger;
public PrivacyModel(ILogger<PrivacyModel> logger)
{
_logger = logger;
}
public void OnGet()
{
}
}
}
반환 형식이 IActionResult 또는 Task<IActionResult>
이면 반환 문을 제공해야 합니다. 예를 들어 메서드는 다음과 같습니다 Pages/Movies/Create.cshtml.cs
OnPostAsync
.
public async Task<IActionResult> OnPostAsync()
{
if (!ModelState.IsValid || _context.Movie == null || Movie == null)
{
return Page();
}
_context.Movie.Add(Movie);
await _context.SaveChangesAsync();
return RedirectToPage("./Index");
}
Pages/Movies/Index.cshtml
Razor페이지를 살펴봅니다.
@page
@model RazorPagesMovie.Pages.Movies.IndexModel
@{
ViewData["Title"] = "Index";
}
<h1>Index</h1>
<p>
<a asp-page="Create">Create New</a>
</p>
<table class="table">
<thead>
<tr>
<th>
@Html.DisplayNameFor(model => model.Movie[0].Title)
</th>
<th>
@Html.DisplayNameFor(model => model.Movie[0].ReleaseDate)
</th>
<th>
@Html.DisplayNameFor(model => model.Movie[0].Genre)
</th>
<th>
@Html.DisplayNameFor(model => model.Movie[0].Price)
</th>
<th></th>
</tr>
</thead>
<tbody>
@foreach (var item in Model.Movie) {
<tr>
<td>
@Html.DisplayFor(modelItem => item.Title)
</td>
<td>
@Html.DisplayFor(modelItem => item.ReleaseDate)
</td>
<td>
@Html.DisplayFor(modelItem => item.Genre)
</td>
<td>
@Html.DisplayFor(modelItem => item.Price)
</td>
<td>
<a asp-page="./Edit" asp-route-id="@item.ID">Edit</a> |
<a asp-page="./Details" asp-route-id="@item.ID">Details</a> |
<a asp-page="./Delete" asp-route-id="@item.ID">Delete</a>
</td>
</tr>
}
</tbody>
</table>
Razor는 HTML에서 C# 또는 Razor 관련 태그로 전환될 수 있습니다. @
기호 뒤에 Razor 예약 키워드가 사용되면 이 기호는 Razor 관련 태그로 전환됩니다. 이외의 경우에는 C#으로 전환됩니다.
@page 지시문
@page
Razor 지시문은 파일을 MVC 작업으로 만듭니다. 이는 요청을 처리할 수 있음을 의미합니다. @page
는 페이지의 첫 번째 Razor 지시문이어야 합니다. @page
및 @model
은 Razor 관련 태그로 전환되는 예입니다. 자세한 내용은 Razor 구문을 참조하세요.
@model 지시문
@page
@model RazorPagesMovie.Pages.Movies.IndexModel
@model
지시문은 Razor Page에 전달되는 모델 형식을 지정합니다. 위의 예제에서 @model
줄은 Razor Page에서 PageModel
파생 클래스를 사용할 수 있게 만듭니다. 모델은 페이지에서 @Html.DisplayNameFor
및 @Html.DisplayFor
HTML 도우미에서 사용됩니다.
다음 HTML 도우미에서 사용되는 람다 식을 살펴봅니다.
@Html.DisplayNameFor(model => model.Movie[0].Title)
DisplayNameFor HTML 도우미는 람다 식에서 참조되는 Title
속성을 검사하여 표시 이름을 확인합니다. 람다 식은 계산되는 것이 아니라 검사됩니다. 즉, model
, model.Movie
또는 model.Movie[0]
가 null
이거나 비어 있을 경우 액세스 위반이 없습니다. 람다 식이 계산될 경우(예: @Html.DisplayFor(modelItem => item.Title)
사용) 모델의 속성 값이 계산됩니다.
레이아웃 페이지
RazorPagesMovieHomePrivacy 및 . 각 페이지는 동일한 메뉴 레이아웃을 표시합니다. 메뉴 레이아웃은 파일에서 Pages/Shared/_Layout.cshtml
구현됩니다.
Pages/Shared/_Layout.cshtml
파일을 열어 검사합니다.
레이아웃 템플릿을 사용하여 HTML 컨테이너 레이아웃을 다음과 같이 지정할 수 있습니다.
- 한 위치에 지정됩니다.
- 사이트의 여러 페이지에 적용됩니다.
@RenderBody()
줄을 찾습니다. RenderBody
는 사용자가 만드는 모든 페이지 특정 보기가 표시되는 자리 표시자이며 레이아웃 페이지에서 래핑됩니다. 예를 들어 링크를 선택하면 Privacy 보기가 Pages/Privacy.cshtml
메서드 내부에 RenderBody
렌더링됩니다.
ViewData 및 레이아웃
파일에서 다음 태그를 고려합니다.Pages/Movies/Index.cshtml
@page
@model RazorPagesMovie.Pages.Movies.IndexModel
@{
ViewData["Title"] = "Index";
}
강조 표시된 이전 태그는 C#으로 전환되는 Razor의 예제입니다. {
및 }
문자로 C# 코드 블록을 묶습니다.
PageModel
기본 클래스에는 데이터를 뷰에 전달하는 데 사용할 수 있는 ViewData
사전 속성이 있습니다. 키 값 패턴을 사용하여 개체가 ViewData
사전에 추가됩니다. 이전 샘플에서는 Title
속성이 ViewData
사전에 추가됩니다.
Title
속성이 Pages/Shared/_Layout.cshtml
파일에서 사용됩니다. 다음 태그는 파일의 처음 몇 줄을 보여 줍니다 _Layout.cshtml
.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>@ViewData["Title"] - RazorPagesMovie</title>
@*Markup removed for brevity.*@
<link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.css" />
@*Markup removed for brevity.*@
줄은 Razor 주석입니다. HTML 주석 <!-- -->
과 달리 Razor 주석은 클라이언트에 전송되지 않습니다. 자세한 내용은 MDN 웹 문서: HTML 시작을 참조하세요.
레이아웃 업데이트
<title>
RazorPagesMovie 대신 Movie를Pages/Shared/_Layout.cshtml
표시하도록 파일의 요소를 변경합니다.<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>@ViewData["Title"] - Movie</title>
파일에서 다음 앵커 요소를 찾습니다
Pages/Shared/_Layout.cshtml
.<a class="navbar-brand" asp-area="" asp-page="/Index">RazorPagesMovie</a>
이전 요소를 다음 태그로 바꿉니다.
<a class="navbar-brand" asp-page="/Movies/Index">RpMovie</a>
이전 앵커 요소는 태그 도우미입니다. 이 경우에는 앵커 태그 도우미입니다.
asp-page="/Movies/Index"
태그 도우미 특성 및 값으로/Movies/Index
Razor 페이지의 링크를 만듭니다.asp-area
특성 값이 비어 있으므로 영역은 링크에서 사용되지 않습니다. 자세한 내용은 영역을 참조하세요.변경 내용을 저장하고 RpMovie 링크를 선택하여 앱을 테스트합니다. 문제가 있는 경우 GitHub에서 _Layout.cshtml 파일을 참조하세요.
Home, RpMovie, 만들기, 편집 및 삭제 링크를 테스트합니다. 각 페이지는 브라우저 탭에서 볼 수 있는 제목을 설정합니다. 페이지에 책갈피를 지정하면 책갈피에 제목이 사용됩니다.
참고 항목
Price
필드에 소수점을 입력하지 못할 수도 있습니다. 소수점으로 쉼표(",")를 사용하는 비영어 로캘 및 비미국 영어 날짜 형식에 대해 jQuery 유효성 검사를 지원하려면 앱을 세계화하는 단계를 수행해야 합니다. 소수점 추가에 대한 지침은 이 GitHub 문제 4076을 참조하세요.
Layout
속성은 Pages/_ViewStart.cshtml
파일에서 설정됩니다.
@{
Layout = "_Layout";
}
위의 태그는 Pages 폴더의 모든 Razor 파일에 대해 레이아웃 파일로 Pages/Shared/_Layout.cshtml
로 설정합니다. 자세한 내용은 레이아웃을 참조하세요.
Create 페이지 모델
페이지 모델을 검사합니다 Pages/Movies/Create.cshtml.cs
.
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using RazorPagesMovie.Models;
namespace RazorPagesMovie.Pages.Movies
{
public class CreateModel : PageModel
{
private readonly RazorPagesMovie.Data.RazorPagesMovieContext _context;
public CreateModel(RazorPagesMovie.Data.RazorPagesMovieContext context)
{
_context = context;
}
public IActionResult OnGet()
{
return Page();
}
[BindProperty]
public Movie Movie { get; set; } = default!;
// To protect from overposting attacks, see https://aka.ms/RazorPagesCRUD
public async Task<IActionResult> OnPostAsync()
{
if (!ModelState.IsValid || _context.Movie == null || Movie == null)
{
return Page();
}
_context.Movie.Add(Movie);
await _context.SaveChangesAsync();
return RedirectToPage("./Index");
}
}
}
OnGet
메서드는 페이지에 필요한 상태를 초기화합니다. 만들기 페이지에는 초기화할 상태가 없습니다. 따라서 Page
가 반환됩니다. 자습서의 뒷부분에서 상태를 초기화하는 OnGet
의 예가 나와 있습니다. 메서드는 Page
페이지를 렌더링하는 개체를 Create.cshtml
만듭니다PageResult
.
Movie
속성은 BindProperty 특성을 사용하여 모델 바인딩을 옵트인합니다. 만들기 폼이 폼 값을 게시하면 ASP.NET Core 런타임이 게시된 값을 Movie
모델에 바인딩합니다.
페이지에 폼 데이터가 게시되면 OnPostAsync
메서드가 실행됩니다.
public async Task<IActionResult> OnPostAsync()
{
if (!ModelState.IsValid || _context.Movie == null || Movie == null)
{
return Page();
}
_context.Movie.Add(Movie);
await _context.SaveChangesAsync();
return RedirectToPage("./Index");
}
모델 오류가 있는 경우 폼과 게시된 모든 폼 데이터가 다시 표시됩니다. 대부분의 모델 오류는 폼이 게시되기 전에 클라이언트 쪽에서 catch할 수 있습니다. 예를 들어 데이터로 변환될 수 없는 날짜 필드에 대한 값을 게시하는 모델 오류가 발생할 수 있습니다. 클라이언트 쪽 유효성 검사 및 모델 유효성 검사는 자습서의 뒷부분에서 설명합니다.
모델 오류가 없는 경우:
- 데이터가 저장됩니다.
- 브라우저가 인덱스 페이지로 리디렉션됩니다.
Create Razor Page
Pages/Movies/Create.cshtml
Razor Page 파일을 살펴봅니다.
@page
@model RazorPagesMovie.Pages.Movies.CreateModel
@{
ViewData["Title"] = "Create";
}
<h1>Create</h1>
<h4>Movie</h4>
<hr />
<div class="row">
<div class="col-md-4">
<form method="post">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="Movie.Title" class="control-label"></label>
<input asp-for="Movie.Title" class="form-control" />
<span asp-validation-for="Movie.Title" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Movie.ReleaseDate" class="control-label"></label>
<input asp-for="Movie.ReleaseDate" class="form-control" />
<span asp-validation-for="Movie.ReleaseDate" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Movie.Genre" class="control-label"></label>
<input asp-for="Movie.Genre" class="form-control" />
<span asp-validation-for="Movie.Genre" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Movie.Price" class="control-label"></label>
<input asp-for="Movie.Price" class="form-control" />
<span asp-validation-for="Movie.Price" class="text-danger"></span>
</div>
<div class="form-group">
<input type="submit" value="Create" class="btn btn-primary" />
</div>
</form>
</div>
</div>
<div>
<a asp-page="Index">Back to List</a>
</div>
@section Scripts {
@{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}
Visual Studio에서는 다음 태그를 태그 도우미에 사용되는 독특한 굵은 글꼴로 표시합니다.
<form method="post">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<label asp-for="Movie.Title" class="control-label"></label>
<input asp-for="Movie.Title" class="form-control" />
<span asp-validation-for="Movie.Title" class="text-danger"></span>
<form method="post">
요소는 폼 태그 도우미입니다. 폼 태그 도우미에는 위조 방지 토큰이 자동으로 포함됩니다.
스캐폴딩 엔진은 ID를 제외하고 다음과 비슷한 모델에서 필드마다 Razor 태그를 만듭니다.
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="Movie.Title" class="control-label"></label>
<input asp-for="Movie.Title" class="form-control" />
<span asp-validation-for="Movie.Title" class="text-danger"></span>
</div>
유효성 검사 태그 도우미 (<div asp-validation-summary
및 <span asp-validation-for
) 는 유효성 검사 오류를 표시합니다. 유효성 검사는 이 시리즈의 뒷부분에서 자세히 설명합니다.
레이블 태그 도우미(<label asp-for="Movie.Title" class="control-label"></label>
)는 Title
속성에 대한 레이블 캡션 및 [for]
특성을 생성합니다.
입력 태그 도우미(<input asp-for="Movie.Title" class="form-control">
)는 DataAnnotations 특성을 사용하고 클라이언트 쪽의 jQuery 유효성 검사에 필요한 HTML 특성을 생성합니다.
태그 도우미(예: <form method="post">
)에 대한 자세한 내용은 ASP.NET Core의 태그 도우미를 참조하세요.
다음 단계
만들기, 삭제, 세부 정보 및 편집 페이지
Pages/Movies/Index.cshtml.cs
페이지 모델을 살펴봅니다.
// Unused usings removed.
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.EntityFrameworkCore;
using RazorPagesMovie.Models;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace RazorPagesMovie.Pages.Movies
{
public class IndexModel : PageModel
{
private readonly RazorPagesMovie.Data.RazorPagesMovieContext _context;
public IndexModel(RazorPagesMovie.Data.RazorPagesMovieContext context)
{
_context = context;
}
public IList<Movie> Movie { get;set; }
public async Task OnGetAsync()
{
Movie = await _context.Movie.ToListAsync();
}
}
}
Razor Pages는 PageModel
에서 파생됩니다. 일반적으로 PageModel
파생 클래스의 이름은 <PageName>Model
로 지정됩니다. 생성자는 종속성 주입을 사용하여 RazorPagesMovieContext
를 페이지에 추가합니다.
public class IndexModel : PageModel
{
private readonly RazorPagesMovie.Data.RazorPagesMovieContext _context;
public IndexModel(RazorPagesMovie.Data.RazorPagesMovieContext context)
{
_context = context;
}
Entity Framework로 비동기 프로그래밍에 대한 자세한 내용은 비동기 코드를 참조하세요.
페이지에 대한 요청을 만들면 OnGetAsync
메서드가 Razor Page에 동영상 목록을 반환합니다. Razor 페이지에서 OnGetAsync
또는 OnGet
을 호출하여 페이지 상태를 초기화합니다. 이 경우 OnGetAsync
는 동영상 목록을 가져와 표시합니다.
OnGet
이 void
를 반환하거나 OnGetAsync
가 Task
를 반환하면 return 문이 사용되지 않은 것입니다. 예를 들어 Privacy 페이지는:
public class PrivacyModel : PageModel
{
private readonly ILogger<PrivacyModel> _logger;
public PrivacyModel(ILogger<PrivacyModel> logger)
{
_logger = logger;
}
public void OnGet()
{
}
}
반환 형식이 IActionResult
또는 Task<IActionResult>
이면 반환 문을 제공해야 합니다. 예를 들어 메서드는 다음과 같습니다 Pages/Movies/Create.cshtml.cs
OnPostAsync
.
public async Task<IActionResult> OnPostAsync()
{
if (!ModelState.IsValid)
{
return Page();
}
_context.Movie.Add(Movie);
await _context.SaveChangesAsync();
return RedirectToPage("./Index");
}
}
Pages/Movies/Index.cshtml
Razor페이지를 살펴봅니다.
@page
@model RazorPagesMovie.Pages.Movies.IndexModel
@{
ViewData["Title"] = "Index";
}
<h1>Index</h1>
<p>
<a asp-page="Create">Create New</a>
</p>
<table class="table">
<thead>
<tr>
<th>
@Html.DisplayNameFor(model => model.Movie[0].Title)
</th>
<th>
@Html.DisplayNameFor(model => model.Movie[0].ReleaseDate)
</th>
<th>
@Html.DisplayNameFor(model => model.Movie[0].Genre)
</th>
<th>
@Html.DisplayNameFor(model => model.Movie[0].Price)
</th>
<th></th>
</tr>
</thead>
<tbody>
@foreach (var item in Model.Movie) {
<tr>
<td>
@Html.DisplayFor(modelItem => item.Title)
</td>
<td>
@Html.DisplayFor(modelItem => item.ReleaseDate)
</td>
<td>
@Html.DisplayFor(modelItem => item.Genre)
</td>
<td>
@Html.DisplayFor(modelItem => item.Price)
</td>
<td>
<a asp-page="./Edit" asp-route-id="@item.ID">Edit</a> |
<a asp-page="./Details" asp-route-id="@item.ID">Details</a> |
<a asp-page="./Delete" asp-route-id="@item.ID">Delete</a>
</td>
</tr>
}
</tbody>
</table>
Razor는 HTML에서 C# 또는 Razor 관련 태그로 전환될 수 있습니다. @
기호 뒤에 Razor 예약 키워드가 사용되면 이 기호는 Razor 관련 태그로 전환됩니다. 이외의 경우에는 C#으로 전환됩니다.
@page 지시문
@page
Razor 지시문은 파일을 MVC 작업으로 만듭니다. 이는 요청을 처리할 수 있음을 의미합니다. @page
는 페이지의 첫 번째 Razor 지시문이어야 합니다. @page
및 @model
은 Razor 관련 태그로 전환되는 예입니다. 자세한 내용은 Razor 구문을 참조하세요.
@model 지시문
@page
@model RazorPagesMovie.Pages.Movies.IndexModel
@model
지시문은 Razor Page에 전달되는 모델 형식을 지정합니다. 위의 예제에서 @model
줄은 Razor Page에서 PageModel
파생 클래스를 사용할 수 있게 만듭니다. 모델은 페이지에서 @Html.DisplayNameFor
및 @Html.DisplayFor
HTML 도우미에서 사용됩니다.
다음 HTML 도우미에서 사용되는 람다 식을 살펴봅니다.
@Html.DisplayNameFor(model => model.Movie[0].Title)
DisplayNameFor HTML 도우미는 람다 식에서 참조되는 Title
속성을 검사하여 표시 이름을 확인합니다. 람다 식은 계산되는 것이 아니라 검사됩니다. 즉, model
, model.Movie
또는 model.Movie[0]
가 null
이거나 비어 있을 경우 액세스 위반이 없습니다. 람다 식이 계산될 경우(예: @Html.DisplayFor(modelItem => item.Title)
사용) 모델의 속성 값이 계산됩니다.
레이아웃 페이지
RazorPagesMovieHomePrivacy 및 . 각 페이지는 동일한 메뉴 레이아웃을 표시합니다. 메뉴 레이아웃은 파일에서 Pages/Shared/_Layout.cshtml
구현됩니다.
Pages/Shared/_Layout.cshtml
파일을 열어 검사합니다.
레이아웃 템플릿을 사용하여 HTML 컨테이너 레이아웃을 다음과 같이 지정할 수 있습니다.
- 한 위치에 지정됩니다.
- 사이트의 여러 페이지에 적용됩니다.
@RenderBody()
줄을 찾습니다. RenderBody
는 사용자가 만드는 모든 페이지 특정 보기가 표시되는 자리 표시자이며 레이아웃 페이지에서 래핑됩니다. 예를 들어 링크를 선택하면 Privacy 보기가 Pages/Privacy.cshtml
메서드 내부에 RenderBody
렌더링됩니다.
ViewData 및 레이아웃
파일에서 다음 태그를 고려합니다.Pages/Movies/Index.cshtml
@page
@model RazorPagesMovie.Pages.Movies.IndexModel
@{
ViewData["Title"] = "Index";
}
강조 표시된 이전 태그는 C#으로 전환되는 Razor의 예제입니다. {
및 }
문자로 C# 코드 블록을 묶습니다.
PageModel
기본 클래스에는 데이터를 뷰에 전달하는 데 사용할 수 있는 ViewData
사전 속성이 있습니다. 키 값 패턴을 사용하여 개체가 ViewData
사전에 추가됩니다. 이전 샘플에서는 Title
속성이 ViewData
사전에 추가됩니다.
Title
속성이 Pages/Shared/_Layout.cshtml
파일에서 사용됩니다. 다음 태그는 파일의 처음 몇 줄을 보여 줍니다 _Layout.cshtml
.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>@ViewData["Title"] - RazorPagesMovie</title>
@*Markup removed for brevity.*@
@*Markup removed for brevity.*@
줄은 Razor 주석입니다. HTML 주석 <!-- -->
과 달리 Razor 주석은 클라이언트에 전송되지 않습니다. 자세한 내용은 MDN 웹 문서: HTML 시작을 참조하세요.
레이아웃 업데이트
<title>
RazorPagesMovie 대신 Movie를Pages/Shared/_Layout.cshtml
표시하도록 파일의 요소를 변경합니다.<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>@ViewData["Title"] - Movie</title>
파일에서 다음 앵커 요소를 찾습니다
Pages/Shared/_Layout.cshtml
.<a class="navbar-brand" asp-area="" asp-page="/Index">RazorPagesMovie</a>
이전 요소를 다음 태그로 바꿉니다.
<a class="navbar-brand" asp-page="/Movies/Index">RpMovie</a>
이전 앵커 요소는 태그 도우미입니다. 이 경우에는 앵커 태그 도우미입니다.
asp-page="/Movies/Index"
태그 도우미 특성 및 값으로/Movies/Index
Razor 페이지의 링크를 만듭니다.asp-area
특성 값이 비어 있으므로 영역은 링크에서 사용되지 않습니다. 자세한 내용은 영역을 참조하세요.변경 내용을 저장하고 RpMovie 링크를 선택하여 앱을 테스트합니다. 문제가 있는 경우 GitHub에서 _Layout.cshtml 파일을 참조하세요.
Home, RpMovie, 만들기, 편집 및 삭제 링크를 테스트합니다. 각 페이지는 브라우저 탭에서 볼 수 있는 제목을 설정합니다. 페이지에 책갈피를 지정하면 책갈피에 제목이 사용됩니다.
참고 항목
Price
필드에 소수점을 입력하지 못할 수도 있습니다. 소수점으로 쉼표(",")를 사용하는 비영어 로캘 및 비미국 영어 날짜 형식에 대해 jQuery 유효성 검사를 지원하려면 앱을 세계화하는 단계를 수행해야 합니다. 소수점 추가에 대한 지침은 이 GitHub 문제 4076을 참조하세요.
Layout
속성은 Pages/_ViewStart.cshtml
파일에서 설정됩니다.
@{
Layout = "_Layout";
}
위의 태그는 Pages 폴더의 모든 Razor 파일에 대해 레이아웃 파일로 Pages/Shared/_Layout.cshtml
로 설정합니다. 자세한 내용은 레이아웃을 참조하세요.
Create 페이지 모델
페이지 모델을 검사합니다 Pages/Movies/Create.cshtml.cs
.
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using RazorPagesMovie.Models;
using System;
using System.Threading.Tasks;
namespace RazorPagesMovie.Pages.Movies
{
public class CreateModel : PageModel
{
private readonly RazorPagesMovie.Data.RazorPagesMovieContext _context;
public CreateModel(RazorPagesMovie.Data.RazorPagesMovieContext context)
{
_context = context;
}
public IActionResult OnGet()
{
return Page();
}
[BindProperty]
public Movie Movie { get; set; }
public async Task<IActionResult> OnPostAsync()
{
if (!ModelState.IsValid)
{
return Page();
}
_context.Movie.Add(Movie);
await _context.SaveChangesAsync();
return RedirectToPage("./Index");
}
}
}
OnGet
메서드는 페이지에 필요한 상태를 초기화합니다. 만들기 페이지에는 초기화할 상태가 없습니다. 따라서 Page
가 반환됩니다. 자습서의 뒷부분에서 상태를 초기화하는 OnGet
의 예가 나와 있습니다. 메서드는 Page
페이지를 렌더링하는 개체를 Create.cshtml
만듭니다PageResult
.
Movie
속성은 BindProperty 특성을 사용하여 모델 바인딩을 옵트인합니다. 만들기 폼이 폼 값을 게시하면 ASP.NET Core 런타임이 게시된 값을 Movie
모델에 바인딩합니다.
페이지에 폼 데이터가 게시되면 OnPostAsync
메서드가 실행됩니다.
public async Task<IActionResult> OnPostAsync()
{
if (!ModelState.IsValid)
{
return Page();
}
_context.Movie.Add(Movie);
await _context.SaveChangesAsync();
return RedirectToPage("./Index");
}
모델 오류가 있는 경우 폼과 게시된 모든 폼 데이터가 다시 표시됩니다. 대부분의 모델 오류는 폼이 게시되기 전에 클라이언트 쪽에서 catch할 수 있습니다. 예를 들어 데이터로 변환될 수 없는 날짜 필드에 대한 값을 게시하는 모델 오류가 발생할 수 있습니다. 클라이언트 쪽 유효성 검사 및 모델 유효성 검사는 자습서의 뒷부분에서 설명합니다.
모델 오류가 없는 경우:
- 데이터가 저장됩니다.
- 브라우저가 인덱스 페이지로 리디렉션됩니다.
Create Razor Page
Pages/Movies/Create.cshtml
Razor Page 파일을 살펴봅니다.
@page
@model RazorPagesMovie.Pages.Movies.CreateModel
@{
ViewData["Title"] = "Create";
}
<h1>Create</h1>
<h4>Movie</h4>
<hr />
<div class="row">
<div class="col-md-4">
<form method="post">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="Movie.Title" class="control-label"></label>
<input asp-for="Movie.Title" class="form-control" />
<span asp-validation-for="Movie.Title" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Movie.ReleaseDate" class="control-label"></label>
<input asp-for="Movie.ReleaseDate" class="form-control" />
<span asp-validation-for="Movie.ReleaseDate" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Movie.Genre" class="control-label"></label>
<input asp-for="Movie.Genre" class="form-control" />
<span asp-validation-for="Movie.Genre" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Movie.Price" class="control-label"></label>
<input asp-for="Movie.Price" class="form-control" />
<span asp-validation-for="Movie.Price" class="text-danger"></span>
</div>
<div class="form-group">
<input type="submit" value="Create" class="btn btn-primary" />
</div>
</form>
</div>
</div>
<div>
<a asp-page="Index">Back to List</a>
</div>
@section Scripts {
@{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}
Visual Studio에서는 다음 태그를 태그 도우미에 사용되는 독특한 굵은 글꼴로 표시합니다.
<form method="post">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<label asp-for="Movie.Title" class="control-label"></label>
<input asp-for="Movie.Title" class="form-control" />
<span asp-validation-for="Movie.Title" class="text-danger"></span>
<form method="post">
요소는 폼 태그 도우미입니다. 폼 태그 도우미에는 위조 방지 토큰이 자동으로 포함됩니다.
스캐폴딩 엔진은 ID를 제외하고 다음과 비슷한 모델에서 필드마다 Razor 태그를 만듭니다.
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="Movie.Title" class="control-label"></label>
<input asp-for="Movie.Title" class="form-control" />
<span asp-validation-for="Movie.Title" class="text-danger"></span>
</div>
유효성 검사 태그 도우미 (<div asp-validation-summary
및 <span asp-validation-for
) 는 유효성 검사 오류를 표시합니다. 유효성 검사는 이 시리즈의 뒷부분에서 자세히 설명합니다.
레이블 태그 도우미(<label asp-for="Movie.Title" class="control-label"></label>
)는 Title
속성에 대한 레이블 캡션 및 [for]
특성을 생성합니다.
입력 태그 도우미(<input asp-for="Movie.Title" class="form-control">
)는 DataAnnotations 특성을 사용하고 클라이언트 쪽의 jQuery 유효성 검사에 필요한 HTML 특성을 생성합니다.
태그 도우미(예: <form method="post">
)에 대한 자세한 내용은 ASP.NET Core의 태그 도우미를 참조하세요.
다음 단계
ASP.NET Core