如何在ASP.NET Core 2.0中使用Razor頁面


如何在ASP.NET Core 2.0中使用Razor頁面

 DotNetCore 2017-11-22 14:49

問題

如何在ASP.NET Core 2.0中使用Razor頁面

創建一個空的項目並修改Startup.cs文件以為MVC添加服務和中間件。

  1. publicvoid ConfigureServices(

  2. IServiceCollection services)

  3. {

  4. services.AddSingleton<IMovieService, MovieService>();

  5. services.AddMvc();

  6. }

  7. publicvoid Configure(

  8. IApplicationBuilder app,

  9. IHostingEnvironment env)

  10. {

  11. app.UseMvc();

  12. }

添加一個服務和域模型(IMovieService的實現只是示例源代碼中的內存列表),

  1. publicclass Movie

  2. {

  3. publicint Id { get; set; }

  4. public string Title { get; set; }

  5. publicint ReleaseYear { get; set; }

  6. public string Summary { get; set; }

  7. }

  8. publicinterface IMovieService

  9. {

  10. List<Movie> GetMovies();

  11. Movie GetMovie(int id);

  12. void AddMovie(Movie item);

  13. void UpdateMovie(Movie item);

  14. void DeleteMovie(int id);

  15. bool MovieExists(int id);

  16. }

添加輸入和輸出模型(通過屬性綁定接收和發送數據)。

  1. publicclass MovieInputModel

  2. {

  3. publicint Id { get; set; }

  4. [Required]

  5. public string Title { get; set; }

  6. publicint ReleaseYear { get; set; }

  7. public string Summary { get; set; }

  8. }

  9. publicclass MovieOutputModel

  10. {

  11. publicint Id { get; set; }

  12. public string Title { get; set; }

  13. publicint ReleaseYear { get; set; }

  14. public string Summary { get; set; }

  15. public DateTime LastReadAt { get; set; }

  16. }

添加一個名為Pages的文件夾,並為其添加Index,_Layout,_ViewImports和_ViewStart頁面。這些頁面與MVC沒有區別。另外,為您的CRUD頁面添加一個文件夾Movies。

添加4個新的RazorPage項目到電影文件夾 - 稱為索引,創建,編輯和刪除。這些將添加.cshtml和.cshtml.cs文件。

這些頁面中的每一個都將通過構造器注入來注入我們的 IMovieService ,例如,

  1. private readonly IMovieService service;

  2. public IndexModel(IMovieService service)

  3. {

  4. this.service = service;

  5. }

修改Index.cshtml。

  1. @page

  2. @model IndexModel

  3. @{

  4. }

  5. <strong>Movie Listing</strong>

  6. <div>

  7. <a asp-page="/Index">Home</a> |

  8. <a asp-page="./Create">Add New</a>

  9. </div>

  10. <table>

  11. <thead>

  12. <tr>

  13. <th>Title</th>

  14. <th>Year</th>

  15. <th></th>

  16. <th></th>

  17. <th></th>

  18. </tr>

  19. </thead>

  20. <tbody>

  21. @foreach (var item in Model.Movies)

  22. {

  23. <tr>

  24. <td>@item.Title</td>

  25. <td>@item.ReleaseYear</td>

  26. <td><a asp-page="./Edit" asp-route-id="@item.Id">Edit</a></td>

  27. <td><a asp-page="./Delete" asp-route-id="@item.Id">Delete</a></td>

  28. </tr>

  29. }

  30. </tbody>

  31. </table>

修改Index.cshtml.cs。

  1. public List<MovieOutputModel> Movies { get; set; }

  2. publicvoid OnGet()

  3. {

  4. this.Movies = this.service.GetMovies()

  5. .Select(item => new MovieOutputModel

  6. {

  7. Id = item.Id,

  8. Title = item.Title,

  9. ReleaseYear = item.ReleaseYear,

  10. Summary = item.Summary,

  11. LastReadAt = DateTime.Now

  12. })

  13. .ToList();

  14. }

