ASP.NET Core应用程序5:控制器和视图(二)
1 准备工作
在Startup中启用会话配置。
services.AddDistributedMemoryCache(); services.AddSession(options => { options.Cookie.IsEssential = true; });
app.UseSession();
2 使用ViewBag
操作方法使用视图模型提供数据,但有时还需额外信息。可以使用ViewBag提供额外数据。
public async Task<IActionResult> Index(long id = 1) { ViewBag.AveragePrice = await _context.Products.AverageAsync(a=>a.Price); var model = await _context.Products.FindAsync(id); return View(model); }
ViewBag属性是从Controller基类继承来的,它返回一个dynameic对象。可以在视图中访问操作方法赋给ViewBag的值。
<tr> <th>Price</th> <td> @Model.Price.ToString("c") 平均值的@((Model.Price / ViewBag.AveragePrice * 100).ToString("F2"))% </td> </tr>
3 使用TempData
添加CubedController。
public class CubedController : Controller { public IActionResult Index() { return View("Cubed"); } public IActionResult Cube(double num) { TempData["value"] = num.ToString(); TempData["result"] = Math.Pow(num, 3).ToString(); return RedirectToAction(nameof(Index)); } }
定义了一个Index方法返回Cubed视图。Cube方法执行计算,将结果值保存到TempData中,该属性用来存储键值对。当把值存储为临时数据后,Cube方法重定向到Index方法。
在Views/Shard文件夹下添加Cubed.cshtml。
<!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">Cubed</h6> <form method="get" action="/cubed/cube" class="m-2"> <div class="form-group"> <label>Value</label> <input name="num" class="form-control" value="@(TempData["value"])" /> </div> <button class="btn btn-primary" type="submit">Submit</button> </form> @if (TempData["result"] != null) { <div class="bg-info text-white m-2 p-2"> @TempData["value"]的立方是 @TempData["result"] </div> } </body> </html>
在本例中使用临时数据设置了一个input元素内容,并显示一个结果摘要。读取一个临时数据并不会立刻删除,同一个视图中就可以重复读取值,只有当处理请求完成后,才会删除标记的值。
4 使用布局
示例视图包含重复元素,为了避免这种重复,Razor支持布局,可通过将公共内容放到一个文件中供视图使用。
通常把布局放到Views/Shared文件夹下。添加_Layout.cshtml。
<!DOCTYPE html> <html> <head> <link href="/lib/twitter-bootstrap/css/bootstrap.min.css" rel="stylesheet" /> </head> <body> <div> <h6 class="bg-primary text-white text-center m-2 p-2">共享视图</h6> @RenderBody() </div> </body> </html>
布局包含了供多个视图使用的公共内容。每个视图所特有的内容是通过@RenderBody()方法插入响应,RazorPage
在Views/Home/Index.cshtml中使用布局。
@model Product @{ Layout = "_Layout"; } <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") (平均值的@((Model.Price / ViewBag.AveragePrice * 100).ToString("F2"))%) </td> </tr> <tr><th>Category ID</th><td>@Model.CategoryId</td></tr> <tr><th>SupplierId</th><td>@Model.SupplierId</td></tr> </tbody> </table> </div>
4.1 使用ViewBag配置布局
视图可为布局提供数据值,从而允许定制视图提供的公共内容。ViewBag属性是在选择布局的代码块中定义的。
@{ Layout = "_Layout"; ViewBag.Title = "产品表"; }
在_Layout.cshtml中用ViewBag。
<!DOCTYPE html> <html> <head> <title>@ViewBag.Title</title> <link href="/lib/twitter-bootstrap/css/bootstrap.min.css" rel="stylesheet" /> </head> <body> <div> <h6 class="bg-primary text-white text-center m-2 p-2"> @(ViewBag.Title ?? "共享视图") </h6> @RenderBody() </div> </body> </html>
4.2 使用ViewStart文件
不必在每个视图中设置Layout属性,而是可以在项目中添加一个ViewStart文件,用来提供默认的Layout值。在Views文件下添加_ViewStart.cshtml。
@{ Layout = "_Layout"; }
从Views/Shared文件夹的Common.cshtml文件中删除布局包含内容。
<h6 class="bg-secondary text-white text-center m-2 p-2">共享视图</h6>
4.3 覆盖默认布局
在两种情况下,即使在项目中定义了_ViewStart文件,也可能需要在视图中定义Layout属性。
第一种情况,视图需要的布局和_ViewStart指定的布局不同。在Views/Shared文件夹下添加一个_ImportantLayout.cshtml布局文件。
<!DOCTYPE html> <html> <head> <title>@ViewBag.Title</title> <link href="/lib/twitter-bootstrap/css/bootstrap.min.css" rel="stylesheet" /> </head> <body> <div> <h6 class="bg-primary text-white text-center m-2 p-2"> 重要布局 </h6> @RenderBody() </div> </body> </html>
在Views/Home/Index.cshtm中使用特定布局。Layout将被视图中的值覆盖,从而允许应用不同的布局。
@model Product @{ Layout = "_ImportantLayout"; //Layout = Model.Price > 100 ? "_ImportantLayout":"_Layout"; ViewBag.Title = ViewBag.Title ?? "产品表"; }
第二种情况,视图包含一个完整的html文件,并不需要一个布局,可将Layout值设置为null。
@{ Layout = null; }
4.4 使用布局节
视图引擎支持节的概念,从而允许在布局内提供区域内容。
在Home/Index.cshtml中定义节。
} @section Header{ 产品信息 } <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> @section Footer{ (平均值的@((Model.Price / ViewBag.AveragePrice * 100).ToString("F2"))%) }
使用@RenderSection表达式在布局内应用节,应用布局时@RenderSection把指定节内容插入响应,没有包含再节内的由方法插入响应。如果定义了节但布局中没有使用将会报错。
修改_Layout.cshtml文件中使用节。
<!DOCTYPE html> <html> <head> <title>@ViewBag.Title</title> <link href="/lib/twitter-bootstrap/css/bootstrap.min.css" rel="stylesheet" /> </head> <body> <div class="bg-info text-white m-2 p-2"> 这是布局的一部分 </div> <h6 class="bg-primary text-white text-center m-2 p-2"> @RenderSection("Header") </h6> <div class="bg-info text-white m-2 p-2"> 这是布局的一部分 </div> <div class="m2"> <table class="table table-sm table-striped table-bordered" data-id="@Model.ProductId"> <tbody> @RenderBody(); </tbody> </table> </div> <div class="bg-info text-white m-2 p-2"> 这是布局的一部分 </div> <h6 class="bg-primary text-white text-center m-2 p-2"> @RenderSection("Footer") </h6> <div class="bg-info text-white m-2 p-2"> 这是布局的一部分 </div> </body> </html>
节允许视图向布局提供内容片段,而不指定如何使用他们。以下把body和节合并到一个html表格中。
<!DOCTYPE html> <html> <head> <title>@ViewBag.Title</title> <link href="/lib/twitter-bootstrap/css/bootstrap.min.css" rel="stylesheet" /> </head> <body> <div class="m2"> <table class="table table-sm table-striped table-bordered"> <thead> <tr> <th class="bg-primary text-white text-center" colspan="2"> @RenderSection("Header") </th> </tr> </thead> <tbody> @RenderBody(); </tbody> <tfoot> <tr> <th class="bg-primary text-white text-center" colspan="2"> @RenderSection("Footer") </th> </tr> </tfoot> </table> </div> </body> </html>
(1)使用可选布局节
@RenderSection第二个实参,只有当视图定义了该节时才渲染该节。
@RenderSection("Header",false)
(2)测试布局节
IsSectionDefined用于判断是否定义了指定节。以下如果没有定义则渲染后备内容。
@if (IsSectionDefined("Summary"))// 判断视图是否定义了节 { @RenderSection("Summary", false) } else { <div class="bg-info text-center text-white m-2 p-2"> 这是默认摘要 </div> }
5 使用分部视图
5.1 启动分部视图
通过标签助手可以应用分部视图。
在_ViewImports.cshtml中启用标签助手。
@using MyWebApp.Models @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
5.2 创建分部视图
分部视图也是.cshtml文件,只是使用方式与标准视图区分开。
在Home文件夹下创建_RowPartial.cshtml。
@model Product <tr> <td>@Model.Name</td> <td>@Model.Price</td> </tr>
5.3 应用分部视图
通过在另一个视图或布局中添加partial元素,可以应用分部视图。
在Home/List.cshtml中使用。
<thead> <tr><th>Name</th><th>Price</th><th>平均占比</th></tr> </thead> <tbody> @foreach (Product p in Model) { <partial name="_RowPartial" model="p" /> } </tbody>
注:早期版本中使用@Html.Partial("_RowPartial"),现在仍然支持。
(0)使用表达式选择分部视图模型
for特性使用一个应用到视图模型的表达式,设置分部视图模型。
在Views/Home文件夹下添加_CellPartial.cshtml。
@model string <td class="bg-info text-white" >@Model</td>
在_RowPartial.cshtml中使用。
@model Product <tr> @*<td>@Model.Name</td>*@ <partial name="_CellPartial" for="Name" /> <td>@Model.Price</td> </tr>
6 理解内容编码
Razor视图为内容提供了两种有用功能。html内容编码确保了表达式响应不会修改发送给浏览器的响应结构。json编码功能将对像编码为json并将其插入响应中。
6.1 理解html编码
在HomeController中添加一个方法。
public IActionResult Html() { return View((object)"this is a <h3><i>string</i></h3>"); }
在Views/Home文件夹中添加Html.cshtml。
@model string @{ Layout = null; } <!DOCTYPE html> <html> <head> <link href="/lib/twitter-bootstrap/css/bootstrap.min.css" rel="stylesheet" /> </head> <body> <div class="bg-secondary text-white text-center m-2 p-2">@Model</div> <div class="bg-secondary text-white text-center m-2 p-2">@Html.Raw(Model)</div> </body> </html>
调用@Html.Raw(Model),它返回对象实现了IHtmlHeper接口,模型字符串将会被浏览器解释为html一部分。
6.2 理解json编码
在Index.cshtml中使用json编码
@section Summary { <div class="bg-info text-white m-2 p-2"> @Json.Serialize(Model) </div> }
Json属性返回IJsonHelper接口的一个实现,@Json.Serialize(Model)生成对象的json表示。
本文来自博客园,作者:一纸年华,转载请注明原文链接:https://www.cnblogs.com/nullcodeworld/p/18154568
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!