연습 - 새 Razor 페이지 추가

완료됨

이전 단원에서는 Contoso Pizza 프로젝트의 소스 코드를 가져온 다음, 홈페이지를 간단하게 변경했습니다. 이 단원에서는 프로젝트에 새 Razor 페이지를 추가합니다.

피자 목록 페이지 만들기

새 Razor 페이지를 만들려면 .NET CLI를 사용합니다.

  1. 터미널이 dotnet watch 명령에 의해 차단되었으므로 Explorer에서 ContosoPizza 폴더를 마우스 오른쪽 단추로 클릭하여 다른 터미널을 열고 통합 터미널에서 열기를 선택합니다.

  2. 새 터미널 창에서 다음 명령을 입력합니다.

    dotnet new page --name PizzaList --namespace ContosoPizza.Pages --output Pages
    

    이전 명령:

    • ContosoPizza.Pages 네임스페이스에 다음 두 파일을 만듭니다.
      • PizzaList.cshtml - Razor 페이지
      • PizzaList.cshtml.cs - 관련 PageModel 클래스
    • 프로젝트의 Pages 하위 디렉터리에 두 파일을 저장합니다.
  3. Pages/PizzaList.cshtml에서 @{ } 코드 블록 내에 다음 코드를 추가합니다.

    ViewData["Title"] = "Pizza List 🍕";
    

    그러면 페이지의 <title> 요소가 설정됩니다.

  4. 파일의 끝에 다음 코드를 추가합니다.

    <h1>Pizza List 🍕</h1>
    
    <!-- New Pizza form will go here -->
    
    <!-- List of pizzas will go here -->
    

    그러면 페이지에 제목과 나중에 추가할 기능에 대한 두 개의 HTML 주석 자리 표시자가 추가됩니다.

  5. 파일을 저장합니다. GitHub Codespaces를 사용하는 경우 파일이 자동으로 저장됩니다.

  6. 실행 중인 dotnet watch 터미널로 돌아가 Ctrl+R을 눌러 앱을 다시 로드하고 새 파일을 검색합니다.

탐색 메뉴에 피자 목록 페이지 추가

이것은 페이지를 테스트하기에 좋은 기회이지만, 페이지가 탐색 메뉴에서 아직 연결되지 않았기 때문에 브라우저에서 페이지에 연결할 수 없습니다. 이제 연결하겠습니다.

  1. Pages/Shared/_Layout.cshtml을 엽니다.

  2. navbar-nav 클래스가 있는 <ul> 요소(줄 21에서 시작)에서 홈 및 개인 정보 페이지에 대한 링크가 포함된 <li> 요소를 적어 둡니다. 개인 정보 링크가 포함된 <li> 요소 다음에 다음 코드를 목록 끝에 추가합니다.

    <li class="nav-item">
        <a class="nav-link text-dark" asp-area="" asp-page="/PizzaList">Pizza List 🍕</a>
    </li>
    

    그러면 PizzaList 페이지에 대한 링크가 탐색 메뉴에 추가됩니다.

  3. 파일을 저장합니다. 앱이 있는 브라우저 탭이 자동으로 새로 고침되어 변경 내용을 표시합니다. GitHub Codespaces를 사용하는 경우 파일이 자동으로 저장되지만 브라우저 탭을 수동으로 새로 고쳐야 합니다.

  4. 탐색 메뉴에서 피자 목록 🍕 링크를 선택합니다. 피자 목록 페이지가 나타납니다.

종속성 주입 컨테이너에 PizzaService 클래스 등록

피자 목록 페이지는 피자 목록을 검색하는 PizzaService 개체에 따라 달라집니다. 종속성 주입을 사용하여 PizzaService 개체를 페이지에 제공합니다. 먼저 PizzaService 클래스를 컨테이너에 등록합니다.

  1. Program.cs를 엽니다.

  2. 컨테이너에 서비스를 추가하는 섹션에서 다음 코드를 추가합니다.

    builder.Services.AddScoped<PizzaService>();
    

    이 코드는 종속성 주입 컨테이너에 PizzaService 클래스를 등록합니다. AddScoped 메서드는 각 HTTP 요청에 대해 새 PizzaService 개체를 만들어야 했음을 나타냅니다. 이제 PizzaService는 모든 Razor 페이지에 삽입할 수 있습니다.

  3. 파일을 저장합니다. GitHub Codespaces를 사용하는 경우 파일이 자동으로 저장됩니다.

피자 목록 표시

