@page
Razor 指令将文件转换为一个 MVC 操作,这意味着它可以处理请求。 @page
必须是页面上的第一个 Razor 指令。
@model
指令指定传递到 Razor 页面的模型类型。 在前面的示例中,@model
行使 PageModel
派生的类可用于 Razor 页面。 在页面上的 @Html.DisplayNameFor
和 @Html.DisplayFor
HTML 帮助程序中使用该模型。例如:
@Html.DisplayNameFor(model => model.Movie[0].Title)
DisplayNameFor检查Lambda表达式中引用的Title属性来确定显示名称。检查Lambda表达式(而非求值)。这意味着model,moedl.Movie或model.Movie[0]为null或为空时,不会存在任何访问冲突。 对 Lambda 表达式求值时(例如,使用 @Html.DisplayFor(modelItem => item.Title)
),将求得该模型的属性值。
选择菜单链接(“RazorPagesMovie”、“Home”和“Privacy”)。 每页显示相同的菜单布局。 菜单布局在 Pages/Shared/_Layout.cshtml
文件中实现。
查找 @RenderBody()
行。 RenderBody
是显示全部页面专用视图的占位符,已包装在布局页中。 例如,选择 Privacy 链接后,Pages/Privacy.cshtml
视图在 RenderBody
方法中呈现。
PageModel
基类包含 ViewData
字典属性,可用于将数据传递到某个视图。 可以使用键值模式将对象添加到 ViewData
字典。 在前面的示例中,Title
属性被添加到 ViewData
字典。
查询
[BindProperty(SupportsGet = true)]
public string ? SearchString { get; set; }
[BindProperty]
会绑定名称与属性相同的表单值和查询字符串。 在 HTTP GET 请求中进行绑定需要 [BindProperty(SupportsGet = true)]
。
例如:http请求:https://localhost:5001/Movies?searchString=Ghost
。 筛选的电影将显示出来。
如果向“索引”页面添加了以下路由模板,搜索字符串则可作为 URL 段传递。 例如 https://localhost:5001/Movies/Ghost
。则修改页面@page标记
@page "{searchString?}"
控制器和 Razor Pages 处理来自 HTTP 请求的数据。 例如,路由数据可以提供一个记录键,而发布的表单域可以为模型的属性提供一个值。 编写代码以检索这些值,并将其从字符串转换为 .NET 类型不仅繁琐,而且还容易出错。 模型绑定会自动化该过程。 模型绑定系统:
假设有以下操作方法:
[HttpGet("{id}")]
public ActionResult<Pet> GetById(int id, bool dogsOnly)
并且应用收到一个带有以下 URL 的请求:
https://contoso.com/api/pets/2?DogsOnly=true
在路由系统选择该操作方法之后,模型绑定执行以下步骤:
GetById
的第一个参数,该参数是一个名为 id
的整数。id
=“2”。GetById
的下一个参数,该参数是一个名为 dogsOnly
的布尔值。true
。然后,该框架会调用 GetById
方法,为 id
参数传入 2,并为 dogsOnly
参数传入 true
。
模型绑定尝试查找以下类型目标的值:
PageModel
类的公共属性(若由特性指定)。可应用于控制器或 PageModel
类的公共属性,从而使模型绑定以该属性为目标:
public class EditModel : PageModel
{
[BindProperty]
public Instructor? Instructor { get; set; }
// ...
}
可应用于控制器或 PageModel
类,以使模型绑定以该类的所有公共属性为目标:
[BindProperties]
public class CreateModel : PageModel
{
public Instructor? Instructor { get; set; }
// ...
}
默认情况下,不绑定 HTTP GET 请求的属性。 通常,GET 请求只需一个记录 ID 参数。 记录 ID 用于查找数据库中的项。 因此,无需绑定包含模型实例的属性。 在需要将属性绑定到 GET 请求中的数据的情况下,请将 SupportsGet
属性设置为 true
:
[BindProperty(Name = "ai_user", SupportsGet = true)]
public string? ApplicationInsightsCookie { get; set; }
默认情况下,模型绑定以键值对的形式从 HTTP 请求中的以下源中获取数据:
对于每个目标参数或属性,按照之前列表中指示的顺序扫描源。 有几个例外情况:
IFormFile
或 IEnumerable<IFormFile>
的目标类型。如果默认源不正确,请使用下列属性之一来指定源:
在 Views/[ControllerName]
文件夹中创建特定于控制器的视图。 控制器之间共享的视图都将置于 Views/Shared
文件夹。 要创建一个视图,请添加新文件,并将其命名为与 .cshtml
文件扩展名相关联的控制器操作的相同名称。 要创建与Home
控制器中 About
操作相对应的视图,请在 Views/Home
文件夹中创建一个 About.cshtml
文件.
操作返回一个视图时,会发生称为“视图发现”的过程。 此过程基于视图名称确定使用哪个视图文件。
View
方法 的默认行为 (return View();
) 旨在返回与其从中调用的操作方法同名的视图。 例如,控制器的 About
ActionResult
方法名称用于搜索名为 About.cshtml
的视图文件。 运行时首先在 Views/[ControllerName]
文件夹中搜索该视图。 如果在此处找不到匹配的视图,则会在 Shared
文件夹中搜索该视图。
用 return View();
隐式返回 ViewResult
还是用 return View("<ViewName>");
将视图名称显式传递给 View
方法并不重要。 在这两种情况下,视图发现都会按以下顺序搜索匹配的视图文件:
Views/\[ControllerName]/\[ViewName].cshtml
Views/Shared/\[ViewName].cshtml
可以提供视图文件路径而不提供视图名称。 如果使用从应用根目录开始的绝对路径(可选择以“/”或“~/”开头),则须指定 .cshtml
扩展名:
C#复制
return View("Views/Home/About.cshtml");
也可使用相对路径在不同目录中指定视图,而无需指定 .cshtml
扩展名。 在 HomeController
内,可以使用相对路径返回 Manage
视图的 Index
视图:
C#复制
return View("../Manage/Index");
同样,可以用“./”前缀来指示当前的控制器特定目录:
C#复制
return View("./About");
使用多种方法将数据传递给视图:
ViewData
(ViewDataAttribute
)ViewBag
最可靠的方法是在视图中指定模型类型。 此模型通常称为 viewmodel。 将 viewmodel 类型的实例传递给此操作的视图。
使用 viewmodel 将数据传递给视图可让视图充分利用强类型检查。 强类型化(或强类型)意味着每个变量和常量都有明确定义的类型(例如 string
、int
或 DateTime
)。 在编译时检查视图中使用的类型是否有效。
没有针对可以提供给视图的模型类型的限制。 建议使用普通旧 CLR 对象 (POCO) viewmodel,它几乎没有已定义的行为(方法)。 通常,viewmodel 类要么存储在 Models
文件夹中,要么存储在应用根目录处的单独 ViewModels
文件夹中。
ViewData
、[ViewData]
属性和 ViewBag
)ViewBag
默认情况下不可用以用于 Razor PagesPageModel
类。
除了强类型视图,视图还可以访问弱类型(也称为松散类型)的数据集合。 与强类型不同,弱类型(或松散类型)意味着不显式声明要使用的数据类型。 可以使用弱类型数据集合将少量数据传入及传出控制器和视图。
传递数据于... | 示例 |
---|---|
控制器和视图 | 用数据填充下拉列表。 |
视图和布局视图 | 从视图文件设置布局视图中的 <title> 元素内容。 |
分部视图和视图 | 基于用户请求的网页显示数据的小组件。 |
可以通过控制器和视图上的 ViewData
或 ViewBag
属性来引用此集合。 ViewData
属性是弱类型对象的字典。 ViewBag
属性是 ViewData
的包装器,为基础 ViewData
集合提供动态属性。 注意:对于 ViewData
和 ViewBag
,键查找都不区分大小写。
ViewData
和 ViewBag
在运行时进行动态解析。 由于它们不提供编译时类型检查,因此使用这两者通常比使用 viewmodel 更容易出错。 出于上述原因,一些开发者希望尽量减少或根本不使用 ViewData
和 ViewBag
。
ViewData
ViewData
是通过 string
键访问的 ViewDataDictionary 对象。 字符串数据可以直接存储和使用,而不需要强制转换,但是在提取其他 ViewData
对象值时必须将其强制转换为特定类型。 可用于 ViewData
将数据从控制器传递到视图和视图中,包括 部分视图 和 布局。
以下是在操作中使用 ViewData
设置问候语和地址值的示例:
public IActionResult SomeAction()
{
ViewData["Greeting"] = "Hello";
ViewData["Address"] = new Address()
{
Name = "Steve",
Street = "123 Main St",
City = "Hudson",
State = "OH",
PostalCode = "44236"
};
return View();
}
在视图中处理数据:
@{
// Since Address isn't a string, it requires a cast.
var address = ViewData["Address"] as Address;
}
@ViewData["Greeting"] World!
<address>
@address.Name<br>
@address.Street<br>
@address.City, @address.State @address.PostalCode
</address>
[ViewData]
特性
使用 ViewDataDictionary 的另一种方法是 ViewDataAttribute。 控制器或 Razor 页面模型上使用 [ViewData]
特定的属性将其值存储在字典中并从中进行加载。
在下面的示例中,“Home”控制器包含使用 [ViewData]
标记的 Title
属性。 About
方法设置“关于”视图的标题:
public class HomeController : Controller
{
[ViewData]
public string Title { get; set; }
public IActionResult About()
{
Title = "About Us";
ViewData["Message"] = "Your application description page.";
return View();
}
}
在布局中,从 ViewData 字典读取标题:
<!DOCTYPE html>
<html lang="en">
<head>
<title>@ViewData["Title"] - WebApplication</title>
...
ViewBag
ViewBag
默认情况下不可用以用于 Razor PagesPageModel
类。
ViewBag
是 Microsoft.AspNetCore.Mvc.ViewFeatures.Internal.DynamicViewData
对象,可提供对存储在 ViewData
中对象的动态访问权限。 ViewBag
不需要强制转换,因此使用起来更加方便。 下例演示如何使用与上述 ViewData
有相同结果的 ViewBag
:
public IActionResult SomeAction()
{
ViewBag.Greeting = "Hello";
ViewBag.Address = new Address()
{
Name = "Steve",
Street = "123 Main St",
City = "Hudson",
State = "OH",
PostalCode = "44236"
};
return View();
}
CSHTML复制
@ViewBag.Greeting World!
<address>
@ViewBag.Address.Name<br>
@ViewBag.Address.Street<br>
@ViewBag.Address.City, @ViewBag.Address.State @ViewBag.Address.PostalCode
</address>
ViewData
和 ViewBag
之间差异的摘要
ViewBag
默认情况下不可用以用于 Razor PagesPageModel
类。
ViewData
ContainsKey
、Add
、Remove
和 Clear
。ViewData["Some Key With Whitespace"]
string
类型均须在视图中进行强制转换才能使用 ViewData
。ViewBag
Microsoft.AspNetCore.Mvc.ViewFeatures.Internal.DynamicViewData
,因此它可使用点表示法 (@ViewBag.SomeKey = <value or object>
) 创建动态属性,且无需强制转换。 ViewBag
的语法使添加到控制器和视图的速度更快。@ViewBag.Person?.Name