在渲染局部视图时如何调用控制器操作?
我正在为侧边栏创建部分视图,以显示我网站中最受欢迎的post。 如何创建一个单独的控制器来加载局部视图所需的模型? ( IEnumerable
与热门post)
目前我已经创建了一个加载流行post的控制器类,但是在渲染部分时我一直遇到错误,因为我无法调用控制器并加载部分模型。 例如,如果我从我渲染单个post的视图中调用它,则模型类型将不匹配( Post
vs IEnumerable
)
这是我的SidebarController
:
using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; using GoBaron.Front.Models; namespace GoBaron.Front.Controllers { public class SidebarController : Controller { private readonly ApplicationDbContext _context; public SidebarController(ApplicationDbContext context) { _context = context; } public async Task PopularPosts() { return PartialView(await _context.Posts .Where(p => p.IsActive == true) .OrderByDescending(p => p.Id) .Take(5) .ToListAsync()); } } }
这是我的部分视图PopularPosts.cshtml
:
@model IEnumerable @using GoBaron.Front.Data.Extensions @if (Model.Any()) {
}
当我想要包含热门post侧边栏时,例如在布局中,我只需添加:
@await Html.PartialAsync("~/Views/Sidebar/PopularPosts.cshtml")
这是View Component的一个很好的用例,而不是局部视图。 您不仅需要渲染视图,还需要执行从db加载Popular Posts的逻辑。
而不是Controller,创建一个新的ViewComponent
类。 这包含在其InvokeAsync
方法中为视图组件准备模型的逻辑,它可以使用任意数量的参数。 在您的情况下, InvokeAsync
不带参数,将从db加载流行的post并将呈现视图组件视图:
public class PopularPostsViewComponent: ViewComponent { private readonly ApplicationDbContext _context; public PopularPostsViewComponent(ApplicationDbContext context) { _context = context; } public async Task InvokeAsync() { var posts = await _context.Posts .Where(p => p.IsActive == true) .OrderByDescending(p => p.Id) .Take(5) .ToListAsync(); return View(posts); } }
现在,您需要为该视图组件创建视图。 默认视图名称Default.cshtml
(当您在不指定视图名称的情况下return View()
),它应位于Views/Shared/Components/PopularPosts/Default.cshtml
。 这基本上与您当前的局部视图相同:
@model IEnumerable @using GoBaron.Front.Data.Extensions @if (Model.Any()) { }
然后从任何其他视图,您将呈现视图组件而不是部分,传递InvokeAsync
所需的任何参数。 在你的情况下,你没有参数,所以它将是:
@await Component.InvokeAsync("PopularPosts")
最后,如果您使用的是.Net Core 1.1或更高版本,您也可以将其作为标记帮助程序调用:
PS。 我写了一篇文章,描述了您可能感兴趣的部分,标记助手和视图组件的用法。