修改Create.cshtml。

  1. @page

  2. @model CreateModel

  3. @{

  4. }

  5. <strong>New Movie</strong>

  6. <form method="post">

  7. <div asp-validation-summary="All"></div>

  8. <label asp-for="Movie.Id"></label>

  9. <input asp-for="Movie.Id" /><br />

  10. <label asp-for="Movie.Title"></label>

  11. <input asp-for="Movie.Title" />

  12. <span asp-validation-for="Movie.Title"></span><br />

  13. <label asp-for="Movie.ReleaseYear"></label>

  14. <input asp-for="Movie.ReleaseYear" /><br />

  15. <label asp-for="Movie.Summary"></label>

  16. <textarea asp-for="Movie.Summary"></textarea><br />

  17. <button type="submit">Save</button>

  18. <a asp-page="./Index">Cancel</a>

  19. </form>

修改Create.cshtml.cs。

  1. [BindProperty]

  2. public MovieInputModel Movie { get; set; }

  3. publicvoid OnGet()

  4. {

  5. this.Movie = new MovieInputModel();

  6. }

  7. public IActionResult OnPost()

  8. {

  9. if (!ModelState.IsValid)

  10. return Page();

  11. var model = new Movie

  12. {

  13. Id = this.Movie.Id,

  14. Title = this.Movie.Title,

  15. ReleaseYear = this.Movie.ReleaseYear,

  16. Summary = this.Movie.Summary

  17. };

  18. service.AddMovie(model);

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

  20. }

修改Edit.cshtml。

  1. @page "{id:int}"

  2. @model EditModel

  3. @{

  4. }

  5. <strong>Edit Movie - @Model.Movie.Title</strong>

  6. <form method="post">

  7. <div asp-validation-summary="All"></div>

  8. <input type="hidden" asp-for="Movie.Id" />

  9. <label asp-for="Movie.Title"></label>

  10. <input asp-for="Movie.Title" />

  11. <span asp-validation-for="Movie.Title"></span><br />

  12. <label asp-for="Movie.ReleaseYear"></label>

  13. <input asp-for="Movie.ReleaseYear" /><br />

  14. <label asp-for="Movie.Summary"></label>

  15. <textarea asp-for="Movie.Summary"></textarea><br />

  16. <button type="submit">Save</button>

  17. <a asp-page="./Index">Cancel</a>

  18. </form>

修改Edit.cshtml.cs。

  1. [BindProperty]

  2. public MovieInputModel Movie { get; set; }

  3. public IActionResult OnGet(int id)

  4. {

  5. var model = this.service.GetMovie(id);

  6. if (model == null)

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

  8. this.Movie = new MovieInputModel

  9. {

  10. Id = model.Id,

  11. Title = model.Title,

  12. ReleaseYear = model.ReleaseYear,

  13. Summary = model.Summary

  14. };

  15. return Page();

  16. }

  17. public IActionResult OnPost()

  18. {

  19. if (!ModelState.IsValid)

  20. return Page();

  21. var model = new Movie

  22. {

  23. Id = this.Movie.Id,

  24. Title = this.Movie.Title,

  25. ReleaseYear = this.Movie.ReleaseYear,

  26. Summary = this.Movie.Summary

  27. };

  28. service.UpdateMovie(model);

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

  30. }

修改Delete.cshtml。

  1. @page "{id:int}"

  2. @model DeleteModel

  3. @{

  4. }

  5. <strong>Delete Movie</strong>

  6. <p>Are you sure you want to delete <strong>@Model.Title</strong>?</p>

  7. <form method="post">

  8. <input type="hidden" asp-for="Id" />

  9. <button type="submit">Yes</button>

  10. <a asp-page="./Index">No</a>

  11. </form>

修改Delete.cshtml.cs。

  1. [BindProperty]

  2. publicint Id { get; set; }

  3. public string Title { get; set; }

  4. public IActionResult OnGet(int id)

  5. {

  6. var model = this.service.GetMovie(id);

  7. if (model == null)

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

  9. this.Id = model.Id;

  10. this.Title = model.Title;

  11. return Page();

  12. }

  13. public IActionResult OnPost()

  14. {

  15. if (!service.MovieExists(this.Id))

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

  17. service.DeleteMovie(this.Id);

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

  19. }

運行並瀏覽到/電影。

點擊時,首先編輯(注意網址是/ Movies / Edit / 1),

