Asp.Net Core将ViewComponent渲染为变量 [英] Asp.Net Core render ViewComponent to variable
问题描述
我正在尝试将 ViewComponent
呈现为ASP.NET Core 3.0(页面)中服务中的字符串.
我找到了两个解决问题的方法,但是都适用于3.0之前的旧版本,并且有一些我不知道如何解决的问题.
- 第一个摘录自
I am trying to render
ViewComponent
to a string in a service in ASP.NET Core 3.0 (Pages).I found two partial solutions to my problem, but both are for older pre 3.0 version and have some issues that I do not know how to resolve.
- First one is taken from GitHub Gist, but designed with controllers in mind and
NullView
was removed 3.0 (and is really hard to find any reference on it). - The second option is here, but fails one line 42 (no view is found). I believe that this is due to the changes made in .net core, where the views are now precompiled and the razor view engine therefore cannot find them.
I did some of my own experimenting, but could not get it working (I believe I am facing the same issue as the second solution I posted). I would appreciate any help regarding this matter on how to get it working. I've added my best attempt and a minimum project to GitHub, where Render is in the Service folder and in the Index.cshtml.cs is the call to the service.
Thanks!
解决方案The Reasons
NullView
is an internal class now. But that's a very simple class that does nothing. In other words, simply copy & paste it from the src into your source code.The tutorials you linked above is used to render a plain view. However, since you're trying to render a view component instead of a view, you should avoid passing a view path directly. You should pass a ViewComponent Class Name (or Type) instead.
Model = await _viewRender.RenderToStringAsync(
"/Components/Test/Default.cshtml",// don't pass a view path since we're not rendering a view file but a view component "Test", // because the `ViewComponent` Name is Test new TestModel { StrToPrint = "Print From Service" });According to the official docs, The runtime searches for the view in the following paths:
- /Views/{Controller Name}/Components/{View Component Name}/{View Name}
- /Views/Shared/Components/{View Component Name}/{View Name}
- /Pages/Shared/Components/{View Component Name}/{View Name}
However, your
Test
ViewComponent resides inPages/Components/Test/Default.cshtml
, which can not be found by Razor by default. Either configure a custom View Location, or move it to the standard location such that Razor can find the view files.Finally, rendering a ViewComponent as a page seems a bit of overkill. I would suggest you should use
IViewComponentHelper
to render theViewComponent
as anIHtmlContent
such that I can write to aStringWriter
:public class MyViewComponentContext { public HttpContext HttpContext { get; set; } public ActionContext ActionContext { get; set; } public ViewDataDictionary ViewData { get; set; } public ITempDataDictionary TempData { get; set; } } private async Task<string> Render( MyViewComponentContext myViewComponentContext,string viewComponentName,object args) { using (var writer = new StringWriter()) { var helper = this.GetViewComponentHelper(myViewComponentContext, writer); var result = await helper.InvokeAsync(viewComponentName, args); // get an IHtmlContent result.WriteTo(writer, HtmlEncoder.Default); await writer.FlushAsync(); return writer.ToString(); } }
Demo
If I fix the issues as I described above, when running your project I'll get the correct result:
这篇关于Asp.Net Core将ViewComponent渲染为变量的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!
- First one is taken from GitHub Gist, but designed with controllers in mind and