在asp.net核心ViewComponent
中,我们必须在返回InvokeAsync
的{{1}}方法中实现逻辑。但是,我没有任何IViewComponentResult
逻辑可以在invoke方法内执行。因此,基于SO post here,我删除了async
限定词,只返回了async
Task.FromResult
然后在View中(由于我没有public Task<IViewComponentResult> InvokeAsync(MyBaseModel model)
{
var name = MyFactory.GetViewComponent(model.DocumentTypeID);
return Task.FromResult<IViewComponentResult>(View(name, model));
}
,所以我不在这里使用async
)
await
但是视图呈现了这一点:
@Component.InvokeAsync("MyViewComponent", new { model = Model })
1 [Microsoft.AspNetCore.Html.IHtmlContent]`
答案 0 :(得分:2)
您必须await
Component.InvokeAsync
。您的方法不执行任何异步操作这一事实无关紧要。该方法本身是异步的。
但是,这有点过分简化了。坦率地说,async
/ await
关键字的易用性掩盖了这一切实际上是多么复杂。准确地说,与其将这些类型的方法称为“异步”,不如将它们称为“任务返回”。任务本质上是某些操作的句柄。该操作可以是异步或同步。它与异步关系最密切,只是因为在大多数情况下将同步操作包装在任务中是毫无意义的。但是,关键是仅仅因为某些东西必须返回任务并不意味着它必须是异步的。
所有异步所做的就是允许线程切换的可能性。在某些操作(通常涉及I / O)会导致工作线程空闲一段时间的情况下,该线程可用于其他工作,并且原始工作 在其他线程上完成。注意此处使用被动语言。异步操作可以不涉及线程切换。该任务可以在同一线程上完成,就好像它是同步的一样。如果基础操作已经完成,则该任务甚至可以立即完成。
在这里的情况下,您没有做任何异步工作,这很好。但是,方法定义要求使用Task<T>
作为返回值,因此您必须使用Task.FromResult
返回实际结果。这些都是非常标准的东西,似乎已经为您所理解。我想,您所缺少的是,您在考虑的是,由于您实际上并未在进行任何异步工作,因此使用await
是错误的。 await
关键字没有什么神奇之处;它基本上只是意味着一直待在这里直到任务完成。如果没有要完成的异步工作(例如此处的情况),则同步代码将正常运行,并在完成后返回到调用代码。不过,为方便起见,await
还执行了另一个重要功能:它解开了任务。
这就是您的问题所在。由于您不等待,因此任务本身将返回到Razor视图处理管道中。它不知道该怎么做,因此默认情况下它会执行它的操作,并且仅在其上调用ToString
,因此您将返回该文本。展开后,您只需要IViewComponentResult
,而Razor 确实知道该怎么做。
答案 1 :(得分:1)
如果您在invoke方法内执行的逻辑是同步的,即您没有任何await
,则有2个选项:
async
关键字的invoke方法,并且应该返回Task.FromResult<T>
public IViewComponentResult Invoke()
。我认为async
关键字启用了await
关键字,这很重要。 async
关键字没什么特别的。
由于标记帮助程序方法,在呈现视图的主线程上
要等待调用视图组件Component.InvokeAsync()
,您确实需要在此处放置await
关键字以启动任务。 await
检查视图组件渲染以查看其是否已经完成。如果有,那么主线程将继续运行。否则,主线程将告诉ViewComponent运行。