我正在为侧边栏创建部分视图,以显示我网站中最受欢迎的帖子。如何创建用于加载局部视图所需模型的独立控制器? (IEnumerable<Post>
热门帖子)
目前我已经创建了一个加载流行帖子的控制器类,但是在渲染部分时我一直遇到错误,因为我无法调用控制器并加载部分模型。例如,如果我从呈现单个帖子的视图中调用它,则模型类型将不匹配(Post
vs IEnumerable<Post>
)
这是我的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<IActionResult> PopularPosts()
{
return PartialView(await _context.Posts
.Where(p => p.IsActive == true)
.OrderByDescending(p => p.Id)
.Take(5)
.ToListAsync());
}
}
}
这是我的部分观点PopularPosts.cshtml
:
@model IEnumerable<GoBaron.Front.Models.Post>
@using GoBaron.Front.Data.Extensions
@if (Model.Any())
{
<div class="sidebar-item" id="topTrending">
<header class="sidebar-item__header">
<h1>Najpopularniejsze</h1>
</header>
<div class="sidebar-item__content">
@foreach (var item in Model)
{
<a asp-controller="Post" asp-action="Details" asp-route-id="@item.Id" asp-route-slug="@item.Title.ConvertToSlug()" title="@item.Title">
<div class="sidebar-post-item" style="background-image:url('@item.PosterUrl')">
<span class="sidebar-post-item__counter">+5</span>
<span class="sidebar-post-item__title">@item.Title</span>
</div>
</a>
}
</div>
</div>
}
当我想要包含热门帖子侧边栏时,例如在布局中,我只需添加:
@await Html.PartialAsync("~/Views/Sidebar/PopularPosts.cshtml")
答案 0 :(得分:15)
这是View Component的一个很好的用例,而不是局部视图。您不仅需要渲染视图,还需要执行从db中加载Popular Posts的那一段逻辑。
创建一个新的$('#line').remove();
$('#chart_container').append('<canvas id="line" height="600px" style="margin-top:20px;" ></canvas>');
类,而不是Controller。这包含在其ViewComponent
方法中为视图组件准备模型的逻辑,它可以使用任意数量的参数。在你的情况下,InvokeAsync
没有参数,将从数据库加载流行的帖子,并将呈现视图组件视图:
InvokeAsync
现在您需要为该视图组件创建视图。默认视图名称public class PopularPostsViewComponent: ViewComponent
{
private readonly ApplicationDbContext _context;
public PopularPostsViewComponent(ApplicationDbContext context)
{
_context = context;
}
public async Task<IViewComponentResult> 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<GoBaron.Front.Models.Post>
@using GoBaron.Front.Data.Extensions
@if (Model.Any())
{
<div class="sidebar-item" id="topTrending">
<header class="sidebar-item__header">
<h1>Najpopularniejsze</h1>
</header>
<div class="sidebar-item__content">
@foreach (var item in Model)
{
<a asp-controller="Post" asp-action="Details" asp-route-id="@item.Id" asp-route-slug="@item.Title.ConvertToSlug()" title="@item.Title">
<div class="sidebar-post-item" style="background-image:url('@item.PosterUrl')">
<span class="sidebar-post-item__counter">+5</span>
<span class="sidebar-post-item__title">@item.Title</span>
</div>
</a>
}
</div>
</div>
}
所需的任何参数。在你的情况下,你没有参数,所以它将是:
InvokeAsync
最后,如果您使用的是.Net Core 1.1或更高版本,您也可以将其作为标记助手调用:
@await Component.InvokeAsync("PopularPosts")
PS。我写了一篇article来描述你可能感兴趣的部分,标记助手和视图组件的用法。