首页 > 编程语言 >ASP.NET Core应用程序7:使用视图组件

ASP.NET Core应用程序7:使用视图组件

时间:2024-05-19 11:52:41浏览次数:19  
标签:Core ASP 视图 cshtml 组件 Cities public Population

  视图组件是类,为支持分部视图或者在父视图中注入少量Html或Json数据提供了应用程序逻辑。

1 准备工作

  Models文件夹中添加City.cs类和CitiesData类,为CitiesData添加服务。

    public class City
    {
        public string Name { get; set; }
        public string Country { get; set; }
        public int Population { get; set; }
    }
    public class CitiesData
    {
        private List<City> cities = new List<City>
        {
            new City { Name = "London", Country = "UK", Population = 8539000},
            new City { Name = "New York", Country = "USA", Population = 8406000 },
            new City { Name = "San Jose", Country = "USA", Population = 998537 },
            new City { Name = "Paris", Country = "France", Population = 2244000 }
        };

        public IEnumerable<City> Cities => cities;

        public void AddCity(City newCity)
        {
            cities.Add(newCity);
        }
    }
services.AddSingleton<CitiesData>();

  在Pages文件夹下添加Cities.cshtml的Razor Pages。

@page
@inject CitiesData Data

<div class="m-2">
    <table class="table table-sm table-striped table-bordered">
        <tbody>
            @foreach (var item in Data.Cities)
            {
                <tr>
                    <td>@item.Name</td>
                    <td>@item.Country</td>
                    <td>@item.Population</td>
                </tr>
            }
        </tbody>
    </table>
</div>

  浏览器请求http://localhost:5000/cities。

2 理解视图组件

  可将视图组件想象成一个专门的操作页面,但它只用于为分部视图提供数据,不能接收http请求,而且提供的内容将总是被包含到父视图中。

3 创建和使用视图组件

  视图组件是名称以ViewComponent结束,并定义了Invoke或InvokeAsync方法的类,派生自ViewComponent基类,或者使用ViewComponent特性装饰的类。
  在项目的任何位置都可以定义视图组件,但约定做法是把它们放到名为Components的文件夹中。

  创建Components文件夹,添加CitySummary.cs。

    public class CitySummary : ViewComponent
    {
        private CitiesData data;

        public CitySummary(CitiesData cdata)
        {
            data = cdata;
        }
        public string Invoke()
        {
            return $"{data.Cities.Count()}座城市," +
                $"{data.Cities.Sum(a => a.Population)}人";
        }
    }

(1)应用视图组件
  使用添加到视图和Pazor Pages生成的C#类的Component属性,该属性返回的对象实现了IViewComponentHelper接口,接口提供了InvokeAsync方法。

  如下Views/Home/Index.cshtml文件中应用视图组件,在使用时将视图组件类名作为实参。把名称空间添加到Views/_ViewImports.cshtml中。

@section Summary {
    <div class="bg-info text-white m-2 p-2">
        @await Component.InvokeAsync("CitySummary")
    </div>
}
@using MyWebApp.Components

  浏览器请求http://localhost:5000/home/index/1。
(2)使用标签助手应用视图组件
  在Views/_ViewImports.cshtml中添加配置标签助手。修改Views/Home/Index.cshtml文件中应用视图组件。

@addTagHelper *,MyWebApp
@section Summary {
    <div class="bg-info text-white m-2 p-2"
       <vc:city-summary />
    </div>
}

4 理解视图组件结果

  视图组件通过让Invoke方法返回一个实现了IViewComponentResult接口的对象,可以返回更复杂的效果。3个内置类实现了此接口,这些类以及ViewComponent基类提供了创建的方法。

  如下三个内置类:

  • ViewViewComponentResult:用于手动指定一个Razor视图,包括可选视图模型数据。使用View方法可创建其实例。
  • ContentViewComponentResult:用于指定文本结果,该文本结果将被安全编码。使用Content方法可创建其实例。
  • HtmlContentViewComponentResult:用于指定一个Html片段,该片段不会被编码,直接包含到html中。没有ViewComponent方法可创建其实例。

