[C#/ASP.NET MVC/.NETCORE] RAZOR 구문에서 주석 사용하기
■ RAZOR 구문에서 주석을 사용하는 방법을 보여준다. ▶ 예제 코드 (CSHTML)
1 2 3 |
@* 주석 *@ |
■ RAZOR 구문에서 주석을 사용하는 방법을 보여준다. ▶ 예제 코드 (CSHTML)
1 2 3 |
@* 주석 *@ |
■ 서버 재시작 없이 .cshtml 파일의 변경 사항을 반영하는 방법을 보여준다. 1. 아래 누겟 패키지를 설치한다. ▶ 설치 누겟 패키지
1 2 3 |
Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation |
2.
■ Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation 누겟을 설치하는 방법을 보여준다. 1. Visual Studio를 실행한다. 2. [도구] / [NuGet 패키지 관리자] / [패키지 관리자 콘솔] 메뉴를 실행한다.
■ @page 지시문을 사용해 경로 템플리트를 추가하는 방법을 보여준다. ▶ Pages/Movies/Index.cshtml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 |
@page "{SearchString?}" @using TestProject.Models @model TestProject.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.MovieList[0].Title) </th> <th> @Html.DisplayNameFor(model => model.MovieList[0].ReleaseDate) </th> <th> @Html.DisplayNameFor(model => model.MovieList[0].Genre) </th> <th> @Html.DisplayNameFor(model => model.MovieList[0].Price) </th> <th></th> </tr> </thead> <tbody> @foreach(Movie movie in Model.MovieList) { <tr> <td> @Html.DisplayFor(modelItem => movie.Title) </td> <td> @Html.DisplayFor(modelItem => movie.ReleaseDate) </td> <td> @Html.DisplayFor(modelItem => movie.Genre) </td> <td> @Html.DisplayFor(modelItem => movie.Price) </td> <td> <a asp-page="./Edit" asp-route-id="@movie.ID">Edit</a> | <a asp-page="./Details" asp-route-id="@movie.ID">Details</a> | <a asp-page="./Delete" asp-route-id="@movie.ID">Delete</a> </td> </tr> } </tbody> </table> |
▶ Pages/Movies/Index.cshtml.cs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 |
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.RazorPages; using Microsoft.AspNetCore.Mvc.Rendering; using Microsoft.EntityFrameworkCore; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using TestProject.Data; using TestProject.Models; namespace TestProject.Pages.Movies { /// <summary> /// 인덱스 모델 /// </summary> public class IndexModel : PageModel { //////////////////////////////////////////////////////////////////////////////////////////////////// Field ////////////////////////////////////////////////////////////////////////////////////////// Private #region Field /// <summary> /// 컨텍스트 /// </summary> private readonly DatabaseContext context; #endregion //////////////////////////////////////////////////////////////////////////////////////////////////// Property ////////////////////////////////////////////////////////////////////////////////////////// Public #region 영화 리스트 - MovieList /// <summary> /// 영화 리스트 /// </summary> public IList<Movie> MovieList { get;set; } #endregion #region 검색 문자열 - SearchString /// <summary> /// 검색 문자열 /// </summary> [BindProperty(SupportsGet = true)] public string SearchString { get; set; } #endregion //////////////////////////////////////////////////////////////////////////////////////////////////// Constructor ////////////////////////////////////////////////////////////////////////////////////////// Public #region 생성자 - IndexModel(context) /// <summary> /// 생성자 /// </summary> /// <param name="context">컨텍스트</param> public IndexModel(DatabaseContext context) { this.context = context; } #endregion //////////////////////////////////////////////////////////////////////////////////////////////////// Method ////////////////////////////////////////////////////////////////////////////////////////// Public #region GET 비동기 처리하기 - OnGetAsync() /// <summary> /// GET 비동기 처리하기 /// </summary> /// <returns>태스크</returns> public async Task OnGetAsync() { var movieQueryable = from movie in this.context.Movie select movie; if(!string.IsNullOrEmpty(SearchString)) { movieQueryable = movieQueryable.Where(s => s.Title.Contains(SearchString)); } MovieList = await movieQueryable.ToListAsync(); } #endregion } } |
※ TestDB 데이터베이스 생성 1. 비주얼 스튜디오를
■ @page 지시문을 사용해 경로 템플리트를 추가하는 방법을 보여준다. ▶ Pages/Movies/Edit.cshtml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
@page "{id:int}" @model TestProject.Pages.Movies.EditModel @{ ViewData["Title"] = "Edit"; } <h1>Edit</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> <input type="hidden" asp-for="Movie.ID" /> <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="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");} } |
▶ Pages/Movies/Edit.cshtml.cs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 |
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.RazorPages; using Microsoft.EntityFrameworkCore; using System.Linq; using System.Threading.Tasks; using TestProject.Data; using TestProject.Models; namespace TestProject.Pages.Movies { /// <summary> /// 편집 모델 /// </summary> public class EditModel : PageModel { //////////////////////////////////////////////////////////////////////////////////////////////////// Field ////////////////////////////////////////////////////////////////////////////////////////// Private #region Field /// <summary> /// 컨텍스트 /// </summary> private readonly DatabaseContext context; #endregion //////////////////////////////////////////////////////////////////////////////////////////////////// Property ////////////////////////////////////////////////////////////////////////////////////////// Public #region 영화 - Movie /// <summary> /// 영화 /// </summary> [BindProperty] public Movie Movie { get; set; } #endregion //////////////////////////////////////////////////////////////////////////////////////////////////// Constructor ////////////////////////////////////////////////////////////////////////////////////////// Public #region 생성자 - EditModel(context) /// <summary> /// 생성자 /// </summary> /// <param name="context">컨텍스트</param> public EditModel(DatabaseContext context) { this.context = context; } #endregion //////////////////////////////////////////////////////////////////////////////////////////////////// Method ////////////////////////////////////////////////////////////////////////////////////////// Public #region GET 비동기 처리하기 - OnGetAsync(id) /// <summary> /// GET 비동기 처리하기 /// </summary> /// <param name="id">ID</param> /// <returns>액션 결과 태스크</returns> public async Task<IActionResult> OnGetAsync(int id) { Movie = await this.context.Movie.FirstOrDefaultAsync(m => m.ID == id); if(Movie == null) { return NotFound(); } return Page(); } #endregion #region POST 비동기 처리하기 - OnPostAsync() /// <summary> /// POST 비동기 처리하기 /// </summary> /// <returns>액션 결과 태스크</returns> public async Task<IActionResult> OnPostAsync() { if(!ModelState.IsValid) { return Page(); } this.context.Attach(Movie).State = EntityState.Modified; try { await this.context.SaveChangesAsync(); } catch(DbUpdateConcurrencyException) { if(!MovieExists(Movie.ID)) { return NotFound(); } else { throw; } } return RedirectToPage("./Index"); } #endregion ////////////////////////////////////////////////////////////////////////////////////////// Private #region 영화 존재 여부 구하기 - MovieExists(id) /// <summary> /// 영화 존재 여부 구하기 /// </summary> /// <param name="id">ID</param> /// <returns>영화 존재 여부</returns> private bool MovieExists(int id) { return this.context.Movie.Any(e => e.ID == id); } #endregion } } |
▶ Pages/Movies/Delete.cshtml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 |
@page "{id:int}" @model TestProject.Pages.Movies.DeleteModel @{ ViewData["Title"] = "Delete"; } <h1>Delete</h1> <h3>Are you sure you want to delete this?</h3> <div> <h4>Movie</h4> <hr /> <dl class="row"> <dt class="col-sm-2"> @Html.DisplayNameFor(model => model.Movie.Title) </dt> <dd class="col-sm-10"> @Html.DisplayFor(model => model.Movie.Title) </dd> <dt class="col-sm-2"> @Html.DisplayNameFor(model => model.Movie.ReleaseDate) </dt> <dd class="col-sm-10"> @Html.DisplayFor(model => model.Movie.ReleaseDate) </dd> <dt class="col-sm-2"> @Html.DisplayNameFor(model => model.Movie.Genre) </dt> <dd class="col-sm-10"> @Html.DisplayFor(model => model.Movie.Genre) </dd> <dt class="col-sm-2"> @Html.DisplayNameFor(model => model.Movie.Price) </dt> <dd class="col-sm-10"> @Html.DisplayFor(model => model.Movie.Price) </dd> </dl> <form method="post"> <input type="hidden" asp-for="Movie.ID" /> <input type="submit" value="Delete" class="btn btn-danger" /> | <a asp-page="./Index">Back to List</a> </form> </div> |
▶ Pages/Movies/Delete.cshtml.cs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 |
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.RazorPages; using Microsoft.EntityFrameworkCore; using System.Threading.Tasks; using TestProject.Data; using TestProject.Models; namespace TestProject.Pages.Movies { /// <summary> /// 삭제 모델 /// </summary> public class DeleteModel : PageModel { //////////////////////////////////////////////////////////////////////////////////////////////////// Field ////////////////////////////////////////////////////////////////////////////////////////// Private #region Field /// <summary> /// 컨텍스트 /// </summary> private readonly DatabaseContext context; #endregion //////////////////////////////////////////////////////////////////////////////////////////////////// Property ////////////////////////////////////////////////////////////////////////////////////////// Public #region 영화 - Movie /// <summary> /// 영화 /// </summary> [BindProperty] public Movie Movie { get; set; } #endregion //////////////////////////////////////////////////////////////////////////////////////////////////// Constructor ////////////////////////////////////////////////////////////////////////////////////////// Public #region 생성자 - DeleteModel(context) /// <summary> /// 생성자 /// </summary> /// <param name="context">컨텍스트</param> public DeleteModel(DatabaseContext context) { this.context = context; } #endregion //////////////////////////////////////////////////////////////////////////////////////////////////// Method ////////////////////////////////////////////////////////////////////////////////////////// Public #region GET 비동기 처리하기 - OnGetAsync(id) /// <summary> /// GET 비동기 처리하기 /// </summary> /// <param name="id">ID</param> /// <returns>액션 결과 태스크</returns> public async Task<IActionResult> OnGetAsync(int id) { Movie = await this.context.Movie.FirstOrDefaultAsync(m => m.ID == id); if(Movie == null) { return NotFound(); } return Page(); } #endregion #region POST 비동기 처리하기 - OnPostAsync(id) /// <summary> /// POST 비동기 처리하기 /// </summary> /// <param name="id">ID</param> /// <returns>액션 결과 태스크</returns> public async Task<IActionResult> OnPostAsync(int id) { Movie = await this.context.Movie.FindAsync(id); if(Movie != null) { this.context.Movie.Remove(Movie); await this.context.SaveChangesAsync(); } return RedirectToPage("./Index"); } #endregion } } |
▶
■ @model 지시문을 사용하는 방법을 보여준다. @model 지시문은 RAZOR 페이지에 전달되는 모델 형식을 지정한다. @model 지시문은 아래의 예제와 같이 RAZOR 페이지에서 PageModel
■ @page 지시문을 사용하는 방법을 보여준다. 파일을 MVC 작업으로 만든다. – 이것은 요청을 처리할 수 있음을 의미한다. @page 지시문은 페이지의 첫 번째
■ RAZOR 구문에서 @: 지시문을 사용해 문자열을 출력하는 방법을 보여준다. ▶ Views/Home/Test.cshtml
1 2 3 4 5 6 7 8 9 10 11 12 13 |
@{ Layout = null; } <p>RAZOR 구문에서 @@: 지시문을 사용해 문자열 출력하기</p> <hr /> <div> @for (int i = 0; i < 10; i++) { <span>@i</span>@: } </div> |
TestProject.zip
■ RAZOR 구문에서 <text> 태그를 사용해 문자열을 출력하는 방법을 보여준다. ▶ Views/Home/Test.cshtml
1 2 3 4 5 6 7 8 9 10 11 12 13 |
@{ Layout = null; } <p>RAZOR 구문에서 <text> 태그를 사용해 문자열 출력하기</p> <hr /> <div> @for(int i = 0; i < 10; i++) { <span>@i</span><text> </text> } </div> |
TestProject.zip
■ RAZOR 구문에서 반복문을 사용하는 방법을 보여준다. ▶ Views/Home/Test.cshtml
1 2 3 4 5 6 7 8 9 10 11 12 13 |
@{ Layout = null; } <p>RAZOR 구문에서 반복문 사용하기</p> <hr /> <div> @for(int i = 0; i < 10; i++) { <span>@i</span><text> </text> } </div> |
TestProject.zip
■ RAZOR 구문에서 조건문을 사용하는 방법을 보여준다. ▶ Views/Home/Test.cshtml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
@{ Layout = null; } <p>RAZOR 구문에서 조건문 사용하기</p> <hr /> @{ int age = 21; } <div> <p>나이 : @age</p> @if(age % 2 == 0) { <p>짝수 나이</p> } else { <p>홀수 나이</p> } </div> |
TestProject.zip
■ RAZOR 구문에서 C# 코드를 사용하는 방법을 보여준다. ▶ Views/Home/Test.cshtml
1 2 3 4 5 6 7 8 9 10 11 12 |
@using System.IO; @{ Layout = null; } <p>RAZOR 구문에서 C# 코드 사용하기</p> <hr /> @{ string[] filePathArray = Directory.GetFiles(@"C:\Windows", "*.*", SearchOption.TopDirectoryOnly); } <p>파일 수 : @filePathArray.Length</p> |
TestProject.zip
■ RAZOR 구문에서 @ 기호를 사용하는 방법을 보여준다. ▶ Views/Home/Test.cshtml
1 2 3 4 5 6 7 8 9 10 11 12 13 |
@{ Layout = null; } <p>RAZOR 구문에서 @@ 기호 사용하기</p> <hr /> <div> 이메일 : test@daum.com, test@("@")daum.com </div> <div> 트위터 : @@test </div> |
TestProject.zip
■ RAZOR 구문에서 변수를 사용하는 방법을 보여준다. ▶ Views/Home/Test.cshtml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
@{ Layout = null; } <p>RAZOR 구문에서 변수 사용하기</p> <hr /> @{ int value1 = 100; long value2 = 200L; float value3 = 10.5f; double value4 = 10.12345d; string value5 = "\"테스트\" 문자열 입니다."; string value6 = @"""테스트"" 문자열 입니다."; } <p>int : @value1</p> <p>long : @value2</p> <p>float : @value3</p> <p>double : @value4</p> <p>string : @value5</p> <p>string : @value6</p> |
TestProject.zip
■ @inject 지시문을 사용해 뷰 페이지에서 의존성을 주입하는 방법을 보여준다. ▶ Models/DataModel.cs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
namespace TestProject.Models { /// <summary> /// 데이터 모델 /// </summary> public class DataModel { //////////////////////////////////////////////////////////////////////////////////////////////////// Property ////////////////////////////////////////////////////////////////////////////////////////// Public #region ID - ID /// <summary> /// ID /// </summary> public int ID { get; set; } #endregion #region 성명 - Name /// <summary> /// 성명 /// </summary> public string Name { get; set; } #endregion #region 직함 - Title /// <summary> /// 직함 /// </summary> public string Title { get; set; } #endregion } } |
▶ Models/DataRepository.cs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 |
using System.Collections.Generic; using System.Linq; namespace TestProject.Models { /// <summary> /// 데이터 저장소 /// </summary> public class DataRepository { //////////////////////////////////////////////////////////////////////////////////////////////////// Field ////////////////////////////////////////////////////////////////////////////////////////// Private #region Field /// <summary> /// 소스 리스트 /// </summary> private readonly List<DataModel> sourceList = new List<DataModel>() { new DataModel { ID = 1, Name = "김철수", Title = "차장" }, new DataModel { ID = 2, Name = "이영희", Title = "과장" }, new DataModel { ID = 3, Name = "홍길동", Title = "대리" } }; #endregion //////////////////////////////////////////////////////////////////////////////////////////////////// Field ////////////////////////////////////////////////////////////////////////////////////////// Private #region 리스트 구하기 - GetList() /// <summary> /// 리스트 구하기 /// </summary> /// <returns>리스트</returns> public List<DataModel> GetList() { return this.sourceList; } #endregion #region 리스트 구하기 - GetList(name) /// <summary> /// 리스트 구하기 /// </summary> /// <param name="name">성명</param> /// <returns>리스트</returns> public List<DataModel> GetList(string name) { return this.sourceList.Where(n => n.Name.ToLower().Equals(name.ToLower())).ToList(); } #endregion #region 데이터 구하기 - GetData(id) /// <summary> /// 데이터 구하기 /// </summary> /// <param name="id">ID</param> /// <returns>데이터</returns> public DataModel GetData(int id) { return this.sourceList.Where(n => n.ID == id).SingleOrDefault(); } #endregion } } |
▶ Models/DataFinder.cs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
using System.Threading.Tasks; namespace TestProject.Models { /// <summary> /// 데이터 파인더 /// </summary> public class DataFinder { //////////////////////////////////////////////////////////////////////////////////////////////////// Field ////////////////////////////////////////////////////////////////////////////////////////// Private #region Field /// <summary> /// 데이터 저장소 /// </summary> private DataRepository repository = new DataRepository(); #endregion //////////////////////////////////////////////////////////////////////////////////////////////////// Method ////////////////////////////////////////////////////////////////////////////////////////// Public #region 데이터 구하기 - GetData(id) /// <summary> /// 데이터 구하기 /// </summary> /// <param name="id">ID</param> /// <returns>데이터</returns> public async Task<DataModel> GetData(int id) { return await Task.FromResult(repository.GetData(id)); } #endregion } } |
▶ Controllers/DataController.cs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
using Microsoft.AspNetCore.Mvc; using System.Collections.Generic; using TestProject.Models; namespace TestProject.Controllers { /// <summary> /// 데이터 컨트롤러 /// </summary> public class DataController : Controller { //////////////////////////////////////////////////////////////////////////////////////////////////// Method ////////////////////////////////////////////////////////////////////////////////////////// Public #region 인덱스 페이지 처리하기 - Index() /// <summary> /// 인덱스 페이지 처리하기 /// </summary> /// <returns>액션 결과</returns> public IActionResult Index() { DataRepository repository = new DataRepository(); List<DataModel> list = repository.GetList(); return View(list); } #endregion } } |