首页 > 其他分享 >第21章 控制器和视图(一)

第21章 控制器和视图(一)

时间:2024-04-24 10:58:45浏览次数:15  
标签:Razor 控制器 21 C# 视图 Model 表达式 Name

1 准备工作

添加包:dotnet add package Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation --version 3.1.1

2 开始使用视图

2.1 配置应用程序

HTML响应是使用视图创建的,视图则是混合了HTML元素和C#表达式的文件。
配置Startup来启用HTML响应。

services.AddControllersWithViews().AddRazorRuntimeCompilation();

之前使用AddController方法来启用MVC框架,但它只支持Web服务控制器。这里我们启用AddControllersWithViews方法来支持视图。使用AddRazorRuntimeCompilation方法是为了启用安装包所提供的功能,方便开发过程中使用视图。

app.UseEndpoints(endpoints =>
{
    endpoints.MapControllers();
    endpoints.MapControllerRoute("Default", "{controller=Home}/{action=Index}/{id?}");
});

在端点路由配置中添加了MapControllerRoute方法,默认页面的路由。

2.2 创建html控制器

    public class HomeController : Controller
    {
        private DataContext _context;

        public HomeController(DataContext ctx)
        {
            _context = ctx;
        }
        public async Task<IActionResult> Index(long id =1)
        {
            return View(await _context.Products.FindAsync(1));
        }
    }

html控制器基类是Controller,它派生自Web服务控制器ControllerBase,并提供用于视图的方法。

(1)理解约定式路由

html控制器依赖于约定式路由,而不是Route特性。约定式路由指的是使用控制器名称和操作方法名称来配置路由系统。

endpoints.MapControllerRoute("Default", "{controller=Home}/{action=Index}/{id?}");

这条语句路由分三段,前面两个指代控制器和操作方法名称,而第三段允许收到一个名为id的参数。对于不包含所有片段的URL默认值将选择Home控制器的Index方法。这个是常用配置,也可以简写为下面这样。

endpoints.MapDefaultControllerRoute();

(2)理解Razor视图约定

当操作方法调用View方法时,将创建一个ViewResult,告诉MVC框架使用默认约定来寻找视图。Razor视图引擎将寻找一个与操作方法同名、且带有cshtml文件扩展名的视图。视图保存在Views文件中,按照关联的控制器进行分组。
因为操作方法时由Home控制器定义,所以首先搜索Views/Home文件夹。如果没有找到Index.cshtml,就检查Views/Shared文件夹,这里包含控制器之间的共享视图。

2.3 创建Razor视图

在Views/Home目录下创建Index.cshtml视图。

<!DOCTYPE html>
<html>
<head>
    <link href="/lib/twitter-bootstrap/css/bootstrap.min.css" rel="stylesheet" />
</head>
<body>
    <h6 class="bg-primary text-white text-center m-2 p-2">Product Table</h6>
    <div class="m-2">
        <table class="table table-sm table-striped table-bordered">
            <tbody>
                <tr><th>Name</th><td>@Model.Name</td></tr>
                <tr><th>Price</th><td>@Model.Price.ToString("c")</td></tr>
                <tr><th>Category ID</th><td>@Model.CategoryId</td></tr>
            </tbody>
        </table>
    </div>
</body>
</html>

2.4 通过名称选择视图

通过View方法提供一个名称Watersports作为参数选择视图,同时创建Watersports.cshtml。

        public async Task<IActionResult> Index(long id = 1)
        {
            var model = await _context.Products.FindAsync(id);
            if (model.CategoryId == 1)
            {
                return View("Watersports", model);
            }
            return View(model);
        }

使用共享视图

在Views/Shared文件夹中添加一个名为Common.cshtml的Razor视图文件。

<!DOCTYPE html>
<html>
<head>
    <link href="/lib/twitter-bootstrap/css/bootstrap.min.css" rel="stylesheet" />
</head>
<body>
    <h6 class="bg-secondary text-white text-center m-2 p-2">Shared View</h6>
</body>
</html>

在HomeController添加一个操作方法,它依赖于使用方法名称作为视图名称。

        public IActionResult Common()
        {
            return View();
        }

添加一个SecondController,它的一个操作方法返回View,参数使用Common。

    public class SecondController : Controller
    {
        public IActionResult Index()
        {
            return View("Common");
        }
    }

