C# 从IViewComponentThelper扩展方法中调用Component.InvokeAsync()

C# 从IViewComponentThelper扩展方法中调用Component.InvokeAsync(),c#,razor,extension-methods,asp.net-core-3.1,asp.net-core-viewcomponent,C#,Razor,Extension Methods,Asp.net Core 3.1,Asp.net Core Viewcomponent,我有一个解决方案,它既有一个ASP.NET核心3.1 web应用程序项目,也有一个Razor客户端库(RCL)项目。我正在尝试编写一个视图组件,该组件将与Razor客户端库一起分发,但可以从ASP.NET核心web应用程序中引用 在web应用程序的\u Layout.cshtml上调用InvokeAsync()标记帮助程序时,我可以成功呈现此ViewComponent: @await Component.InvokeAsync(“NavBar”,new{}) 但是我想使RCL不依赖于web应用

我有一个解决方案,它既有一个ASP.NET核心3.1 web应用程序项目,也有一个Razor客户端库(RCL)项目。我正在尝试编写一个视图组件,该组件将与Razor客户端库一起分发,但可以从ASP.NET核心web应用程序中引用

在web应用程序的
\u Layout.cshtml
上调用
InvokeAsync()
标记帮助程序时,我可以成功呈现此
ViewComponent

@await Component.InvokeAsync(“NavBar”,new{})
但是我想使RCL不依赖于web应用程序上提供的字符串名称。相反,我想通过如下扩展方法调用
ViewComponent

@{await Component.RenderMyViewComponentAsync();}
对我来说,这种方式对使用此共享RCL库的人更有利,因为他们不需要指定
ViewComponent
的确切名称,并且可以依靠IntelliSense来完成扩展方法

我创建了一个helper类,该类接受
ViewComponent
对象,并在扩展方法中调用其
InvokeAsync()
方法:

公共静态类PartialHelper
{
公共静态异步任务RenderMyViewComponentAsync(此IViewComponentThelper vcHelper)
{
return wait vcHelper.InvokeAsync(“NavBar”,new{});
}
}
当然,在
NavBarViewComponent.cs
中,我实现了
InvokeAsync()
方法:

公共类NavBarViewComponent:ViewComponent
{
公共异步任务InvokeAsync()
{
返回视图();
}
}
但问题是:我看不到后一种方法在屏幕上渲染视图,尽管这两种方法仍然会影响我的
NavBarViewComponent.InvokeAsync()

在我看来,返回
ViewComponent
s的两种方法在功能上是等效的,并且使用相同的方法,除了
@{wait Component.RenderMyViewComponentAsync();}
首先通过一个helper函数

我试着用两种方法调试,但都没用。我被卡住了


有没有办法实现我在这里的要求?如果需要任何澄清,请询问。

您的扩展方法实际上与它应该的工作方式完全相同。问题在于如何从
\u Layout.cshtml
调用它。您正在使用以下语法:

@{await Component.RenderMyViewComponentAsync();}
它将其视为在脚本块中,而不是将
IHtmlContent
呈现给视图。
IHtmlContent
已正确返回,但未分配给任何内容或写入输出

相反,您只需要使用调用
InvokeAsync()
时使用的相同样式语法:

@await Component.RenderMyViewComponentAsync()

然后,这将完全符合您的预期。

除了回答您的具体问题之外,我还想回答您问题背后的问题。您的总体目标似乎是简化语法,而不依赖于不提供任何设计或编译时验证的字符串

我真的很喜欢您使用扩展方法作为解决方案的方法,我很可能会借用这一方法。但解决类似目标的另一种方法是:


这在Visual Studio中为您提供了基本的IntelliSense支持,并且比
InvokeAsync()
方法更简洁

也就是说,值得注意的是,标记助手方法确实有几个关键限制:

  • 它不支持排除您在
    InvokeAsync()
    方法*上定义的任何可选参数
  • 如果缺少任何参数,Visual Studio和编译器都不会提供(明显的)警告
  • 考虑到这一点,如果视图组件有任何参数,尤其是其中任何参数有逻辑默认值,那么使用扩展方法的方法可能仍然更可取

    *注意:从ASP.NET Core 6 Preview 6开始,作为标记帮助程序调用的视图组件现在将使用可选参数()


    扩展方法也有同样的问题,所以谢谢你的回答

    一个添加-使用泛型在编译时捕获错误,而不是使用字符串:

    await Component.InvokeAsync<NavBar>();
    

    嗯,我完全没有注意到
    InvokeAsync()
    上有一个泛型类型选项。那很有用。我仍然更喜欢使用taghelper语法(),但对于需要使用
    InvokeAsync()
    的情况,这会更好。谢谢。更新:从ASP.NET Core 6 Preview 6开始,作为标记帮助程序调用的视图组件现在将使用可选参数()。这使它们非常适合这种情况。
    await Component.InvokeAsync<NavBar>();
    
    public IActionResult Index()
    {
        return ViewComponent(typeof(NavBar));
    }