Search code examples
c#asp.net-core-mvcasp.net-core-mvc-2.0

Why Does the ViewComponentResult.ExecuteResult method return void?


I'm trying to better understand the "behind the scenes" on view components. I know that the standard approach is to invoke the ViewComponent by using

 @await Component.InvokeAsync("MyViewComponent", itsModel) 

or a view component tag helper in the .cshtml file.

It's possible however to use view componets other ways. So for example you can return a view directly from a controller by using return ViewComponent("MyViewComponent", itsModel); from an action method.

It seems like it should be possible to easily render the view component to a string. I see that on the ViewComponetResult returned by ViewComponent("MyViewComponent", itsModel); there is an ExecuteResult method.

In a controller it can be called like this:

 ViewComponent("MyViewComponent", itsModel).ExecuteResult(this.ControllerContext);

At first blush I'd expect such a method to return a string of html. But it returns void. Why? What is ViewComponentResult.ExecuteResult doing if it's not returning a result? And how can I render a ViewComponentResult into a string of HTML?


Solution

  • I finally understand how this works. @TavisJ's comment is what tipped me of and sent me researching in the right direction.

    On a ViewComponentResult or more universally, on any ActionResult the ExecuteResult returns void because the output of the ViewComponent is written to the associated HttpResponse.Body. This is true of the async version of the call as well except that of course it returns a Task.

    So for example, if a person were to make the following call:

      await ViewComponent("MyViewComponent", itsModel).ExecuteResultAsync(this.ControllerContext);
    

    to capture the "output" of the view component, one would first need to replace the this.ControllerContext.HttpResponse.Response.Body with a stream of their choice before making the ExecuteResultAsync call so that the output is captured in a stream that can then be converted to a string.

    Then of course, the original stream should be put back on the this.ControllerContext.HttpResponse.Response.Body so the rest of the view renders correctly.