4.1 返回一个分部视图

  最有用的响应是ViewViewComponentResult,它告诉Razor渲染一个分部视图,并在父视图中包含渲染结果。ViewComponent基类提供了View方法用于创建ViewViewComponentResult对像。
  在Models文件夹下添加CityViewModel.cs视图模型类。修改CitySummary视图组件的Invoke方法。

    public class CityViewModel
    {
        public int Cities { get; set; }
        public int Population { get; set; }
    }
        public IViewComponentResult Invoke()
        {
            var model = new CityViewModel()
            {
                Cities = data.Cities.Count(),
                Population = data.Cities.Sum(x => x.Population),
            };
            return View(model);
        }

  使用浏览器请求http://localhost:5000/home/index/1,因为还没有可供视图组件使用的视图所以会报错,但可以看出使用该视图组件时都搜索了哪些位置。

InvalidOperationException: The view 'Components/CitySummary/Default' 
    was not found. The following locations were searched:
/Views/Home/Components/CitySummary/Default.cshtml
/Views/Shared/Components/CitySummary/Default.cshtml
/Pages/Shared/Components/CitySummary/Default.cshtml

  创建Views/Shared/Components/CitySummary文件夹,添加Default.cshtml的Razor视图。

@model CityViewModel

<table class="table table-sm table-bordered text-white [email protected]">
    <thead>
        <tr><th colspan="2">Cities Summary</th></tr>
    </thead>
    <tbody>
        <tr>
            <td>Cities:</td>
            <td class="text-right">
                @Model.Cities
            </td>
        </tr>
        <tr>
            <td>Population:</td>
            <td class="text-right">
                @Model.Population.ToString("#,###")
            </td>
        </tr>
    </tbody>
</table>

  使用浏览器请求http://localhost:5000/home/index/1和http://localhost:5000/data。

4.2 返回Html片段

  ContentViewComponentResult类用于不使用视图情况下,在父视图中包含Html片段。使用从ViewComponent基类继承的Content方法,可以创建其实例。
修改如下。

        public IViewComponentResult Invoke()
        {
            return Content("这是一个<h3><i>string</i></h3>");
        }

  使用浏览器请求http://localhost:5000/data,会看到返回的结果并没有解释为html元素,Content方法是编码的。要想把<h3><i>标签转换成html显示,则必须创建HtmlContentViewComponentResult对象,为其构造函数提供一个HtmlString对象。

using Microsoft.AspNetCore.Mvc.ViewComponents;
using Microsoft.AspNetCore.Html;
        public IViewComponentResult Invoke()
        {
            var htmlString = new HtmlString("这是一个<h3><i>string</i></h3>");
            return new HtmlContentViewComponentResult(htmlString);
        }

5 获取上下文数据

  通过ViewComponent基类定义的一些属性,将关于当前请求和父视图的详细信息提供给视图组件。
  在Component/CitySummary.cs中使用请求数据。

        public string Invoke()
        {
            if (RouteData.Values["controller"] != null)
            {
                return "controller请求";
            }
            else
            {
                return "Razor Pages请求";
            }
        }

5.1 使用实参提供父视图的上下文

  父视图能够为视图组件提供额外的上下文数据,包括应该生成的内容的数据。

        public IViewComponentResult Invoke(string themeName)
        {
            ViewBag.Theme = themeName;

            return View(new CityViewModel
            {
                Cities = data.Cities.Count(),
                Population = data.Cities.Sum(c => c.Population)
            });
        }

  在Views/Shared/Components/CitySummar/Default.cshtml文件中设置内容样式。

<table class="table table-sm table-bordered text-white [email protected]">
......

  这时必须为视图组件的Invoke方法提供参数值。修改Views/Home/Index.cshtml。

