View Components are similar to partial views, except that they don’t have a visual design surface; all of its contents must be produced by .NET code. Only “tangible” content can be returned, no redirects, or any other contents that require HTTP status codes.
A View Component needs to either inherit from ViewComponent (no API documentation yet) or be a POCO class decorated with the ViewComponentAttribute. If it inherits from ViewComponent, it gets a lot of useful infrastructure methods, otherwise, it is possible to inject some context, such as a ViewContext reference.
A View Component looks like this:
As you can see, a View Component can take parameters, any number, for that matter, and, by convention, its entry point must be called Invoke, return an instance of IViewComponentResult, and here is where its parameters are declared.
A View Component is rendered like this:
As you can see, the argument to Invoke must be the View Component’s class name, without the ViewComponent suffix. We can override this and set our own name, by applying the ViewComponentAttribute:
Notice that this uses a POCO class that does not inherit from ViewComponent. However, the Razor syntax will be exactly the same, because of the Name passed in the ViewComponentAttribute attribute. It basically only needs to be public, concrete and non-generic.
It is also possible to use an asynchronous version:
In this case, the Razor syntax must be instead:
@await Component.InvokeAsync("Sum", 1, 2); <!-- <span class="result">3</span> –>
Because the ViewComponent class exposes some properties that give access to the execution context, namely, ViewContext, it is also possible to have it in the POCO version, by decorating a ViewContext property with ViewContextAttribute:
The ViewComponentContext class gives direct access to the arguments, the ViewData and ViewBag collections, the FormContext and a couple of other useful context properties, so it is generally good to have it near by. It is even possible to access the view’s model:
View Components can benefit of dependency injection. Just add the types that you wish to inject to the constructor, works with both the POCO and the ViewComponent version:
One last remark: view components are automatically loaded from the executing assembly, but it is possible to load them from other assemblies, we just need to get an handle to the web application’s IViewComponentDescriptorCollectionProvider. From it, we can get to the ViewComponents collection and add our own:
This makes it very easy to register View Components that are declared in different assemblies.