我最近不得不自己实现这种类型的功能,发现这个问题和 Jesse Taber 博客的链接非常有帮助,所以我想我会在这里使用 ASP.NET MVC 分享我的实现。
基本理论是,您在提交表单时将令牌传递给控制器,然后控制器在下载发生时在响应中设置具有该值的 cookie。
(为 VB.NET 道歉)
在模型中添加一个属性来存储令牌:
Public Property DownloadToken As String
然后在返回结果之前在响应中设置cookie:
If Response.Cookies("MyFileDownloadToken") Is Nothing Then
Dim cookie As New HttpCookie("MyFileDownloadToken", ParameterModel.DownloadToken)
Response.Cookies.Add(cookie)
Else
Response.Cookies("MyFileDownloadToken").Value = ParameterModel.DownloadToken
End If
将令牌属性添加为表单上的隐藏字段:
@Html.HiddenFor(Function(m) m.DownloadToken)
然后我们可以使用JavaScript来控制sumbit按钮和jQuery Cookie插件来获取和设置cookies的值。
var fileDownloadChecker;
$(function ()
{
$("#MyForm").submit(function ()
{
$(".validation-summary-errors").empty(); //Clear any validation errors from a previous failed form submission
PreventResubmission();
});
$("#submitButton").prop("disabled", false);
}
function PreventResubmission()
{
//Use the current time as a unique token that we can check for in the response
var token = new Date().getTime();
//Set the token so that it is passed through to the controller
$("#DownloadToken").val(token);
//Prevent the user from resubmitting the form
$("#submitButton").prop("disabled", true);
$("#submitButton").val("Running...");
//Check once a second for the token in the response
fileDownloadChecker = window.setInterval(function ()
{
var cookieValue = $.cookie("MyFileDownloadToken");
if (cookieValue == token)
{
EnableFormSubmission();
}
}, 1000);
}
function EnableFormSubmission()
{
//Stop checking for the token
window.clearInterval(fileDownloadChecker);
fileDownloadChecker = 0;
//Clear the hidden field
$("#DownloadToken").val("");
//Clear the cookie that contains the token
$.cookie("MyFileDownloadToken", null, { path: "/" });
//Enable the form submit button
$("#submitButton").prop("disabled", false);
$("#submitButton").val("Run");
}
注意事项:
1) HttpCookie 类和 jQuery Cookie 接口的默认路径设置不同。默认情况下,HttpCookie 在根目录('/')创建,而 jQuery 插件将根据当前路径搜索(和设置)cookie。如果读取 cookie,它将回退并查看其他路径。所以我们至少在清除cookie时指定路径。 (遇到这样的情况,代码可以运行一次,但随后会失败,因为它会在当前路径中找到 cookie 并始终返回该值)
2) 我添加了一行以在页面加载时启用提交按钮,因为如果页面在运行阶段因任何原因刷新,它将保持按钮的“禁用”状态。
3) 如果你的页面和我的一样,它会显示模型验证错误,但页面在成功提交后永远不会刷新,因此任何以前的验证错误仍将显示在表单上。我在表单的提交事件处理程序中添加了一行,以从任何具有“.validation-summary-errors”类的元素中清除任何子元素。