ASP.NET Core Razor Pages 开发实战:从入门到部署 📅 发布时间:2026/8/25 12:26:40 👁 浏览次数: 这次我们来看一个 ASP.NET Core Razor Pages 项目。这不是一个需要高显存的 AI 模型而是一个用于构建现代 Web 应用的成熟技术框架。它的核心价值在于提供了一种比传统 MVC 更简单、更聚焦的页面模型来开发 Web UI尤其适合内容驱动的网站。对于 .NET 开发者而言Razor Pages 降低了构建页面的复杂度将相关的处理逻辑如 HTTP 方法处理和视图直接绑定在同一个文件中开发体验更直观。如果你正在寻找一种高效的方式来创建带有表单、数据交互的网页或者从 Web Forms 或 MVC 迁移过来Razor Pages 值得重点关注。本文将基于 ASP.NET Core 的最新实践带你快速了解 Razor Pages 的核心能力、环境搭建、项目创建、功能开发到部署测试的全流程。我们会重点关注其与 MVC 的差异、页面模型PageModel的使用、数据绑定与验证以及如何集成 API 等实用场景。1. 核心能力速览能力项说明技术栈ASP.NET Core (支持 .NET 6/7/8/9)开发模式基于页面的开发模型每个页面包含视图.cshtml和页面模型.cshtml.cs主要功能构建动态 Web 页面、处理表单提交、数据绑定、模型验证、依赖注入硬件门槛无特殊要求普通开发机即可依赖 .NET SDK启动方式命令行dotnet run或 IDE如 Visual Studio一键启动是否支持 API是可与 Web API 控制器在同一个项目中混合使用适合场景内容管理系统CMS、企业内部应用、数据仪表盘、带有复杂表单的业务页面2. 适用场景与使用边界Razor Pages 非常适合构建以页面为中心的 Web 应用程序。它简化了为每个独立页面编写控制器和动作方法的流程。它适合内容驱动型网站如产品展示页、新闻文章页、关于我们等每个页面逻辑独立。表单密集型应用如用户注册、数据提交、调查问卷利用内置的模型绑定和验证非常方便。快速原型开发页面模型将前后端逻辑放在一起便于快速迭代和测试单一页面功能。从 Web Forms 迁移其事件处理模型OnGet,OnPost对 Web Forms 开发者更友好。它可能不适合纯 API 后端服务如果项目仅提供 JSON/XML 接口不涉及 UI 渲染使用最小 API 或 Web API 控制器更纯粹。极度复杂的单页面应用SPA前端交互极其复杂建议使用 Angular、React、Vue 等前端框架ASP.NET Core 仅作为后端 API。需要高度复用控制器逻辑的场景如果多个视图需要共享完全相同的后端处理逻辑传统 MVC 的控制器可能更合适。安全与合规边界输入验证必须充分利用 Razor Pages 内置的模型验证特性防止非法数据提交。跨站请求伪造CSRF表单必须使用防伪令牌Html.AntiForgeryToken()。授权与认证对于需要权限的页面应使用[Authorize]特性进行保护。3. 环境准备与前置条件开始之前请确保你的开发环境满足以下条件操作系统Windows 10/11 macOS 或 Linux 发行版如 Ubuntu。.NET SDK安装最新长期支持LTS版本或当前版本。例如 .NET 8 或 .NET 9预览版。你可以从 .NET 官网 下载。在命令行中运行dotnet --version来验证安装。代码编辑器或 IDE任选其一Visual Studio 2022Windows/macOS对 .NET 开发支持最全面社区版免费。Visual Studio Code跨平台轻量需要安装 C# 扩展。浏览器用于测试如 Chrome、Edge 或 Firefox。磁盘空间约 2-4 GB 用于 SDK、工具和项目文件。4. 安装部署与启动方式我们将从零开始创建一个 Razor Pages 项目。4.1 创建新项目打开终端命令行提示符、PowerShell 或 VS Code 终端导航到你希望创建项目的目录。使用以下命令创建一个新的 Razor Pages 项目dotnet new webapp -n MyRazorApp -o MyRazorAppdotnet new webapp使用“Razor Pages”项目模板。-n MyRazorApp指定项目名称。-o MyRazorApp指定输出目录文件夹名称。4.2 项目结构解析创建完成后进入项目目录并查看结构cd MyRazorApp dir # Windows # 或 ls -la # Linux/macOS关键目录和文件Pages/核心目录。所有 Razor 页面.cshtml和对应的页面模型文件.cshtml.cs都放在这里或其子目录下。默认包含Index.cshtml主页、Error.cshtml等。Program.cs应用程序的入口点配置服务依赖注入和 HTTP 请求管道。appsettings.json应用程序配置文件如连接字符串、日志设置。wwwroot/静态资源文件夹CSS, JavaScript, 图片。4.3 启动应用程序在项目根目录包含MyRazorApp.csproj的目录下运行dotnet run命令输出会显示应用程序正在监听的 URL通常是https://localhost:5001和http://localhost:5000。打开浏览器访问https://localhost:5001。你将看到 Razor Pages 项目的默认主页。在 Visual Studio 中打开项目文件.csproj直接按F5或点击“运行”按钮即可启动调试。5. 功能测试与效果验证让我们通过创建几个典型页面来验证 Razor Pages 的核心功能。5.1 创建“关于我们”静态页面创建页面文件在Pages文件夹下新建一个文件About.cshtml。编辑页面视图在About.cshtml中直接编写 HTML 和 Razor 语法。page model MyRazorApp.Pages.AboutModel { ViewData[Title] 关于我们; } h1ViewData[Title]/h1 p这是一个使用 ASP.NET Core Razor Pages 构建的“关于我们”页面。/p p当前服务器时间DateTime.Now/p创建页面模型可选但推荐在Pages文件夹下新建文件About.cshtml.cs。这允许你为页面添加后端逻辑。using Microsoft.AspNetCore.Mvc.RazorPages; namespace MyRazorApp.Pages { public class AboutModel : PageModel { // 可以在这里定义属性供前端页面使用 public string CompanyInfo { get; set; } 示例公司; // 页面 GET 请求的处理方法 public void OnGet() { // 可以在这里执行初始化逻辑如从数据库加载数据 ViewData[Message] $欢迎了解{CompanyInfo}; } } }修改视图以使用模型更新About.cshtml使用页面模型中定义的属性。page model MyRazorApp.Pages.AboutModel { ViewData[Title] 关于我们; } h1ViewData[Title]/h1 pViewData[Message]/p !-- 使用从PageModel传递过来的数据 -- p这是一个使用 ASP.NET Core Razor Pages 构建的“关于我们”页面。/p p公司名称Model.CompanyInfo/p !-- 直接使用PageModel的属性 -- p当前服务器时间DateTime.Now/p测试确保应用正在运行 (dotnet run)然后在浏览器中访问https://localhost:5001/About。你将看到包含动态内容的“关于我们”页面。5.2 创建带表单验证的“联系我们”页面这是一个更复杂的例子演示表单处理、模型绑定和验证。创建页面文件在Pages文件夹下新建Contact.cshtml和Contact.cshtml.cs。定义数据模型在Contact.cshtml.cs中我们定义一个ContactFormModel类来表示表单数据并应用数据注解进行验证。using System.ComponentModel.DataAnnotations; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.RazorPages; namespace MyRazorApp.Pages { public class ContactModel : PageModel { // 这个属性将绑定表单数据 [BindProperty] public ContactFormModel Form { get; set; } new(); // 用于向视图传递成功消息 public string SuccessMessage { get; set; } public void OnGet() { // GET请求初始化 } // 处理表单的POST请求 public IActionResult OnPost() { if (!ModelState.IsValid) { // 如果验证失败返回当前页面并显示错误信息 return Page(); } // 模拟处理表单数据例如保存到数据库发送邮件 // ... // 处理成功重定向到成功页面或显示成功消息 SuccessMessage $感谢您{Form.Name}我们已经收到您的留言。; // 为了防止重复提交通常使用 Post-Redirect-Get (PRG) 模式 // return RedirectToPage(./ContactSuccess); // 本例中我们简单地在同一页面显示消息 ModelState.Clear(); // 清除表单数据 Form new ContactFormModel(); // 重置表单 return Page(); } } public class ContactFormModel { [Required(ErrorMessage 姓名是必填项)] [Display(Name 您的姓名)] public string Name { get; set; } [Required(ErrorMessage 邮箱是必填项)] [EmailAddress(ErrorMessage 请输入有效的邮箱地址)] [Display(Name 电子邮箱)] public string Email { get; set; } [Required(ErrorMessage 主题是必填项)] [StringLength(100, ErrorMessage 主题不能超过100个字符)] [Display(Name 主题)] public string Subject { get; set; } [Required(ErrorMessage 留言内容是必填项)] [DataType(DataType.MultilineText)] [Display(Name 留言内容)] public string Message { get; set; } } }创建表单视图编辑Contact.cshtml。page model MyRazorApp.Pages.ContactModel { ViewData[Title] 联系我们; } h1ViewData[Title]/h1 if (!string.IsNullOrEmpty(Model.SuccessMessage)) { div classalert alert-success rolealert Model.SuccessMessage /div } form methodpost Html.AntiForgeryToken() !-- 重要添加防伪令牌 -- div classform-group label asp-forForm.Name/label input asp-forForm.Name classform-control / span asp-validation-forForm.Name classtext-danger/span /div div classform-group label asp-forForm.Email/label input asp-forForm.Email classform-control / span asp-validation-forForm.Email classtext-danger/span /div div classform-group label asp-forForm.Subject/label input asp-forForm.Subject classform-control / span asp-validation-forForm.Subject classtext-danger/span /div div classform-group label asp-forForm.Message/label textarea asp-forForm.Message classform-control rows5/textarea span asp-validation-forForm.Message classtext-danger/span /div button typesubmit classbtn btn-primary提交留言/button /form section Scripts { partial name_ValidationScriptsPartial / !-- 引入客户端验证脚本 -- }测试表单功能访问https://localhost:5001/Contact。不填写任何信息直接提交页面会显示所有字段的验证错误信息客户端验证。填写无效邮箱格式会提示“请输入有效的邮箱地址”。正确填写所有信息后提交页面会显示成功消息并且表单被清空。5.3 测试页面路由与参数传递Razor Pages 支持在路由中传递参数。创建带参数的页面在Pages文件夹下创建Welcome.cshtml和Welcome.cshtml.cs。// Welcome.cshtml.cs using Microsoft.AspNetCore.Mvc.RazorPages; namespace MyRazorApp.Pages { public class WelcomeModel : PageModel { // 路由参数会绑定到这个属性 [BindProperty(SupportsGet true)] // SupportsGet 允许从GET请求绑定 public string Name { get; set; } public void OnGet() { // 如果URL中没有提供Name参数可以设置默认值 if (string.IsNullOrEmpty(Name)) { Name 访客; } } } }page {name?} !-- 定义可选的路由参数 name -- model MyRazorApp.Pages.WelcomeModel { ViewData[Title] 欢迎; } h1欢迎Model.Name/h1测试路由访问https://localhost:5001/Welcome页面显示“欢迎访客”。访问https://localhost:5001/Welcome/张三页面显示“欢迎张三”。6. 接口 API 与批量任务虽然 Razor Pages 专注于页面但它可以轻松地与 Web API 集成或在同一项目中混合使用。6.1 在 Razor Pages 项目中添加 Web API 控制器在项目根目录创建Controllers文件夹。在该文件夹下创建ApiController.cs。using Microsoft.AspNetCore.Mvc; namespace MyRazorApp.Controllers { [ApiController] [Route(api/[controller])] public class ApiController : ControllerBase { [HttpGet(data)] public IActionResult GetData() { var data new { Message 来自API的数据, Timestamp DateTime.UtcNow }; return Ok(data); } [HttpPost(submit)] public IActionResult SubmitData([FromBody] SomeModel model) { // 处理接收到的数据 if (model null) { return BadRequest(无效的数据); } // ... 处理逻辑 return Ok(new { success true, received model }); } } public class SomeModel { public string Value { get; set; } } }在 Razor Page 中调用 API你可以在页面模型的OnGet或OnPost方法中使用HttpClient调用这个 API或者在前端使用 JavaScript (Fetch API 或 Axios) 调用。6.2 前端 JavaScript 调用 API 示例在Contact.cshtml的Scripts部分添加section Scripts { partial name_ValidationScriptsPartial / script // 示例页面加载后从API获取数据 document.addEventListener(DOMContentLoaded, function () { fetch(/api/Api/data) .then(response response.json()) .then(data { console.log(从API获取的数据, data); // 可以将数据展示在页面的某个元素上 // document.getElementById(api-data).innerText data.Message; }) .catch(error console.error(获取API数据失败, error)); }); /script }6.3 关于“批量任务”在 Web 应用上下文中“批量任务”通常指后台作业。对于 Razor Pages 应用如果需要处理长时间运行或周期性的任务如发送批量邮件、处理上传的文件建议使用后台服务BackgroundService或Hangfire、Quartz.NET等专用库。简单后台服务示例在Program.cs中注册一个托管服务// 定义后台服务 public class MyBackgroundService : BackgroundService { protected override async Task ExecuteAsync(CancellationToken stoppingToken) { while (!stoppingToken.IsCancellationRequested) { // 执行你的批量任务逻辑 Console.WriteLine($后台任务执行于{DateTime.Now}); await Task.Delay(TimeSpan.FromMinutes(5), stoppingToken); // 每5分钟执行一次 } } } // 在 Program.cs 的 builder.Services 中注册 builder.Services.AddHostedServiceMyBackgroundService();7. 资源占用与性能观察作为一个 .NET Core 应用其资源占用主要取决于应用复杂度、并发请求量和数据访问。内存占用一个简单的 Razor Pages 应用启动后内存占用通常在 100-300 MB。可以使用任务管理器或dotnet-counters工具监控。CPU 使用率在空闲状态下很低。在高并发请求或执行复杂计算时会升高。启动时间首次启动冷启动需要 JIT 编译稍慢。后续请求响应很快。使用ReadyToRun (R2R)编译或ASP.NET Core 原生 AOT.NET 8可以显著提升启动速度。监控工具Visual Studio 诊断工具调试时查看 CPU、内存。dotnet-counters命令行性能监控工具。dotnet-counters monitor -n MyRazorApp --counters System.RuntimeApplication Insights 或 OpenTelemetry用于生产环境监控。性能优化建议使用异步编程在页面模型的处理器方法如OnGetAsync和数据库访问中广泛使用async/await避免阻塞线程。缓存策略对不常变的数据使用内存缓存 (IMemoryCache) 或分布式缓存。捆绑与压缩对静态资源CSS, JS进行捆绑和压缩。数据库优化使用高效的查询考虑索引。8. 常见问题与排查方法问题现象可能原因排查方式解决方案dotnet run失败提示“未找到项目”未在正确的项目目录包含.csproj文件下执行命令。检查当前目录使用dir *.csproj或ls *.csproj。导航到正确的项目根目录再执行命令。浏览器访问localhost:5001显示“无法访问此网站”1. 应用未成功启动。2. 端口被占用。3. HTTPS 证书问题。1. 查看dotnet run控制台是否有错误输出。2. 检查端口占用netstat -ano | findstr :5001。3. 尝试访问http://localhost:5000。1. 根据控制台错误修复代码。2. 在Program.cs或appsettings.json中修改应用端口。3. 开发时可在Program.cs中暂时禁用 HTTPS 重定向。页面显示“HTTP Error 404”1. 页面文件路径或名称错误。2. 路由未正确配置。1. 检查Pages文件夹下的文件路径和名称是否与访问的 URL 匹配区分大小写。2. 检查page指令中的路由模板。1. 确保文件位于Pages目录下且访问 URL 为/FileName不含扩展名。2. 使用page “{id?}”等定义参数路由。表单提交后模型属性为null未使用[BindProperty]特性或属性名与表单字段名不匹配。1. 在页面模型的属性上添加[BindProperty]。2. 检查前端asp-for绑定的属性名。1. 为需要绑定的属性添加[BindProperty]。2. 确保前端name属性与后端属性名一致。客户端验证不生效未引入验证脚本部分_ValidationScriptsPartial。检查视图文件是否包含section Scripts { partial name“_ValidationScriptsPartial” / }。在表单页面中添加对验证脚本部分的引用。修改.cshtml文件后浏览器未刷新浏览器缓存或开发服务器热重载未触发。手动刷新浏览器CtrlF5。确保Program.cs中builder.Services.AddRazorPages()已调用。在开发环境中Razor 文件更改会自动触发重新编译和浏览器刷新。发布到 IIS 后出现 500 错误1. 未安装 ASP.NET Core 运行时/托管捆绑包。2. 应用程序池未设置为“无托管代码”。3. 文件权限问题。查看 Windows 事件查看器或 IIS 日志中的详细错误信息。1. 在服务器安装对应版本的 ASP.NET Core 运行时/托管捆绑包 。2. 将 IIS 中站点对应的应用程序池的“.NET CLR 版本”设置为“无托管代码”。3. 确保 IIS_IUSRS 用户对网站目录有读取和执行权限。9. 最佳实践与使用建议保持页面模型精简PageModel应专注于处理当前页面的 HTTP 请求和准备视图数据。复杂的业务逻辑应抽取到单独的服务类中并通过依赖注入使用。善用布局Layout和部分视图Partial Views将通用的页面结构如页头、页脚、导航栏放在_Layout.cshtml中。将可重用的 UI 片段如产品卡片、评论列表创建为部分视图。使用 Tag HelpersTag Helpers如asp-page,asp-route-*,asp-validation-for让 Razor 语法更接近 HTML提高可读性和开发效率。实施安全的开发实践始终使用防伪令牌在任何修改数据的表单POST、PUT、DELETE上使用Html.AntiForgeryToken()或form标签帮助器它默认包含。进行输入验证不仅在客户端验证服务器端ModelState.IsValid检查必不可少。防范 XSSRazor 默认对输出进行 HTML 编码。除非必要不要使用Html.Raw()。使用授权使用[Authorize]特性保护需要认证或特定角色的页面。组织页面结构对于大型项目在Pages下创建子文件夹来组织页面如Pages/Products/,Pages/Admin/。这会自动生成嵌套的路由如/Products/Index。考虑可测试性将业务逻辑放在可注入的服务中使得对PageModel的单元测试更容易可以模拟这些服务。为生产环境做好准备使用appsettings.Production.json覆盖开发配置。配置正确的日志级别。启用HSTS。考虑使用反向代理如 Nginx, IIS。10. 总结与下一步ASP.NET Core Razor Pages 提供了一种高效、直观的方式来构建服务器端渲染的 Web 页面。它通过将视图和逻辑紧密耦合在页面单元中简化了开发流程特别适合表单处理和内容展示类应用。通过本文的步骤你应该已经能够创建、运行并测试一个基本的 Razor Pages 应用理解了页面模型、路由、模型绑定和验证的核心机制。接下来可以深入探索的方向数据访问集成 Entity Framework Core连接真实数据库实现 CRUD 操作。身份认证与授权使用 ASP.NET Core Identity 为你的应用添加用户注册、登录和角色管理功能。更高级的客户端交互结合 JavaScript 框架如 Alpine.js, htmx或使用 Razor 组件Blazor来增强用户体验无需完全转向 SPA。实时通信集成 SignalR实现页面实时更新功能。部署将应用部署到 Azure App Service、Linux 虚拟机或 Docker 容器中。建议从官方文档和实际项目入手逐步掌握更高级的特性。对于需要高度交互前端的部分可以评估 Razor Pages 与前端框架结合的混合模式这能让你在开发效率和用户体验之间找到最佳平衡。