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.
NullView was removed 3.0 (and is really hard to find any reference on it).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!
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 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.
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();
}
}
If I fix the issues as I described above, when running your project I'll get the correct result:

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With