ViewComponent InvokeAsync 方法和非异步操作

LP1*_*P13 0 async-await asp.net-core-mvc asp.net-core asp.net-core-2.0

在 ASP.NET Core 中,ViewComponent我们必须在InvokeAsync返回IViewComponentResult. async但是,我在调用方法内没有执行任何逻辑。因此,根据此处的帖子,我删除了async限定符并返回Task.FromResult

public Task<IViewComponentResult> InvokeAsync(MyBaseModel model)
{        
    var name = MyFactory.GetViewComponent(model.DocumentTypeID);        
    return Task.FromResult<IViewComponentResult>(View(name, model));
}
Run Code Online (Sandbox Code Playgroud)

然后在视图中(因为我没有,所以async我不在await这里使用)

@Component.InvokeAsync("MyViewComponent", new { model = Model })
Run Code Online (Sandbox Code Playgroud)

然而视图呈现这个:

System.Threading.Tasks.Task1[Microsoft.AspNetCore.Html.IHtmlContent]`

Chr*_*att 5

你必须awaitComponent.InvokeAsync. 您的方法不执行任何异步操作这一事实并不重要。该方法本身是异步的。

然而,这有点过于简单化了。async坦率地说, /关键字的简单性await掩盖了这一切实际上有多么复杂。准确地说,与其将这些类型的方法称为“异步”,不如将它们称为“任务返回”更合适。任务本质上是某些操作的句柄。该操作可以是异步的同步的。它与异步关系最为密切,因为在大多数情况下将同步操作包装在任务中是毫无意义的。然而,要点是,仅仅因为某些东西必须返回任务并不意味着它必须是异步的。

异步所做的只是允许线程切换的可能性。在某些操作(通常涉及 I/O)的情况下,会导致工作线程空闲一段时间,该线程可用于其他工作,并且原始工作可能会在不同的线程上完成。注意这里被动语言的使用。异步操作不涉及线程切换;该任务可以在同一个线程上完成,就像同步一样。如果基础操作已经完成,该任务甚至可以立即完成。

在您的场景中,您没有执行任何异步工作,这很好。然而,方法定义需要Task<T>作为返回,所以你必须使用Task.FromResult返回你的实际结果。这些都是非常标准的东西,你似乎已经理解了。我认为您缺少的是,您认为由于您实际上没有执行任何异步工作,因此使用await. 这个关键字并没有什么神奇的地方await。它基本上只是意味着保持在这里直到任务完成。如果没有异步工作要做,就像这里的情况一样,同步代码将正常运行并在完成后返回到调用代码,但是,为了方便起见,await还执行另一个重要功能:它解开任务。

这就是你的问题所在。由于您没有等待,因此任务本身将返回到 Razor 视图处理管道中。它不知道如何处理它,所以它会执行默认情况下所做的事情,只是调用ToString它,因此您将得到返回的文本。打开包装后,您就拥有了IViewComponentResult,而 Razor确实知道如何处理它。