ASP.NET AJAX示例:文档锁定程序
此示例属于简单的文档管理系统。如任何正式的文档管理系统一样,我们必须提供并发管理。即,我们需要一种方法来处理两个用户尝试编辑同一个文档的问题。我们将通过创建某种类型的锁定机制,来使正在编辑的文档不能再由另一个用户编辑,从而达到上述目的。我们将利用 AJAX 让用户有更愉快的锁定机制体验。首先,我们将创建用户尝试编辑但无法编辑(因为其他用户正在编辑该文档)的文档队列,当这些文档可用时自动通知用户。其次,我们将确保当用户关闭其浏览器或导航到其他位置时,解除对文档的锁定。后一个功能帮助确保文档不会永远处于锁定状态。为此,在本指南中,我们将跳过与 AJAX 实现不相关的功能;但是,可下载项目包含所有功能。
首先,当用户尝试编辑文档时,我们会尝试对其建立排它锁,如果失败,我们会将此文档添加到用户的队列然后使其返回到主页。对此处的 AJAX 没有什么特别之处,但是我们将查看一下代码,以便给出示例必要的上下文。在用于编辑的 Page 的 OnLoad 事件中,添加以下代码。
- //C#:ASP.NET AJAX示例
- if (!Page.IsPostBack)
- {
- //应验证用户输入
- Document document = GetDocument(Request.QueryString["id"]);
- //我们拥有此文档,但不能编辑它!
- if (!Locker.AcquireLock(document))
- {
- //让我们将它添加到要查看的用户文档列表
- User.CurrentUser.AddDocumentToQueue(document.DocumentId);
- Response.Redirect("DocumentList.aspx");
- }
- //好了,我们拥有此文档,并且可以编辑它
- //...
- }
关键行的位置是将文档添加到当前用户的队列中(这会将文档添加到会话中)。接下来,我们将创建用户控件,该控件可以被放置到任何页上,用于当队列文档可用时通知用户。此用户控件将包含一个 AJAX 方法以及注册 AJAX 的类所需的代码。
- 'VB.NET:ASP.NET AJAX示例
- Private Sub Page_Load(s As Object, e As EventArgs)
- Handles MyBase.Load
- Ajax.Utility.RegisterTypeForAjax(GetType(UnlockNotifier))
- End Sub
- '遍历队列文档并检查它们是否可用
- < Ajax.AjaxMethod()> _
- Public Function GetUnlockedDocuments() As DocumentCollection
- '获得属于用户的所有队列文档的 ID
- Dim queuedDocument As ArrayList = User.CurrentUser.DocumentQueue
- Dim unlocked As DocumentCollection = New DocumentCollection
- For Each documentId As Integer In queuedDocumentIds
- '如果队列文档不再被锁定
- If Not Locker.IsLocked(documentId) Then
- unlocked.Add(Document.GetDocumentById(documentId))
- End If
- Next
- Return unlockedDocuments
End Function现在需要的是使一些 JavaScript 发出请求并处理响应。我们将基于响应在要动态创建的表中放置已发布的文档信息(如果有)。为此,我们将开始编写 HTML。
- < div id="notifyBox" style="display:none;">
- < b>The following queued documents can now be edited< /b>
- < table cellpadding="5" cellspacing="0"
- border="0" style="border:1px solid #EEE;"
- id="notifyTable">
- < /table>
- < /div>
如果没有可用的文档(或是没有为该用户列出文档),我们使用 DIV 标记隐藏所有内容,用 TABLE 标记来显示结果。我们将使用轮询系统来检查是否存在任何可用的队列文档。一般来说,这意味着我们将在稍后一段时间内一直调用服务器端方法,并显示结果。在加载页面时仅发生第一次调用,每隔 X 秒发生后续调用。
- < script language="javascript">
- window.setTimeout("PollQueue();", 2000);
- //每隔 2 秒激发以检查在具有许多用户的实际系统中是否发布了
- //队列文档,2 秒可能会使服务器承受
- //过高的负荷。我们甚至可以首先检查用户是否
- //拥有队列,但是我们确实需要进行一些
- //性能测试
- function PollQueue()
- {
- //UnlockNotifier 是我们使用 Ajax.NET 注册的类型
- //GetUnlockedDocuments 是该类型中的方法,标有
- //AjaxMethod 属性
- UnlockNotifier.GetUnlockedDocuments(PollQueue_CallBack);
- //每隔 2 秒调用其本身
- window.setTimeout("PollQueue();", 2000);
- }
- < /script>
剩下的就是处理响应。这与以前示例中的代码相似。首先,检查是否存在错误,获得响应,遍历可用的文档,动态创建 HTML,在这种情况下,向表中添加行和列。
- function PollQueue_CallBack(response)
- {
- var notifyBox = document.getElementById("notifyBox");
- var notifyTable = document.getElementById("notifyTable");
- //如果我们无法找到表通知框
- if (notifyBox == null || notifyTable == null)
- {
- return;
- }
- //如果服务器端代码出现异常
- if (response.error != null)
- {
- notifyBox.style.display = "none";
- alert(response.error); //我们应该能做得更好
- return;
- }
- var documents = response.value;
- //如果不是我们所希望的响应
- if (documents == null || typeof(documents) != "object")
- {
- notifyBox.style.display = "none";
- return;
- }
- for (var i = 0; i < notifyTable.rows.length; ++i)
- {
- notifyTable.deleteRow(i);
- }
- for(var i = 0; i < documents.length; ++i)
- {
- var row = notifyTable.insertRow(0);
- row.className = "Row" + i%2;
- var cell = row.insertCell(0);
- cell.innerHTML = documents[i].Title;
- cell = row.insertCell(1);
- var date = documents[i].Created;
- cell.innerHTML = date.getDay() + "/" + date.getMonth()
- + "/" + date.getYear();
- cell = row.insertCell(2);
- cell.innerHTML = "< a href='DocumentEdit.aspx?id="
- + documents[i].DocumentId + "'>edit< /a>";
- }
- notifyBox.style.display = "block";
- }
我们要看到的最后一个快速改进是当用户关闭浏览器、导航到其他链接或单击“后退”按钮时,将自动解除文档锁定。通常,可以通过触发 JavaScript OnBeforeUnLoad 事件或 OnUnload 事件达到此目的,这会打开新的小型弹出式窗口,该弹出式窗口在加载页面时做一些清理然后自行关闭。您自己可以使用弹出式窗口,但是其他人则不能使用,它将导致弹出式窗口受阻并使文档永久保持锁定状态。要解决此问题,我们仍需要两个 JavaScript 事件,但是并不是启动弹出式窗口,而是将通过 AJAX 执行服务器端方法。在用于编辑文档的页上(即,放置锁的页),我们添加一些简单的 JavaScript。
- < script language="javascript">
- //如果用户关闭浏览器或点击“后退”按钮,
- //确保该文档会被解除锁定
- window.onbeforeunload = ReleaseLock;
- function ReleaseLock() {
- Locker.ReleaseDocument(< %=DocumentID%>);
- }
- < /script>
在这里,DocumentId 是在后面的代码中定义和设置的变量。另外,我们可以在会话中存储 DocumentId,并在服务器端 ReleaseDocument 中访问。通常,ReleaseDocument 从锁定的文档列表中删除文档。
以上就是ASP.NET AJAX示例:文档锁定程序的实现。
【编辑推荐】