피자 목록 페이지의 PageModel 클래스를 수정하여 PizzaService 개체에서 피자 목록을 검색하고 속성에 저장해 보겠습니다.

  1. Pages/PizzaList.cshtml.cs를 엽니다.

  2. 파일 맨 위에 다음 using 문을 추가합니다.

    using ContosoPizza.Models;
    using ContosoPizza.Services;
    

    이러한 문은 페이지에서 사용할 PizzaPizzaService 형식을 가져옵니다.

  3. ContosoPizza.Pages 네임스페이스 블록 내에서 전체 PizzaListModel 클래스를 다음 코드로 바꿉니다.

    public class PizzaListModel : PageModel
    {
        private readonly PizzaService _service;
        public IList<Pizza> PizzaList { get;set; } = default!;
    
        public PizzaListModel(PizzaService service)
        {
            _service = service;
        }
    
        public void OnGet()
        {
            PizzaList = _service.GetPizzas();
        }
    }
    

    위의 코드에서

    • _service라는 프라이빗 읽기 전용 PizzaService가 만들어집니다. 이 변수는 PizzaService 개체에 대한 참조를 보유합니다.
      • readonly 키워드 생성자에서 변수가 설정된 후에는 _service 변수 값을 변경할 수 없음을 나타냅니다.
    • PizzaList 속성은 피자 목록을 보관하도록 정의됩니다.
      • IList<Pizza> 형식은 PizzaList 속성에 Pizza 개체 목록이 있음을 나타냅니다.
      • PizzaList는 컴파일러에 나중에 초기화될 것임을 나타내기 위해 default!로 초기화되므로 null 안전 검사가 필요하지 않습니다.
    • 생성자는 PizzaService 개체를 허용합니다.
      • PizzaService 개체는 종속성 주입을 통해 제공됩니다.
    • OnGet 메서드는 PizzaService 개체에서 피자 목록을 검색하여 PizzaList 속성에 저장하도록 정의됩니다.

    null 안전성을 이해하는 데 도움이 필요한 경우 C#의 Null 안전성을 참조하세요.

  4. 파일을 저장합니다. GitHub Codespaces를 사용하는 경우 파일이 자동으로 저장됩니다.

  5. 실행 중인 dotnet watch 터미널로 돌아가서 Ctrl+R을 눌러 등록된 서비스와 PizzaListModel에 대한 새 생성자를 사용하여 앱을 다시 로드합니다.

피자 목록 표시

이제 페이지에서 피자 목록에 액세스할 수 있으므로 해당 목록을 사용하여 페이지에 피자를 표시합니다.

  1. Pages/PizzaList.cshtml을 엽니다.

  2. <!-- List of pizzas will go here --> 주석을 다음 코드로 바꿉니다.

    <table class="table mt-5">
        <thead>
            <tr>
                <th scope="col">Name</th>
                <th scope="col">Price</th>
                <th scope="col">Size</th>
                <th scope="col">Gluten Free</th>
                <th scope="col">Delete</th>
            </tr>
        </thead>
        <tbody>
        @foreach (var pizza in Model.PizzaList)
        {
            <tr>
                <td>@pizza.Name</td>
                <td>@($"{pizza.Price:C}")</td>
                <td>@pizza.Size</td>
                <td>@(pizza.IsGlutenFree ? "✔️" : string.Empty)</td>
                <td>
                    <form method="post" asp-page-handler="Delete" asp-route-id="@pizza.Id">
                        <button class="btn btn-danger">Delete</button>
                    </form>
                </td>
            </tr>
        }
        </tbody>
    </table>
    

    위의 코드에서

    • 피자 목록을 표시하는 <table> 요소가 만들어집니다.
    • 테이블 헤더를 저장할 <thead> 요소가 만들어집니다.
    • <tbody> 내부의 @foreach 문은 피자 목록을 반복합니다.
      • Model 속성은 코드 숨김 파일에서 만든 PizzaListModel 개체를 참조합니다.
      • PizzaList 속성은 코드 숨김 파일에서 정의된 PizzaList 속성을 참조합니다.
    • @foreach 문의 각 반복은 피자 데이터를 저장할 <tr> 요소를 만듭니다.
      • Razor 구문은 <td> 요소에 피자 데이터를 표시하는 데 사용됩니다. 이 구문은 pizza 변수에 저장된 Pizza 개체의 속성을 표시하는 데 사용됩니다.
      • Price는 C# 문자열 보간을 사용하여 형식이 지정됩니다.
      • 3항 식은 IsGlutenFree 속성 값을 “✔️” 또는 빈 셀로 표시하는 데 사용됩니다.
      • 피자를 삭제하는 양식이 만들어집니다.
        • asp-page-handler 특성은 양식을 코드 숨김 파일의 Delete 처리기로 제출해야 함을 나타냅니다. 이후 단원에서 해당 처리기를 만듭니다.
        • asp-route-id 특성은 Pizza 개체의 Id 속성을 Delete 처리기에 전달해야 했음을 나타냅니다.
  3. 파일을 저장합니다. 브라우저에서 피자 목록 페이지가 피자 목록과 함께 새로 고쳐집니다. GitHub Codespaces를 사용하는 경우 파일이 자동으로 저장되지만 브라우저 탭을 수동으로 새로 고쳐야 합니다.

작업 목록이 있는 피자 목록 페이지 스크린샷

잘했습니다! 피자 목록을 표시하는 Razor 페이지를 만들었습니다. 다음 단원에서는 태그 도우미 및 페이지 처리기에 대해 알아봅니다.