可以看到结果,http://localhost:5000/home/common和http://localhost:5000/second都显示的是Common视图。
注意:也可以不用视图引擎选择文件,而自己指定相对路径的完整路径来选择某个视图。

return View("/Views/Shared/Common.cshtml");

3 使用Razor视图

Razor视图包含html表达式和C#表达式。混杂在html元素中,用@字符表示。Razor视图将被转换为C#类,它继承自RazorPage类,像其他C#类一样被编译。
可以通过obj/Debug/netcoreapp3.1/Razor/Views文件夹下内容,看到生成的视图类。
cshtml文件中的一个片段,会被 ExecuteAsync方法转换为一系列C#语句,再把html片段和表达式的计算结果写入响应得到最终html。

<tr><th>Name</th><td>@Model.Name</td></tr>
WriteLiteral("<tr><th>Name</th><td>");
Write(Model.Name);
WriteLiteral("</td></tr>");

设置视图模型类型

为Watersports.cshtml文件生成的类派生自RazorPage<T>,但是Razor不知道操作方法为视图模型使用什么类型,所以选择了RazorPage<dynamic>作为泛型类型实参。这样即便写一个不存在的属性编译也不会报错,直到运行时才会报错。
为在开发中检查表达式,可使用model关键字指定Model对象类型。这样当生成C#类时将使用RazorPage<Product>这样作为泛型实参。

@model MyWebApp.Models.Product
<!DOCTYPE html>
......

使用视图导入文件

通过在项目中添加视图导入文件,能够指定在一组名称空间中搜索类型。视图导入文件的名称为_ViewImports.cshtml,包含在Views文件夹中。

@using MyWebApp.Models

通过使用@using表达式,并在后面加上名称空间,可以指定哪些名称空间中搜索Razor视图中使用的类,该名称空间包含Watersports.cshtml,就不用加MyWebApp.Models了。

@model Product
<!DOCTYPE html>
......

4 理解Razor语法

4.1 理解指令

指令是向Razor视图引擎发送命令的表达式。

  • @model:指定视图模型的类型;
  • @using:导入名称空间
  • @page:指示Razor Page。
  • @section:指示布局节。
  • @addTagHelper:在视图中添加标签助手。
  • @namespace:设置从视图生成C#类的名称空间。
  • @functions:向从视图生成的C#类添加属性和方法,常用于Razor Page中。
  • @attribute:向从视图生成的C#类添加特性。
  • @implements:声明从视图生成的C#类继承某个接口,或派生自某个基类。
  • @inherits:设置了从视图生成的C#类的基类。
  • @inject:使视图能通过依赖注入直接访问某个服务。

4.2 理解内容表达式

Razor内容表达式生成的内容将包含在视图生成的输出中。

  • @<expression>:这是基本的Razor表达式,其计算结果将被插入响应中。
  • @if@switch:条件表达式。
  • @foreach:为序列中每个元素生成内容。
  • @{...}:定义一个代码块。
  • @::指示没有包含在html中的内容。
  • @try:用于捕获异常。
  • @await:用于执行异步操作,结果将被插入响应中。

4.3 设置元素内容

视图可包含更复杂表达式,但要求把这些表达式放到括号内,以便区分代码和静态内容。

<tr><th>Tax</th><td>@Model.Price * 0.2m</td></tr>
<tr><th>Tax</th><td>@(Model.Price * 0.2m)</td></tr>

4.4 设置特性值

表达式可用于设置元素特性的值。

<table class="table table-sm table-striped table-bordered" data-id="@Model.ProductId">

4.5 使用条件表达式

使用@if。

@if (Model.Price > 200)
{
    <tr><th>Name</th><td>Luxury @Model.Name</td></tr>
}
else
{
    <tr><th>Name</th><td>Basic @Model.Name</td></tr>
}

使用@switch,@:前缀来处理未包含在html元素中的字面量值

<tr>
    <th>Name</th>
    <td>
        @switch (Model.Name)
        {
            case "Kayak":
                @:Small Boat       
                break;
            case "Lifejacket":
                @:Flotation Aid
                break;
            default:
                @Model.Name
                break;
        }
    </td>
</tr>

4.6 枚举序列

HomeController中添加List方法。

public IActionResult List()
{
    return View(_context.Products); 
}

添加List.cshtml.

@model IEnumerable<Product>
<!DOCTYPE html>
<html>
<head>
    <link href="/lib/twitter-bootstrap/css/bootstrap.min.css" rel="stylesheet" />
