当前位置:主页 > 软件编程 > .NET代码 >

ASP.NET Core中的Razor页面使用视图组件

时间:2022-11-15 09:46:32 | 栏目:.NET代码 | 点击:

视图组件简介

在新的ASP.NET Core MVC中,视图组件类似于局部视图,但它们更强大。视图组件不使用模型绑定,仅依赖于您在调用时提供的数据。

视图组件特性:

视图组件是在任何地方可重用的呈现逻辑,对于局部视图来说相对复杂,例如:

视图组件由两部分组成:类(通常继承自ViewComponent)和返回的结果(通常是视图)。像控制器一样,视图组件可以是POCO,但大多数开发人员都希望利用从ViewComponent继承的方法和属性。

创建视图组件

此部分包含创建视图组件的高级功能。在本文的后面,我们将详细介绍每一个步骤,并创建一个视图组件。

视图组件类

视图组件类可以通过以下任何方式来创建:

与控制器一样,视图组件必须是公共、非嵌套、非抽象类。视图组件名称是删除“ViewComponent”后缀的类名称,也可以使用ViewComponentAttribute.Name属性显式指定名称。

视图组件类特性:

视图组件方法

视图组件在InvokeAsync方法中定义逻辑,并返回IViewComponentResult类型。参数直接来自视图组件的调用,而不是模型绑定;视图组件从不直接处理请求;通常视图组件会初始化模型,并通过调用View方法将其传递给视图。总而言之,视图组件方法特性:

查找视图路径

运行时在以下路径中搜索视图:

视图组件的视图名称默认为Default,这意味着您的视图文件通常将命名为Default.cshtml。创建视图组件结果或调用View方法时,可以指定不同的视图名称。

我们建议您视图文件命名为Default.cshtml,并使用Views/Shared/Components/<view_component_name>/\ <view_name>.cshtml路径。此示例中使用的PriorityList视图组件,视图的路径是Views/Shared/Components/PriorityList/Default.cshtml。

调用视图组件

要使用视图组件,请在视图中调用以下代码:

    @Component.InvokeAsync("Name of view component", <anonymous type containing parameters>)

参数将被传递给InvokeAsync方法,在本文中编写的PriorityList视图组件在Views/Todo/Index.cshtml视图文件中调用。在下文中,使用两个参数调用InvokeAsync方法:

    @await Component.InvokeAsync("PriorityList", new { maxPriority = 4, isDone = true })

通过标签帮助器调用视图组件

对于ASP.NET Core 1.1及更高版本,您可以将视图组件作为标签帮助器(Tag Helper)进行调用:

    <vc:priority-list max-priority="2" is-done="false">
    </vc:priority-list>

标签帮助器将Pascal命名方式的类型和方法参数被转换成它们的小写短横线命名方式(lower kebab case)。调用视图组件的标签帮助器使用该元素,视图组件约定如下:

    <vc:[view-component-name]
      parameter1="parameter1 value"
      parameter2="parameter2 value">
    </vc:[view-component-name]>

注意:为了将视图组件作为标签帮助器,您必须使用@addTagHelper指令注册包含视图组件的程序集。例如,如果您的视图组件位于名为“MyWebApp”的程序集中,请将以下指令添加到_ViewImports.cshtml文件中:

@addTagHelper *, MyWebApp

您可以将视图组件作为标签帮助器注册到引用视图组件的任何文件。有关如何注册标签助手的更多信息,请参阅Managing Tag Helper Scope

本示例中使用的InvokeAsync方法:

    @await Component.InvokeAsync("PriorityList", new { maxPriority = 4, isDone = true })

标签帮助器标记:

    <vc:priority-list max-priority="2" is-done="false">
    </vc:priority-list>

在上面的示例中,PriorityList视图组件变为priority-list;视图组件的参数作为属性按小写短横线命名方式传递。

从控制器直接调用视图组件

视图组件通常在视图调用,但您也可以直接在控制器的方法中调用它们。虽然视图组件被定义为不能像控制器一样直接处理请求,但您可以轻松在控制器的Action方法中实现返回ViewComponentResult内容。

在下面的示例中,在控制器直接调用视图组件:

    public IActionResult IndexVC()
    {
        return ViewComponent("PriorityList", new { maxPriority = 3, isDone = false });
    }

演练:创建一个简单的视图组件

示例下载,构建和测试入门代码。这是一个简单的项目,Todo控制器显示 Todo 项目列表。

添加ViewComponent类

创建一个 ViewComponents 文件夹并添加以下PriorityListViewComponent类:

using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using ViewComponentSample.Models;

namespace ViewComponentSample.ViewComponents
{
    public class PriorityListViewComponent : ViewComponent
    {
        private readonly ToDoContext db;

        public PriorityListViewComponent(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();
        }
        
    }
}

代码注意事项:

创建视图组件Razor视图

@await Component.InvokeAsync是调用视图组件的语法。第一个参数是我们要调用组件的名称,随后是传递给组件的参数。InvokeAsync可以包含任意数量的参数。

调试应用程序,下图显示了ToDo列表和选择项:

您也可以直接在控制器中调用视图组件:

    public IActionResult IndexVC()
    {
        return ViewComponent("PriorityList", new { maxPriority = 3, isDone = false });
    }

指定视图名称

复杂视图组件可能需要在某些情况下指定非默认视图。以下代码显示了如何从InvokeAsync方法中指定“PVC”视图。修改PriorityListViewComponent类中的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);
    }

将 Views/Shared/Components/PriorityList/Default.cshtml 文件复制到名为 Views/Shared/Components/PriorityList/PVC.cshtml 视图文件。添加标题以表示正在使用的是PVC视图。

@model IEnumerable<ViewComponentSample.Models.TodoItem>

<h2> PVC Named Priority Component View</h2>
<h4>@ViewBag.PriorityMessage</h4>
<ul>
    @foreach (var todo in Model)
    {
        <li>@todo.Name</li>
    }
</ul>

修改视图 Views/TodoList/Index.cshtml:

    @await Component.InvokeAsync("PriorityList", new { maxPriority = 4, isDone = true })

运行应用程序并验证是PVC视图。

如果显示不是PVC视图,请验证您调用视图组件priority参数是否为4或更高的。

检测视图路径

避免字符串魔法

如果要编译时安全,则可以使用类名替换硬编码视图组件名称。创建没有以“ViewComponent”后缀的视图组件:

using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using ViewComponentSample.Models;

namespace ViewComponentSample.ViewComponents
{
    public class PriorityList : ViewComponent
    {
        private readonly 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();
        }
    }
}

使用using将命名空间添加到您的Razor视图文件,并使用nameof运算符:

@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>

其它资源

您可能感兴趣的文章:

相关文章