You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.NET5 Razor Page页面两次渲染 OnGet方法重复调用问题

.NET 5 Razor Page OnGet 重复触发问题排查与修复

核心诱因

Razor Page处理方法重复执行基本都是以下两类原因导致:

  • 额外隐式请求触发
    浏览器自动发起的favicon请求、静态资源404后回退到路由管道、浏览器预加载(prefetch/prerender)机制都会在用户无感知的情况下发起额外页面请求。你遇到的点击View按钮触发两次OnGet,大概率是浏览器预加载机制:当<a>标签的链接被浏览器判定为高概率访问目标时,会提前发起预请求加载页面,等用户实际点击时再发起第二次正式请求。
    另外如果静态资源中间件配置顺序错误,静态资源请求会被路由到Razor页面,也会触发OnGet执行。
  • 代码设计违反HTTP规范
    HTTP协议明确规定GET请求必须是幂等的,也就是多次发起相同GET请求不应该产生任何数据变更。你现在把数据库插入逻辑写在OnGet方法里,只要出现任何重复请求(预加载、爬虫访问、用户刷新、网络重试)都会触发重复写入,这是非常典型的设计错误。

修复步骤

  1. 定位重复请求来源
    打开浏览器开发者工具(F12)切换到「网络」面板,勾选「保留日志」后复现问题,查看所有请求记录即可定位重复请求的来源:
    • 如果重复请求的路径是/favicon.ico或者其他CSS/JS/图片路径,说明中间件顺序错误,需要将Startup.cs里的app.UseStaticFiles()调整到app.UseRouting()之前,让静态资源请求直接返回,不进入Razor路由管道。
    • 如果两次请求都是同一个页面路径,查看请求头是否存在Sec-Purpose: prefetch标识,这类是浏览器预加载请求,可以在OnGet里增加判断直接跳过:
    public IActionResult OnGet(int id)
    {
        // 跳过浏览器预加载请求
        if (Request.Headers.TryGetValue("Sec-Purpose", out var purpose) 
            && purpose.ToString().Contains("prefetch"))
        {
            return Page();
        }
        // 其余业务逻辑
    }
    
  2. 修正HTTP方法使用逻辑
    所有数据库写入、状态变更的逻辑必须从GET方法迁移到POST方法,禁止通过GET请求触发数据修改:
    • 调整View页面的后台代码,OnGet仅负责页面数据查询渲染,插入逻辑迁移到OnPost:
    public class ViewModel : PageModel
    {
        private readonly AppDbContext _context;     
        private readonly IServiceScopeFactory _scopeFactory;
    
        public ViewModel(AppDbContext context, IServiceScopeFactory scopeFactory)
        {
            _context = context;
            _scopeFactory = scopeFactory;           
        }        
        
        public IActionResult OnGet(int id)
        {
            // 此处仅编写查询View页面展示数据的逻辑,不做任何写入操作
            return Page();
        }
    
        public IActionResult OnPost(int id)
        {
            if (id > 0) {
                Service.Submit(id, _scopeFactory);                   
            }
            return RedirectToPage("Index");
        }
    }
    
    • 将cars.cshtml中触发跳转的<a>标签替换为POST表单提交按钮:
    <td>
        <form asp-page="View" asp-route-id="@item.id" method="post">
            <button type="submit" class="btn btn-success btn-sm text-white">View</button>
        </form>
    </td>
    
  3. 增加幂等性兜底
    在Service.Submit方法中增加重复校验,比如根据传入id查询数据库是否已存在对应记录,存在则直接跳过插入,从业务层面彻底避免重复数据生成。

内容的提问来源于stack exchange,提问作者gorp88

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.01 02:24:15