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

ASP.NET 5 MVC表单重复提交(ERR_CACHE_MISS)问题及回退页面时提交对象恢复需求

嘿,你的这两个问题其实在ASP.NET MVC里有成熟的解决方案——用Post/Redirect/Get (PRG) 设计模式搭配TempData就能同时搞定表单重复提交和返回页面的状态恢复,我给你一步步拆解:

解决方案:PRG模式+TempData实现无重复提交与状态恢复

1. 解决Checkout页面刷新的表单重复提交问题(ERR_CACHE_MISS)

你现在的Booking表单直接提交到Checkout的Index Get方法,虽然当下能拿到数据,但如果后续业务需要提交更多复杂数据(或者实际用了Post提交),刷新页面就会触发浏览器的“Confirm Form Resubmission”提示——这是因为浏览器会保留Post请求的内容,刷新时会尝试重新发送。

PRG模式的核心思路是:用Post接收提交的数据,处理完后重定向到Get页面。这样浏览器地址栏最终是Get请求,刷新时只会重新发起Get,不会有重复提交的问题。

具体修改步骤:

  • 更新Booking视图的表单:明确指定method="post",提交到Checkout的一个新Post Action(比如叫PrepareCheckout),而不是直接到Index:
    <form asp-controller="Checkout" asp-action="PrepareCheckout" method="post"> 
        <input hidden value="@Model.CarId" name="carId"> 
        <input type="submit" value="Proceed"> 
    </form>
    
  • 在Checkout控制器中新增PrepareCheckout Post Action:这里接收Booking传来的参数,把需要保留的对象存入TempData(后面返回Booking时要用),然后重定向到Index Get页面:
    [HttpPost]
    public async Task<IActionResult> PrepareCheckout(int carId)
    {
        // 这里可以根据carId补全CarsBookingVM的其他字段,比如从数据库拉取车辆信息
        var carsBooking = new CarsBookingVM { CarId = carId };
        
        // TempData只能存基础类型或可序列化对象,所以先序列化
        TempData["PreviousBooking"] = JsonSerializer.Serialize(carsBooking);
        
        // 重定向到Checkout的Index Get方法,彻底避免Post刷新问题
        return RedirectToAction(nameof(Index), new { carId });
    }
    
  • 保留原Checkout的Index Get方法:现在这个页面是通过重定向过来的,刷新时只会发起Get请求,再也不会弹出重复提交的提示了。

2. 实现从Checkout返回Booking时恢复之前的提交对象

当用户在Checkout页面点击返回按钮时,我们可以从之前存在TempData里的对象恢复状态,传递给Booking的页面。

具体修改步骤:

  • 在Checkout视图中添加返回按钮:可以用链接或者表单,指向Booking的Index方法:
    <a asp-controller="Booking" asp-action="Index">Back to Booking</a>
    
  • 修改Booking控制器的Index方法:让它优先从TempData读取之前保存的对象,如果没有再用传入的参数或默认对象:
    public async Task<IActionResult> Index(CarsBookingVM carsBooking) 
    { 
        // 如果传入的参数为空,尝试从TempData恢复之前的提交对象
        if (carsBooking == null || carsBooking.CarId == 0)
        {
            if (TempData.ContainsKey("PreviousBooking"))
            {
                var serializedBooking = TempData["PreviousBooking"].ToString();
                carsBooking = JsonSerializer.Deserialize<CarsBookingVM>(serializedBooking);
                // 如果需要用户多次返回都能恢复状态,就把数据重新存回TempData
                TempData["PreviousBooking"] = serializedBooking;
            }
        }
        return View(carsBooking); 
    }
    

额外注意点

  • TempData的生命周期:默认情况下,TempData里的数据被读取后会被标记为删除,下次请求就没了。如果需要多次使用,可以用TempData.Keep("PreviousBooking")或者像上面那样重新存入数据。
  • 对象序列化:确保你的CarsBookingVM类是可序列化的(比如有公共无参构造函数,字段都是可序列化类型),不然JsonSerializer会报错。
  • Session替代方案:如果需要数据在用户会话中保留更长时间,可以用ISession存储,但TempData更适合这种跨一次重定向的场景,因为它会自动清理,不会占用多余内存。

这样改完之后,两个问题都能解决:Checkout页面刷新不会再出现重复提交提示,返回Booking页面时也能恢复用户之前提交的对象状态。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.28 20:12:45