點擊刪除(注意URL將是/電影/刪除/ 3),

注意

你可以下載源代碼來玩它。

討論

在ASP.NET Core 2.0中引入了Razor頁面,可以更快地構建簡單的Web應用程序,並且是使用各種ASP.NET Core概念(如Razor,Layout Pages和Tag Helper等)的好方法。

Razor Pages使用 ASP.NET Core MVC ,但是編程模型不一樣。與MVC不同,控制器,模型和視圖是體系結構的不同組成部分,在Razor Pages中,這些概念被集中到一個頁面模型的頁面中。

頁面模型

我喜歡將Page Model視為Controller和Models的組合。他們就像控制器,因為他們收到的HTTP請求,像一個模型,因為他們擁有視圖的數據/屬性。

對於.cshtml文件充當Page Model,它必須包含@page指令的第一行。.cshtml.cs(代碼隱藏)類繼承自PageModel抽象類。按照慣例,代碼隱藏類有 模型 附加到頁面的名稱,例如索引頁的代碼隱藏是IndexModel。

路由

路由到頁面取決於它們在您的項目目錄結構中位於Pages文件夾下的位置(默認情況下)。如果URL中沒有指定頁面,則使用默認的索引。

在我們的示例中,我們導航到URL / Movies以查看位於我們的解決方案中的/ Pages / Movies / Index的頁面。類似地,URL / Movies / Edit映射到/ Pages / Movies / Edit頁面。

ASP.NET Core 2.0引入了用於生成URL的新構造,

  • Page()方法

  • asp頁面標簽助手

  • PageModel基類的RedirectToPage()方法

請注意,以/開頭的URL是絕對路徑並指向Pages文件夾。我們也可以使用與./或../相關的URL,或者簡單的省略/。為了更好地理解,這里是從Page / Movies / Delete導航到各種URL時發生的情況,

我們可以將路由約束指定為@page指令的一部分,以指示運行時期望路由參數,或者丟失404(未找到)。在我們的編輯頁面中,我們使用約束 -

  1. @page “{id:int}”

如果您希望使用不同於Pages的名稱作為根文件夾,則可以通過配置頁面選項來實現。

  1. services.AddMvc()

  2. .AddRazorPagesOptions(options =>

  3. {

  4. options.RootDirectory = "/MyPages";

  5. });

處理程序

如前所述,頁面接收HTTP請求(即充當MVC世界中的Action),並由 處理程序方法處理。 這些處理程序返回IActionResult並使用On [verb]的約定命名。最常用的是OnGet()和OnPost()。對於異步,您可以將Async附加到名稱,但是這是可選的。

PageModel基類具有RedirectToPage()方法(返回RedirectToPageResult)導航到其他頁面和Page()方法(返回PageResult)返回當前頁面。請注意,如果處理程序方法的返回類型為void,則運行時將返回PageResult。

為了讓HTTP動詞擁有多個處理器方法,我們可以使用 asp-page-handler屬性來使用 命名處理器方法。這里指定的名字應該在頁面類中使用約定On [動詞] [處理程序]。讓我們添加一個鏈接到我們的電影列表刪除電影,

  1. <td>

  2. <a asp-page="./Index"

  3. asp-page-handler="delete"

  4. asp-route-id="@item.Id">Delete</a>

  5. </td>

在頁面模型類中添加一個方法來處理這個請求(注意它的名字和參數),

  1. public IActionResult OnGetDelete(int id)

  2. {

  3. if (!service.MovieExists(id))

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

  5. service.DeleteMovie(id);

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

  7. }

將鼠標移到刪除鏈接上,您會注意到像/ Movies?id = 1&handler = delete這樣的URL。如果您希望用URL段替換查詢參數,則將以下路由約束添加到@page指令,生成的URL將為/ Movies / delete / 1,

  1. @page "{handler?}/{id:int?}"

捆綁

頁面上的@model指令指向頁面模型類,因為如前所述,該類充當Razor頁面的模型。這適用於讀取屬性,但為了在發布數據時填充它們(即,當使用除GET之外的動詞時),我們需要使用屬性[BindProperty]來標記要使用模型綁定的屬性。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM