Asp.Net Core 将 ViewComponent 渲染为变量

Jak*_*nda 5 c# asp.net-core

我正在尝试渲染ViewComponentASP.NET Core 3.0(页面)中服务中的字符串。

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!

itm*_*nus 6

原因

  1. NullView现在是一个内部类。但这是一个非常简单的类,什么也不做。换句话说,只需将其从 src 复制并粘贴到源代码中即可。
  2. 您上面链接的教程用于渲染普通视图。但是,由于您尝试渲染视图组件而不是视图,因此应该避免直接传递视图路径。您应该传递ViewComponent 类名(或Type)。

    Model = wait _viewRender.RenderToStringAsync(
         "/Components/Test/Default.cshtml", // 不要传递视图路径,因为我们不渲染视图文件而是视图组件
        "Test",                             // 因为 `ViewComponent ` 名称是测试
        新的 TestModel { StrToPrint = "从服务打印" });
    
  3. 根据官方文档,运行时在以下路径中搜索视图

    1. /Views/{控制器名称}/Components/{视图组件名称}/{视图名称}
    2. /Views/Shared/Components/{视图组件名称}/{视图名称}
    3. /Pages/Shared/Components/{视图组件名称}/{视图名称}

    但是,您的TestViewComponent 驻留在Pages/Components/Test/Default.cshtml默认情况下 Razor 无法找到它。配置自定义视图位置,或将其移动到标准位置,以便 Razor 可以找到视图文件。

  4. 最后,将 ViewComponent 渲染为页面似乎有点矫枉过正。我建议您应该使用IViewComponentHelper将 a 渲染ViewComponentIHtmlContent这样我可以写入 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();
        }
    }
    
    Run Code Online (Sandbox Code Playgroud)

演示

如果我按照上面所述解决问题,那么在运行您的项目时我将得到正确的结果:

在此输入图像描述