如果你不喜欢将用户重定向到其他页面,那么使用我的方式你不需要Post/Redirect/Get (PRG) 模式 并且用户留在当前页面而不用担心重新提交表单的负面影响!
我使用TempData 项目和Hidden field(表单的ViewModel 中的属性)在两侧(Server/Client)保持相同的Guid,这是我检测是否表单是否通过刷新重新提交。
代码的最终面看起来非常简短:
行动:
[HttpPost]
public virtual ActionResult Order(OrderViewModel vModel)
{
if (this.IsResubmit(vModel)) // << Check Resubmit
{
ViewBag.ErrorMsg = "Form is Resubmitting";
}
else
{
// .... Post codes here without any changes...
}
this.PreventResubmit(vModel);// << Fill TempData & ViewModel PreventResubmit Property
return View(vModel)
}
在视图中:
@if (!string.IsNullOrEmpty(ViewBag.ErrorMsg))
{
<div>ViewBag.ErrorMsg</div>
}
@using (Html.BeginForm(...)){
@Html.HiddenFor(x=>x.PreventResubmit) // << Put this Hidden Field in the form
// Others codes of the form without any changes
}
在视图模型中:
public class OrderViewModel: NoResubmitAbstract // << Inherit from NoResubmitAbstract
{
// Without any changes!
}
你怎么看?
我通过编写 2 个类使其变得简单:
-
NoResubmitAbstract抽象类
-
ControllerExtentions 静态类(System.Web.Mvc.ControllerBase 的扩展类)
控制器扩展:
public static class ControllerExtentions
{
[NonAction]
public static bool IsResubmit (this System.Web.Mvc.ControllerBase controller, NoResubmitAbstract vModel)
{
return (Guid)controller.TempData["PreventResubmit"]!= vModel.PreventResubmit;
}
[NonAction]
public static void PreventResubmit(this System.Web.Mvc.ControllerBase controller, params NoResubmitAbstract[] vModels)
{
var preventResubmitGuid = Guid.NewGuid();
controller.TempData["PreventResubmit"] = preventResubmitGuid ;
foreach (var vm in vModels)
{
vm.SetPreventResubmit(preventResubmitGuid);
}
}
}
不重新提交摘要:
public abstract class NoResubmitAbstract
{
public Guid PreventResubmit { get; set; }
public void SetPreventResubmit(Guid prs)
{
PreventResubmit = prs;
}
}
只需将它们放入您的 MVC 项目并运行它... ;)