我正在尝试将 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 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}
Finally, rendering a ViewComponent as a page seems a bit of overkill. I would suggest you should use IViewComponentHelper to render the ViewComponent as an IHtmlContent such that I can write to a StringWriter:
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(); } }
However, your Test ViewComponent resides in Pages/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.
Demo
If I fix the issues as I described above, when running your project I'll get the correct result:
更多推荐
Asp.Net Core将ViewComponent渲染为变量
发布评论