I'm using a simple CMS to build a website and have a requirement to inject 'components' into my pages. At present, I am rendering out components in a fairly simple way such as follows:
<latest-blog-posts limit="3" order-by="date asc"/>
I then want to use TagHelpers to fill in the real content. Is there a way to call a controller action in ASP.NET Core and replace the invoking tag with the resulting view. My feeling is that I need to be looking at using output.WriteTo(TextWriter writer, HtmlEncoder encoder)
, but I'm stuck on how to feed the response from an Action into the writer.
You're looking for view components. They're similar in function to the way child actions used to work in MVC 5 and previous.
public class LatestBlogPostsViewComponent : ViewComponent
{
private readonly BlogDbContext db;
public LatestBlogPostsViewComponent(BlogDbContext context)
{
db = context;
}
public async Task<IViewComponentResult> InvokeAsync(int limit, string orderBy)
{
var posts = // get latest posts;
return View(posts);
}
}
Next, create the view Views/Shared/Components/LatestBlogPosts.cshtml
and add the code you'd like to render your list of latest blog posts. Your view's model will be the type of posts
returned by the view component.
Finally, in the view or layout where you want the latest blog posts to be rendered call the component using:
@await Component.InvokeAsync("LatestBlogPosts", new { limit = 3, orderBy = "date asc" })
Or, if you prefer the TagHelper syntax:
<vc:latest-blog-posts limit="3" orderBy="date asc"></vc:latest-blog-posts>
The latter method requires that you register the view component(s).