如何在非PartialView的Razor Page中渲染另一个Razor Page?
问题描述
我是ASP.NET Core新手,查过Stack Overflow相关问答但没解决问题。我创建了空的ASP.NET Core Razor Pages项目,在Model文件夹里建了Category和Character两个模型(关系:每个Category可包含多个Character,每个Character仅属于一个Category)。之后在Pages文件夹下创建Category和Character子文件夹,通过Scaffold生成了各自的CRUD页面(Index、Create、Delete、Details、Edit),路径是Pages/Category/Index.cshtml等、Pages/Character/Index.cshtml等。我想在Pages/Index.cshtml底部渲染Category/Index.cshtml,效果类似iframe但无边框和滚动条,让Category/Index.cshtml成为Pages/Index.cshtml的一部分。
Category模型代码
using System.ComponentModel.DataAnnotations; namespace HV.Model { public class Category { [Key] public int Id { get; set; } public string CategoryName { get; set; } public string CategoryDescription { get; set; } public string? CategoryImage { get; set; } public int CharacterId { get; set; } // 创建表示Category和Character两个类之间关系的导航属性 public List<Characters> Characters { get; set; } } }
Character模型代码
namespace HV.Model { public class Characters { public int Id { get; set; } public string CharacterName { get; set; } public string CharacterBio { get; set; } public string CharacterSecretIdentity { get; set; } public bool Charactergender { get; set; } public string CharacterTeam { get; set; } public bool CharacterGoodOrBad { get; set; } public string? CharacterImage { get; set; } public int CategoryId { get; set; } // 每个Character仅属于一个Category public Category Category { get; set; } } }
当前Pages/Index.cshtml主体代码(需渲染Category索引的部分)
<body> <div class="container bg-dark"> <!-- Background image --> <div class="bg-image shadow-2-strong" id="intro"> </div> <!-- Background image --> </div> <div id="content"> <div class="container d-flex align-items-center justify-content-center text-center h-100"> <div class="text-white"> <h1 class="mb-3 display-2">Welcome to HeroVerse</h1> <h5 class="mb-4">Best & free guide to everything Superhero related</h5> <a class="btn btn-outline-light btn-lg m-2" href="https://www.youtube.com/watch?v=c9B4TPnak1A" role="button" rel="nofollow" target="_blank">Start Exploring</a> <a class="btn btn-outline-light btn-lg m-2" href="https://mdbootstrap.com/docs/standard/" target="_blank" role="button">Say Hi</a> </div> </div> </div> <!-- Add more content here to scroll through --> <div class="container text-white" id="content"> <h2>CATEGORIES</h2> <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer euismod mi et odio tincidunt, sit amet bibendum arcu bibendum.</p> <!-- Render the Categories/Index.cshtml Razor Page as a partial view --> <div> @* @await Html.PartialAsync("~/Pages/Categrory/_Index.cshtml", Model.Categories)*@ @* <component type="typeof(CategoryList)" render-mode="ServerPrerendered" />*@ @* <iframe src="/Categrory/Index" style="width: 100%; height:100vh; border:none" ></iframe>*@ <CategoryList /> </div> </div> <div class="container"> <h2>ABOUT</h2> <partial name="~/Pages/About/_IndexAboutPartial.cshtml" /> </div> <!-- Add more content here --> </body>
解决方案
直接复用完整的Razor Page会包含布局等冗余内容,推荐用以下两种方式实现需求:
方案一:抽离部分视图
- 在
Pages/Category下新建_CategoryListPartial.cshtml,把Category/Index.cshtml里的列表核心代码移进去(去掉页面指令、布局引用,只保留列表渲染逻辑):
@model IEnumerable<HV.Model.Category> <table class="table"> <thead> <tr> <th>@Html.DisplayNameFor(model => model.CategoryName)</th> <th>@Html.DisplayNameFor(model => model.CategoryDescription)</th> <th></th> </tr> </thead> <tbody> @foreach (var item in Model) { <tr> <td>@Html.DisplayFor(modelItem => item.CategoryName)</td> <td>@Html.DisplayFor(modelItem => item.CategoryDescription)</td> <td> <a asp-page="./Category/Edit" asp-route-id="@item.Id">Edit</a> | <a asp-page="./Category/Details" asp-route-id="@item.Id">Details</a> | <a asp-page="./Category/Delete" asp-route-id="@item.Id">Delete</a> </td> </tr> } </tbody> </table>
- 修改
Pages/Index.cshtml.cs,注入数据上下文并获取分类列表:
using HV.Model; using Microsoft.EntityFrameworkCore; using Microsoft.AspNetCore.Mvc.RazorPages; namespace HV.Pages { public class IndexModel : PageModel { private readonly HV.Data.ApplicationDbContext _context; public IndexModel(HV.Data.ApplicationDbContext context) { _context = context; } public IList<Category> Categories { get; set; } = default!; public async Task OnGetAsync() { if (_context.Categories != null) { Categories = await _context.Categories.ToListAsync(); } } } }
- 在
Pages/Index.cshtml中调用部分视图:
<div> @await Html.PartialAsync("~/Pages/Category/_CategoryListPartial.cshtml", Model.Categories) </div>
方案二:使用视图组件
- 创建
Components/CategoryListViewComponent.cs:
using HV.Model; using Microsoft.EntityFrameworkCore; using Microsoft.AspNetCore.Mvc; namespace HV.Components { public class CategoryListViewComponent : ViewComponent { private readonly HV.Data.ApplicationDbContext _context; public CategoryListViewComponent(HV.Data.ApplicationDbContext context) { _context = context; } public async Task<IViewComponentResult> InvokeAsync() { var categories = await _context.Categories.ToListAsync(); return View(categories); } } }
- 创建视图组件对应的视图
Components/CategoryList/Default.cshtml,内容和方案一中的部分视图一致。 - 在
Pages/Index.cshtml中调用视图组件:
<div> @await Component.InvokeAsync("CategoryList") </div>
额外修正
Category模型中的public int CharacterId { get; set; }是多余的,Category作为一对多关系的一方,不需要指向Character的外键,删除该属性可避免数据关系混乱。
内容的提问来源于stack exchange,提问作者DAkers
相关产品推荐
相关产品推荐