<vc:city-summary theme-name="secondary" />

  修改Pages/Data.cshtml。

<vc:city-summary theme-name="danger" />  

  也可以使用组件助手提供值。

@await Component.InvokeAsync("CitySummary",new { themmeName = "danger"})

5.2 创建异步视图组件

  可通过定义一个返回Task的InvokeAsync方法,创建异步视图组件。

  在Components文件夹下添加PageSize.cs的类文件。

    public class PageSize : ViewComponent
    {
        public async Task<IViewComponentResult> InvokeAsync()
        {
            HttpClient client = new HttpClient();
            HttpResponseMessage response
                = await client.GetAsync("http://apress.com");
            return View(response.Content.Headers.ContentLength);
        }
    }

  创建Views/Shared/Components/文件夹,添加Default.cshtml。

@model long
<div class="m-1 p-1 bg-light text-dark">Page size: @Model</div>

  在Views/Home/Index.cshtml中使用异步组件。

<vc:page-size />

6 创建视图组件类

  视图组件是提供功能的一个汇总或快照,由控制器或Razor Pages来深入处理功能。

  在Pages文件夹Cities.cshtml.cs中添加如下。

    [ViewComponent(Name = "CitiesPageHybrid")]
    public class CitiesModel : PageModel
    {
        public CitiesModel(CitiesData cdata)
        {
            Data = cdata;
        }

        public CitiesData Data { get; set; }

        [ViewComponentContext]
        public ViewComponentContext Context { get; set; }

        public IViewComponentResult Invoke()
        {
            return new ViewViewComponentResult()
            {
                ViewData = new ViewDataDictionary<CityViewModel>(
                    Context.ViewData,
                    new CityViewModel
                    {
                        Cities = Data.Cities.Count(),
                        Population = Data.Cities.Sum(c => c.Population)
                    })
            };
        }
    }

  这个页面模型使用了ViewComponent从而允许它用作一个视图组件,Name参数制定了名称。因为此类不能再继承ViewComponent基类,所以使用ViewComponentContext特性来装饰ViewComponentContext属性,这表明在调用Invoke方法之前,应该把值赋给Context.ViewData,View方法不可用,所以创建了ViewViewComponentResult,它依赖于通过被装饰的属性收到上下文对象。

  在Cities.cshtml中更新视图。

@page
@model MyWebApp.Pages.CitiesModel

<div class="m-2">
    <table class="table table-sm table-striped table-bordered">
        <tbody>
            @foreach (var item in Model.Data.Cities)
            {
                <tr>
                    <td>@item.Name</td>
                    <td>@item.Country</td>
                    <td>@item.Population</td>
                </tr>
            }
        </tbody>
    </table>
</div>

  为创建混合视图组件的视图,需创建Pages/Shared/Components/CitiesPageHybrid文件夹,添加Default.cshtml。

@model CityViewModel

<table class="table table-sm table-bordered text-white bg-dark">
    <thead><tr><th colspan="2">Hybrid Page Summary</th></tr></thead>
    <tbody>
        <tr>
            <td>Cities:</td>
            <td class="text-right">@Model.Cities</td>
        </tr>
        <tr>
            <td>Population:</td>
            <td class="text-right">
                @Model.Population.ToString("#,###")
            </td>
        </tr>
    </tbody>
</table>

  在Pages/Data.cshtml中使用组件。

<div class="bg-info text-white m-2 p-2">
    <vc:cities-page-hybrid />
</div>

  请求http://localhost:5000/cities和http://localhost:5000/data。

标签:Core,ASP,视图,cshtml,组件,Cities,public,Population
From: https://www.cnblogs.com/nullcodeworld/p/18200184

