在 ASP.NET WebPages(也就是 Razor 网页模型)中,我们会发现页面代码可以直接使用一些对象,比如直接写 Request["name"] 就能拿到用户提交的参数,直接写 @Page.Title 就能把数据传给布局页。这些对象并不是凭空而来的,它们由框架在页面编译和执行时自动注入,理解这些对象的生命周期和职责边界,是从会写页面到写好页面的关键一步。这篇笔记把最常用的几个对象整理出来,配上可运行的示例代码,方便日后查阅和复习。

Page 对象:页面与布局页之间的桥梁
Page 对象是 WebPages 中最常被低估的一个对象。它的核心作用是充当当前页面与布局页(Layout Page)之间的数据通道。当你在一个内容页里写了 @{ Layout = "~/Shared/_Layout.cshtml"; } 之后,这个页面渲染时会先执行自身逻辑,再把结果填充到布局页的 @RenderBody() 位置。如果内容页想告诉布局页一些信息,比如页面标题、当前导航高亮项,最标准的做法就是通过 Page 对象的动态属性来传递。
Page 对象本质上是一个动态对象(dynamic),你可以给它赋任意属性名,然后直接在布局页中读取。下面这个例子演示了最常见的用法:
@{
// 内容页 Demo.cshtml
Page.Title = "用户列表";
Page.CurrentNav = "user";
Layout = "~/Shared/_Layout.cshtml";
}
<h1>这里是页面正文</h1>
<!-- 布局页 _Layout.cshtml -->
<!DOCTYPE html>
<html>
<head>
<title>@Page.Title</title>
</head>
<body>
<div class="nav @Page.CurrentNav">导航区域</div>
@RenderBody()
</body>
</html>除了自定义属性,Page 对象还有两个内置成员值得记住。一个是 Page.VirtualPath,返回当前页面的虚拟路径,常用于调试;另一个是 PageData 字典,它用在局部页(使用 RenderPage 引入的页面)的场景中,可以传键值对过去:@RenderPage("~/Shared/Header.cshtml", new { UserName = "Tom" }),然后在局部页里通过 PageData["UserName"] 取出。Page 属性和 PageData 的区别在于前者是动态语法糖,后者是显式字典,功能上重叠,团队协作时建议统一用一种,避免维护混乱。
Request 对象:读取用户输入的唯一入口
无论用户是通过 URL 查询字符串、表单 POST 还是 Cookie 提交数据,WebPages 中统一用 Request 对象来读取。它最常用的三种写法是:Request["key"](不区分来源,依次搜索 QueryString、Form、Cookies、ServerVariables)、Request.QueryString["key"](只读 URL 参数)和 Request.Form["key"](只读 POST 数据)。Request["key"] 的好处是写起来省事,坏处是来源不确定,如果页面同时存在同名参数,排查起来会很痛苦,所以正式项目中我更推荐明确写出集合名称。
下面是一段简单的登录表单处理代码,演示了 GET 与 POST 两种情况下参数的读取方式:
@{
if (IsPost)
{
// 只从表单里取,避免被 URL 参数干扰
var userName = Request.Form["userName"];
var password = Request.Form["password"];
<p>用户名是:@userName</p>
}
}
<form method="post">
<input type="text" name="userName" />
<input type="password" name="password" />
<button type="submit">登录</button>
</form>这里要特别强调安全问题和类型转换。首先,所有从 Request 读到的值都是字符串,拿来参与计算前必须转换,比如 Request.QueryString["id"].AsInt(),AsInt 是 WebPages 提供的扩展方法,转换失败会返回默认值 0,不会抛异常,这一点比直接 int.Parse 安全得多。其次,取到的值在输出到页面时 Razor 会自动做 HTML 编码,防住了 XSS,但如果拿去拼接 SQL 语句就必须自己处理,参数化查询是底线。另外 Request.Files 用于文件上传,Request.Browser 能读到浏览器类型,Request.UrlReferrer 可以拿到来路地址,这些属性在统计和防盗链场景中偶尔会用到。
Response 对象:输出内容与页面跳转
Response 对象负责"往外发"的部分。最常见的是 Response.Redirect(url),用于处理完表单后跳转,遵循 Post/Redirect/Get 模式防止重复提交。需要注意的是 Redirect 默认会直接结束当前请求,跳转之后的代码不会执行。第二个常用功能是 Response.Write(),可以直接向输出流写内容,不过在 Razor 页面里我们通常直接用 @表达式 输出,Response.Write 更多出现在 HttpHandler 或写 HTTP 头的场景。
@{
if (IsPost)
{
var ok = false; // 假设这里执行了校验逻辑
if (ok)
{
// 处理成功后跳转,避免刷新页面重复提交
Response.Redirect("~/Success.cshtml");
}
else
{
Response.SetStatus(HttpStatusCode.NotFound);
}
}
}除了跳转和输出,Response 还能控制缓存行为。比如某些纯数据页面不希望被浏览器缓存,可以写 Response.Cache.SetExpires(DateTime.Now.AddDays(-1)),让浏览器每次都重新请求。另外在下载文件的场景中,Response.AddHeader("Content-Disposition", "attachment; filename=test.csv") 配合 Response.BinaryWrite(byteArray) 是经典组合,先设置 MIME 类型和下载头,再把二进制数据写入输出流,最后调用 Response.End() 结束输出。使用时注意顺序,头必须在任何正文输出之前发送,否则会触发异常。
Server 对象与常用辅助方法
Server 对象提供的是工具类能力,最常用的是三个方法。Server.MapPath("~/App_Data/data.txt") 把虚拟路径转换成服务器上的物理路径,读写本地文件前几乎都要先做这一步;Server.HtmlEncode 和 Server.HtmlDecode 负责 HTML 编码解码;Server.UrlEncode 则用于拼 URL 时编码特殊字符。
@{
// 把虚拟路径映射为物理路径后读取文件
var filePath = Server.MapPath("~/App_Data/notes.txt");
if (File.Exists(filePath))
{
var content = File.ReadAllText(filePath);
<pre>@content</pre>
}
// 拼接带中文参数的链接
var keyword = Server.UrlEncode(" ASP.NET 教程 ");
<a href="~/Search.cshtml?q=@keyword">搜索</a>
}这里有一个新手常见坑:MapPath 的参数必须以 ~/ 开头的相对虚拟路径,如果传了绝对路径或者不带 ~/ 的路径,某些部署环境下会抛出异常或映射到错误位置。另外要区分 Server 对象和 WebPages 提供的辅助方法,比如 Href() 函数也负责路径处理,但它输出的是可直接用于浏览器的相对 URL,和 MapPath 输出的服务器物理路径完全是两回事,一个给浏览器用,一个给文件系统用,不要混用。
对象协作的完整流程与小结
把这几个对象串起来看一次完整的请求流程会更清晰:用户访问页面后,框架加载页面,先经过 _PageStart.cshtml` 做初始化(比如登录校验);页面代码执行期间,通过 Request 读取输入,通过 Server 处理路径和编码,业务逻辑处理完毕后把结果交给 Razor 渲染输出,需要跳转时用 Response.Redirect;如果页面有布局,就通过 Page 对象把标题等信息递给布局页,最终由 Response 把整个 HTML 发回浏览器。
几个实践建议作为笔记收尾:第一,取用户输入永远显式指定集合,明确意图;第二,跨页面传值优先用 Session 或 URL 参数,不要依赖 Page 对象,它只在布局渲染这一条链路上有效;第三,所有对文件系统的访问都要经过 MapPath 转换,不要手写物理路径;第四,输出用户可控内容时保持 Razor 默认的自动编码习惯,需要输出原始 HTML 时再显式使用 Html.Raw,并且确保内容可信。把这些对象的职责边界记牢,后面学习数据库操作和辅助方法(WebGrid、WebMail 等)时会顺利很多。
ASP.NETWebPages对象Page对象修改时间:2026-09-06 18:06:43