当前位置: 代码网 > it编程>编程语言>Asp.net > ASP.NET Core中的Razor页面使用视图组件

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

2024年05月18日 Asp.net 我要评论
视图组件简介在新的asp.net core mvc中,视图组件类似于局部视图,但它们更强大。视图组件不使用模型绑定,仅依赖于您在调用时提供的数据。视图组件特性:呈现页面响应的某一部分而不是整个响应包括

视图组件简介

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

视图组件特性:

  • 呈现页面响应的某一部分而不是整个响应
  • 包括在控制器和视图之间发现的关注分离和可测试性优势
  • 可以具有参数和业务逻辑
  • 通常在页面布局中调用

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

  • 动态导航菜单
  • 标签云(查询数据库)
  • 登录面板
  • 购物车
  • 最近发表的文章
  • 典型博客上的侧边栏内容
  • 将在每个页面上呈现的登录面板,并显示要注销或登录的链接,具体取决于用户的登录状态

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

创建视图组件

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

视图组件类

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

  • 继承自 viewcomponent 类
  • 使用[viewcomponent]特性来标记一个类,或者继承自具有[viewcomponent]特性的类
  • 创建类的名称以 viewcomponent 后缀结尾

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

视图组件类特性:

  • 完美支持构造函数依赖注入
  • 不参与控制器生命周期,这意味着您不能在视图组件中使用过滤器

视图组件方法

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

  • 定义一个返回iviewcomponentresultinvokeasync方法
  • 通常会初始化一个模型,并通过调用viewcomponent类型的view方法将其传递给视图
  • 参数来自调用方法,而不是http请求,没有模型绑定
  • 不能直接通过http请求访问,它们通常在视图中通过代码调用;视图组件永远不会处理请求
  • 在方法签名上重载,而不是当前http请求的任何详细信息

查找视图路径

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

  • views/<controller_name>/components/<view_component_name>/<view_name>
  • views/shared/components/<view_component_name>/<view_name>

视图组件的视图名称默认为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();
        }
        
    }
}

代码注意事项:

  • 视图组件类可以包含在项目中的任何文件夹中。
  • 因为类名称prioritylistviewcomponent以后缀viewcomponent结尾,运行时在视图中引用视图组件时使用字符串“prioritylist”。稍后我会详细解释一下。
  • [viewcomponent]特性可以更改用于引用视图组件的名称。例如,我们可以该类命名为xyz并应用该viewcomponent属性:
        [viewcomponent(name = "prioritylist")]
        public class xyz : viewcomponent
  • [viewcomponent]特性告诉视图组件选择器在查找与组件关联的视图时使用名称prioritylist,并在从视图引用组件类时使用字符串“prioritylist”。稍后我会详细解释一下。
  • 组件使用依赖注入来使dbcontext可用。
  • invokeasync 是一个可以从视图中调用的公开方法,它可以使用任意数量的参数。
  • invokeasync方法返回满足isdonemaxpriority参数的todo集合。

创建视图组件razor视图

  • 创建views/shared/components文件夹,此文件夹必须命名为 components。
  • 创建 views/shared/components/prioritylist 文件夹。此文件夹名称必须与视图组件类的名称一致,或者类名称去掉后缀(如果遵循约定在类名称中使用viewcomponent后缀)。如果您使用该viewcomponent特性,则名称需要与特性名称一致。
  • 创建一个views/shared/components/prioritylist/default.cshtml razor视图:
    @model ienumerable<viewcomponentsample.models.todoitem>
    
    <h3>priority items</h3>
    <ul>
        @foreach (var todo in model)
        {
            <li>@todo.name</li>
        }
    </ul>
    razor视图会列出todoitem并显示它们。如果视图组件invokeasync方法未传递视图的名称(如我们的示例中),则按照约定视图名称为 default。在本文的后面,我将向您展示如何传递视图的名称。如果视图组件只适用于特定控制器,则可以将其添加到控制器特定的文件夹(views/todo/components/prioritylist/default.cshtml)。
  • 在视图 views/todo/index.cshtml 文件底部的div元素中包含视图组件的调用
        <div >
            @await component.invokeasync("prioritylist", new { maxpriority = 2, isdone = false })
        </div>

@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或更高的。

检测视图路径

  • priority参数更改为三个或更小,返回默认视图。
  • 临时将 views/todo/components/prioritylist/default.cshtml 重命名为 1default.cshtml。
  • 调试应用程序,您将收到以下错误:

    an unhandled exception occurred while processing the request.
    invalidoperationexception: the view 'components/prioritylist/default' was not found. the following locations were searched:
    /views/todo/components/prioritylist/default.cshtml
    /views/shared/components/prioritylist/default.cshtml
    ensuresuccessful

  • 将视图 views/todo/components/prioritylist/1default.cshtml 复制到 views/shared/components/prioritylist/default.cshtml 。
  • 在 shared 的todo视图组件视图中添加一些标记,以表示视图来自 shared 文件夹。
  • 测试 shared 组件视图。

避免字符串魔法

如果要编译时安全,则可以使用类名替换硬编码视图组件名称。创建没有以“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>

其它资源

到此这篇关于asp.net core中的razor页面使用视图组件的文章就介绍到这了。希望对大家的学习有所帮助,也希望大家多多支持代码网。

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2025  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com