在渲染局部视图时如何调用控制器操作?

我正在为侧边栏创建部分视图,以显示我网站中最受欢迎的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。 我写了一篇文章,描述了您可能感兴趣的部分,标记助手和视图组件的用法。