Introduction to view Components
In the new ASP. NET Core MVC, the view components are similar to the partial view, but they are more powerful. The view component does not use model binding, only depends on the data that you provide when you call.
View Component Features:
- Renders a portion of a page response instead of the entire response
- Includes separation of concerns and testability benefits found between controllers and views
- can have parameters and business logic
- Typically called in a page layout
A view component is a rendering logic that can be reused anywhere, and is relatively complex for a partial view, such as:
- Dynamic navigation Menu
- Tag Cloud (query database)
- Login panel
- Shopping Cart
- Recently published articles
- Sidebar content on a typical blog
- The login panel that will be rendered on each page and displays the link to log off or sign in, depending on the user's login status
A view component consists of two parts: a class (usually inherited from Viewcomponent) and a returned result (usually a view). Like controllers, view components can be Poco, but most developers want to take advantage ViewComponent
of inherited methods and properties.
Creating a View Component
This section contains advanced features for creating view components. Later in this article, we'll cover each step in detail and create a view component.
View Component Classes
View component classes can be created in any of the following ways:
- Inherit from Viewcomponent class
- Use
[ViewComponent]
attributes to mark a class, or inherit from a [ViewComponent]
class with attributes
- The name of the created class ends with the viewcomponent suffix
As with the controller, the view component must be a public, non-nested, non-abstract class. The name of the view component is the class name that removes the "viewcomponent" suffix, or you can ViewComponentAttribute.Name
explicitly specify the name by using an attribute.
View Component class attributes:
- Perfect support for constructor dependency injection
- Does not participate in the controller life cycle, which means that you cannot use filters in the View component
View Component Methods
The view component InvokeAsync
defines the logic in the method and returns the IViewComponentResult
type. Parameters are directly from the call of the view component, not the model binding; The view component never processes the request directly; The view component typically initializes the model and View
passes it to the view by calling the method. In summary, the View component method features:
- Defines a
IViewComponentResult
method to InvokeAsync
return
- Typically initializes a model and
ViewComponent
passes it to the view by invoking a method of the type View
- parameter is from the calling method, not the HTTP request, no model binding
- cannot be accessed directly through HTTP requests, which are usually called through code in the view; The view component never processes the request
- Overloads on the method signature, not any details of the current HTTP request
Find View Path
The runtime searches for views in the following path:
- Views/<controller_name>/components/<view_component_name>/<view_name>
- Views/shared/components/<view_component_name>/<view_name>
The view name of the View component defaults to default, which means that your view file is typically named default.cshtml. When you create a view component result or invoke View
a method, you can specify a different view name.
We recommend that you name the view file default.cshtmland use views/shared/components/<view_component_name>/<view_name >.cshtml path. The view component used in this example, the path to the PriorityList
view is views/shared/components/prioritylist/default.cshtml.
Calling the View component
To use the view component, call the following code in the view:
<anonymous type containing parameters>)
Parameters are passed to the InvokeAsync
method, and the view component written in this article is called in the PriorityList
views/todo/index.cshtml view file. In the following, the method is called using two parameters InvokeAsync
:
@await Component.InvokeAsync("PriorityList", new { maxPriority = 4, isDone = true })
Calling the view component through the tag helper
For ASP. NET Core 1.1 and later, you can call the view component as a tag helper:
<vc:priority-list max-priority="2" is-done="false"> </vc:priority-list>
The tag helper converts the type and method parameters of the Pascal naming method to their lowercase dash naming method (lower kebab case). The label helper that invokes the view component uses the element, and the view component convention is as follows:
<VC: [view-component-name] parameter1= "Parameter1 value" Span class= "hljs-attr" >parameter2= "Parameter2 Value "> </ vc:[view-component-name]>
Note: In order to use the view component as a label helper, you must @addTagHelper
register the assembly that contains the view component with directives. For example, if your view component is in an assembly named "MyWebApp," add the following directive to the _ViewImports.cshtml
file:
@addTagHelper *, MyWebApp
You can register a view component as a label helper to any file that references a view component. For more information about how to register the label Helper, see Managing Tag Helper Scope.
The method used in this example InvokeAsync
:
@await Component.InvokeAsync("PriorityList", new { maxPriority = 4, isDone = true })
Tag Helper Tags:
<vc:priority-list max-priority="2" is-done="false"> </vc:priority-list>
In the example above, the PriorityList
view component is changed, and priority-list
the parameter of the view component is passed as a lowercase dash named as a property.
Calling the view component directly from the controller
View components are typically called in views, but you can also call them directly in the controller's methods. Although the view component is defined as not being able to process requests directly like a controller, you can easily implement the return content in the Controller's action method ViewComponentResult
.
In the following example, the view component is called directly on the controller:
public IActionResult IndexVC() { return ViewComponent("PriorityList", new { maxPriority = 3, isDone = false }); }
Walkthrough: Creating a Simple View component
Sample download, build, and test the Getting started code. This is a simple project and the Todo
controller displays a list of Todo items.
Add Viewcomponent Class
Create a viewcomponents folder and add the following PriorityListViewComponent
classes:
Using MICROSOFT.ASPNETCORE.MVC;Using Microsoft.entityframeworkcore;Using System.Collections.Generic;Using System.Linq;Using System.Threading.Tasks;Using Viewcomponentsample.models;Namespaceviewcomponentsample.viewcomponents{PublicClassPrioritylistviewcomponent:viewcomponent {PrivateReadOnly Todocontext DB;Publicprioritylistviewcomponent (todocontext context) {db = context;} public Async task<iviewcomponentresult> invokeasync (int maxpriority, bool isDone) { var Items = await Getitemsasync (maxpriority, IsDone); return View (items);} private task<list<todoitem>> getitemsasync (int maxpriority, bool isDone) { return db. Todo.where (x = X.isdone = = IsDone && x.priority <= maxpriority). Tolistasync (); } }}
Code considerations:
The
- view Component class can be included in the any folder in your project.
- because the class name prioritylist viewcomponent suffix viewcomponent ends, The runtime uses the string "Prioritylist" when referencing a view component in a view. I'll explain it in more detail later. The
-
[viewcomponent]
attribute can change the name used to reference the view component. For example, we can name the class XYZ
and apply the viewcomponent
property:
[ Viewcomponent (Name = "Prioritylist")] public class xyz: viewcomponent
-
[viewcomponent]
attribute tells the view component selector to use the name when locating the view associated with the component Prioritylist
, and use the string "Prioritylist" when referencing a component class from a view. I'll explain it in more detail later. The
- component uses dependency injection to make
DbContext
available.
-
InvokeAsync
is a public method that can be called from a view, and it can use any number of arguments. The
-
InvokeAsync
method returns a ToDo
collection that satisfies the isDone
and maxpriority
parameters.
Creating a View Component Razor view
- To create
Views/Shared/Components
a folder, this folder must be named components.
- Create the views/shared/components/prioritylist folder. This folder name must be the same as the name of the view component class, or the class name will be stripped of the suffix (if you follow the convention using a suffix in the class name
ViewComponent
). If you use this ViewComponent
attribute, the name needs to be the same as the attribute name.
Create a views/shared/components/prioritylist/default.cshtml razor View:
@model IEnumerable<ViewComponentSample.Models.TodoItem><h3>Priority Items</h3><ul> @foreach (var todo in Model) { <li>@todo.Name</li> }</ul>
The Razor View listsTodoItem
and display them. If the View componentInvokeAsync
method does not pass the name of the view (as in our example), the view name by convention is calledDefault。 Later in this article, I'll show you how to pass the name of the view. If the view component applies only to a specific controller, you can add it to a controller-specific folder (views/todo/components/prioritylist/default.cshtml)。
Call to div
include the view component in the element at the bottom of the view views/todo/index.cshtml file
<div > @await Component.InvokeAsync("PriorityList", new { maxPriority = 2, isDone = false }) </div>
@await Component.InvokeAsync
is the syntax to invoke the view component. The first parameter is the name of the component we want to invoke, followed by the arguments passed to the component. InvokeAsync
can contain any number of parameters.
Debug the application, display the Todo list and select items:
You can also call the view component directly in the controller:
public IActionResult IndexVC() { return ViewComponent("PriorityList", new { maxPriority = 3, isDone = false }); }
Specify the view name
Complex view components may need to specify a non-default view in some cases. The following code shows how to InvokeAsync
specify the PVC view from the method. Modifies PriorityListViewComponent
a method in a class InvokeAsync
.
public async task<iviewcomponentresult> InvokeAsync (int maxpriority, bool isDone) {string MyView = " Default "; //If asking for all completed tasks, render with the "PVC" view. if (maxpriority > 3 && isDone = true) {MyView = " PVC ";} var items = await getitemsasync (maxpriority, isDone); return View (MyView, items); }
Copy the views/shared/components/prioritylist/default.cshtml file to the name views/shared/components/prioritylist/ pvc.cshtml view file. Add a caption to indicate that you are using a PVC view.
@model IEnumerable<viewcomponentsample.models.todoitem>< span class= "kw" ><h2> PVC Named priority Component View</h2> <h4> @ViewBag. Prioritymessage</h4><ul> @foreach (var Todo in Model) {<li> @todo. Name</li>}</UL>
To modify the view views/todolist/index.cshtml:
@await Component.InvokeAsync("PriorityList", new { maxPriority = 4, isDone = true })
Run the application and verify that it is a PVC view.
If the display is not a PVC view, verify that you call the View component priority
parameter to 4 or higher.
Detecting View paths
Avoid string Magic
If you want to compile-time security, you can replace the hard-coded view component name with the class name. Create a view component that does not have a "viewcomponent" suffix:
Using MICROSOFT.ASPNETCORE.MVC;Using Microsoft.entityframeworkcore;Using System.Collections.Generic;Using System.Linq;Using System.Threading.Tasks;Using Viewcomponentsample.models;Namespaceviewcomponentsample.viewcomponents{PublicClassPrioritylist:viewcomponent {PrivateReadOnly Todocontext DB;public prioritylist (ToDoContext Context) {db = context;} public async Task< iviewcomponentresult> invokeasync ( int maxpriority, bool isDone) { var items = await getitemsasync (maxpriority, IsDone); return View (items);} private task<list<todoitem>> getitemsasync (int Maxpriority, bool isDone) {return db. Todo.where (x = X.isdone = = IsDone && x.priority <= maxpriority). Tolistasync (); } }}
Use using
the Add namespace to your Razor view file and use the nameof
operator:
@using ViewComponentSample.Models@using ViewComponentSample.ViewComponents@model IEnumerable<TodoItem><h2>ToDo nameof</h2><div> @await Component.InvokeAsync(nameof(PriorityList), new { maxPriority = 4, isDone = true })</div>
ASP. NET Core Razor View components