</head>
<body>
    <h6 class="bg-secondary text-white text-center m-2 p-2">Products</h6>
    <div class="m-2">
        <table class="table table-sm table-striped table-bordered">
            <thead>
                <tr><th>Name</th><th>Price</th><th></th></tr>
            </thead>
            <tbody>
                @foreach (Product p in Model)
                {
                    <tr>
                        <td>@p.Name</td>
                        <td>@p.Price</td>
                    </tr>
                }
            </tbody>
        </table>
    </div>
</body>
</html>

4.7 使用Razor代码块

代码块是一段C#代码,它不生成内容,但能够为那些生成内容的表达式提供支持。

@{
    decimal average = Model.Average(a => a.Price);
}
<td>平均值的@((p.Price / average * 100).ToString("F1"))% </td>

标签:Razor,控制器,21,C#,视图,Model,表达式,Name
From: https://www.cnblogs.com/nullcodeworld/p/18154560

相关文章

  • 第22章 控制器和视图(二)
    1准备工作在Startup中启用会话配置。services.AddDistributedMemoryCache();services.AddSession(options=>{options.Cookie.IsEssential=true;});app.UseSession();2使用ViewBag操作方法使用视图模型提供数据,但有时还需额外信息。可以使用ViewBag提供额外数......
  • 鸿蒙HarmonyOS实战-ArkUI动画(放大缩小视图)
    ......
  • CVE-2021-34371 Neo4j-Shell 漏洞复现
    前言偶然的一次机会遇到了这个漏洞,决定在vulhub复现下,重要提醒:本次复现所需要的环境为java8kali更换java环境戳这里漏洞描述Neo4j到3.4.18(启用shell服务器)公开了一个RMI服务,该服务可以任意反序列化Java对象,例如通过setSessionVariable。攻击者可滥用此漏洞进行远程......
  • day21-阶段总结
    1.知识点补充1.1并发编程&网络编程从知识点的角度来看,本身两者其实没有什么关系:网络编程,基于网络基础知识、socket模块实现网络的数据传输。并发编程,基于多进程、多线程等来提升程序的执行效率。但是,在很多“框架”的内部其实会让两者结合起来,使用多进程、多线......
  • DRF之视图组件
    【四】视图组件图源:drf(详细)_51CTO博客_什么是drf【1】两个视图基类【1.1】APIView请在【View】中查看详细【1.2】GenericAPIView【1.2.1】常用类属性基本设置:以下属性控制着基本视图的行为。queryset用于从视图返回对象的查询结果集。通常,你必须设置此......
  • 4+1 视图建模及架构设计工程实践
    ​占春良:碧桂园服务技术专家,项目架构师,前阿里资深软件工程师,12年技术开发经验。​01前言架构设计建模的目的是通过统一的UML语言,完成业务的梳理,并对业务系统进行合理的组织(分层、分模块),以提高系统的可扩展性、可重用性、可移植性、易理解性和易测试性,从而达到一个高质量属性的......
  • 2024年4月21日直播源分享
    从今天起,服务器正式更换,有效期三年。原有服务器当前已到期,将无法使用,请大家及时更换到最新的接口地址。直播源获取方式:关注公众号轻笺,发送消息最新,即可获取。本次更新内容如下:新增央视卫视通用线路优化广州频道在移动网络下的播放问题新增了深圳各个频道,当前仅支持电......
  • 上周热点回顾(4.15-4.21)
    热点随笔:· 博客园商业化之路-开篇:开源的脚步,商业化的出路 (博客园团队)· 经过腾讯云这波故障,我想表扬的点和学到的职场保命法则。 (why技术)· 一周涨15kStar的开源项目「GitHub热点速览」 (削微寒)· 面试官:为什么忘记密码要重置而不是告诉你原密码? (JavaGuide)·......
  • 【2024-04-21】连岳摘抄
    23:59每一种事物都在它的时间里拥有自己的时间。树木在冬天不会开花春天的田野,看不到白色的冰寒。                                                 ——佩索阿聪明,......
  • 如何基于Django中的WebSockets和异步视图来实现实时通信功能
    本文分享自华为云社区《结合Django中的WebSockets和异步视图实现实时通信功能的完整指南》,作者:柠檬味拥抱。在现代Web应用程序中,实时通信已经成为了必不可少的功能之一。无论是在线聊天、实时数据更新还是实时通知,都需要通过实时通信技术来实现。Django作为一个强大的Web框架,提......