如何以静默方式保证ASP的执行.. NET MVC3操作页面卸载



我需要在用户离开页面时执行控制器的动作(关闭,刷新,转到链接等)。动作代码如下:

public ActionResult WindowUnload(int token)
    {
        MyObjects[token].Dispose();
        return Content("Disposed");
    }

在窗口下载我做Ajax请求的动作:

$(window).unload(function ()
{
    $.ajax({
        type: "POST",
        url: "@Url.Action("WindowUnload")",
        data: {token: "@ViewData["Token"]"},
        cache: false,
        async: true
    });
    //alert("Disposing.");
})

上面的ajax请求没有到达我的控制器,即该操作没有执行。为了使上面的代码工作,我必须取消注释alert行,但我不想对用户发出警告。

如果我将async选项更改为false (alert被注释),那么它有时会起作用。例如,如果我刷新页面几次太快,那么动作将不会在每次卸载时执行。

有什么建议如何执行动作每次卸载没有警报?注意,我不需要从action返回任何东西到页面。

更新:答案摘要

不可能可靠地在卸载时执行请求,因为它不是卸载时的正确或预期行为。因此,最好重新设计应用程序,避免在窗口卸载时执行HTTP请求。如果无法避免,则有常见的解决方案(如问题所述):

  1. 同步调用ajax,即async: false
    • 优点:在大多数情况下工作。<<li>优点:沉默/gh>缺点:在某些情况下不工作,例如,当用户刷新窗口几次太快(在Firefox中观察到)
  2. successajax呼叫后使用alert
    • 优点:似乎在所有情况下工作。
    • 缺点:不静音,并触发弹出警报。

根据unload文档,使用 async: false 它应该按预期工作。然而,这总是有点不稳定——例如,用户可以通过杀死/崩溃浏览器来离开你的页面,而你不会收到任何回调。此外,浏览器的实现也各不相同。恐怕你连万无一失的办法都没有。

HTTP是无状态的,你永远无法得到一个可靠的方法来检测用户是否离开了你的页面。

建议事件:

  • 会话超时(如果您正在使用会话)
  • 应用程序正在关闭
  • 一个定时器(需要结合前面的建议)
  • 在访问新页面时删除前一个令牌

为什么需要发生这种情况?

从你发布的代码片段,你正试图使用它来处理对象服务器端?您应该调用Dispose来释放对象正在使用的任何非托管资源(例如数据库连接)。

这应该在处理每个请求期间完成。当客户端关闭浏览器窗口时,不应该有任何未管理的资源等待处置。

如果这是您尝试以上述方式执行此操作的方式,则需要重新编写代码。

你试过 onbeforeunload () ?

$(window).bind('beforeunload', function() 
    { 
        alert('unloading!'); 
    } 
);

window.onbeforeunload = function() {
    alert('unloading!'); 
}

从您对@Frazzell的回答的评论来看,听起来您正在尝试管理并发性。因此,如果出现这种情况,这里有两种常见的管理方法。

乐观并发

乐观并发向表中添加时间戳。当客户端编辑记录时,时间戳将包含在表单中。当它们发布更新时,也会发送时间戳,并检查值以确保它是表中最近的。如果是,则更新成功。如果不是,那么其他人会更快地更新,因此它被丢弃。如何处理这个问题取决于你自己。

悲观并发

如果您经常遇到并发冲突,那么悲观并发可能更好。在这里,当客户端编辑记录时,在该行上设置一个标志来锁定它。这将一直保持到客户端完成编辑,并且没有其他用户可以编辑该行。此方法避免了用户丢失更改,但在应用程序中添加了管理。现在您需要一种方法来释放不需要的锁。您还必须通过UI通知用户一行被锁定以进行编辑。

根据我的经验,最好从乐观并发开始。如果有很多人报告问题,我会试图找出人们发生这些冲突的原因。也许我必须把一些实体分解成更小的类型,因为它们已经承担了太多的工作。

这是行不通的,即使你能够以某种方式使它工作,它也会给你带来很多麻烦,因为这不是浏览器/HTTP应该使用的方式。当页面卸载时(在浏览器中),浏览器将调用卸载事件,然后卸载页面(你不能让它等待,甚至不是我的同步ajax调用),如果调用正在进行,浏览器在执行代码卸载页面后,调用也会被取消,这就是为什么你有时会在服务器上看到调用,有时它不工作。如果你能告诉我们为什么你想这样做,我们可以建议你一个更好的方法。

你不能。你唯一能做的就是提示用户留下来,并期待最好的结果。这里有一大堆安全问题。

最新更新