ASP.NET Core应用程序4:控制器和视图(一)
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>
本文来自博客园,作者:一纸年华,转载请注明原文链接:https://www.cnblogs.com/nullcodeworld/p/18154560
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!