相关文章

  • 在 ASP.NET Core 中使用托管服务实现后台任务
    在ASP.NETCore中,后台任务作为托管服务实现。托管服务是一个类,具有实现 IHostedService 接口的后台任务逻辑。本文提供了三个托管服务示例:在计时器上运行的后台任务。激活有作用域的服务的托管服务。有作用域的服务可使用依赖项注入(DI)。按顺序运行的已排队后台任务......
  • net core jwt的基本原理和实现
    NETCore中的JWT(JSONWebToken)基本原理和实现主要涉及到身份验证和授权的过程。以下是对JWT原理和实现的简要概述:JWT原理JWT是一种开放标准(RFC7519),它定义了一种紧凑的、自包含的方式,用于作为JSON对象在各方之间安全地传输信息。这些信息可以被验证和信任,因为它们是数......
  • 基于Azure DevOps 的 CICD 项目部署(.Net Core)
    基于AzureDevOps的CICD项目部署(.NetCore)使用微软的来进行CICD链接:https://dev.azure.com创建新项目创建项目名称选择仓库地址选择空模板创建代理池按照以下步骤把代理部署到服务器上![连接你的服务器创建新的文件夹mkdirmyange......
  • 记一次asp.net 8 服务器爆满的解决过程
    1.描述一下服务器配置:一台2c4g的centos,做api接口反代一台8c16g的windows2019作为实际服务器,跑了iis,sqlserver,mongodb,redis2.业务描述  2.0 服务器分为两个站点:importapi:用于处理数据导入,,,webapi:用于处理对用户端的数据查询  2.1从数据源采集数据后,......
  • Asp-Net-Core开发笔记:使用ActionFilterAttribute实现非侵入式的参数校验
    前言在现代应用开发中,确保API的安全性和可靠性至关重要。面向切面编程(AOP)通过将横切关注点(如验证、日志记录、异常处理)与核心业务逻辑分离,极大地提升了代码的模块化和可维护性。在ASP.NETCore中,利用ActionFilterAttribute可以方便地实现AOP的理念,能够以简洁、高效的方式进行自......
  • (报错)ROS2:WARNING:colcon.colcon_core.package_selection:ignoring unknown package
    在使用colcon编译时,如果直接对所有包编译colconbuild则不会有问题,但是针对单独某个包编译colconbuild--packages-select<pkg>则报错WARNING:colcon.colcon_core.package_selection:ignoringunknownpackagegg了一下找到了问题参考:https://unix.stackexchange.co......
  • 内网渗透 Metasploit(MSF)基础使用
    免责申明以下内容仅供学习使用,非法使用造成的问题由使用人承担攻击思路漏洞探测(信息收集)<-fsacn,namp|漏洞利用<-工具(msf等)|获取服务器权限MSF使用Metasploit就是一个安全漏洞检测工具。它的全称叫做TheMetasploitFramework,简称MSF。MSF主要用于攻击非web端口1......
  • Dapr 与 .NET Aspire
    Dapr与.NETAspire Dapr与.NETAspire结合使用获得无与伦比的本地开发体验 Dapr 提供了一组构建块,用于抽象分布式系统中常用的概念。这包括服务、缓存、工作流、复原能力、机密管理等之间的安全同步和异步通信。不必自己实现这些功能,可以消除样板,降低复杂性,并允许您......
  • ASP.NET Core Web中使用AutoMapper进行对象映射
    前言在日常开发中,我们常常需要将一个对象映射到另一个对象,这个过程中可能需要编写大量的重复性代码,如果每次都手动编写,不仅会影响开发效率,而且当项目越来越复杂、庞大的时候还容易出现错误。为了解决这个问题,对象映射库就随之而出了,这些库可以自动完成对象之间的映射,从而减少大量......
  • Dapr 与 .NET Aspire 结合使用获得无与伦比的本地开发体验
    Dapr提供了一组构建块,用于抽象分布式系统中常用的概念。这包括服务、缓存、工作流、复原能力、机密管理等之间的安全同步和异步通信。不必自己实现这些功能,可以消除样板,降低复杂性,并允许您专注于开发业务功能。在您的时间有限并且您只想进行实验的情况下,在Dapr初始设置上花费大量......