软件下载 | 资讯教程 | 最近更新 | 下载排行 | 一键转帖 | 发布投稿
您的位置:最火下载站 > 网络编程 > ASP.NET > ASP.NET MVC使用UpdatePanel的方法

ASP.NET MVC使用UpdatePanel的方法

ASP.NET AJAX中的UpdatePanel相信大家都有所了解,可惜的是,ASP.NET MVC框架的诞生“毁灭”了大量基于PostBack的控件,首当其冲地可能就是UpdatePanel了。如果没有 PostBack,UpdatePanel就失去了全部作用,甚至不如一些绑定控件,至少它们还能够用于展示。为UpdatePanel长吁短叹之后,我们不禁又开始怀念UpdatePanel的优势:“透明”。在UpdatePanel的帮助下,实现AJAX操作对于开发人员几乎完全透明。我们要做的仅 仅是将需要AJAX更新的内容用UpdatePanel包装起来,一切都是那么优雅。
我们能否在ASP.NET MVC中拯救UpdatePanel呢?也许是可以的吧,但这更像是一个“不可能完成的任务”。我不是传说中的阿汤哥,因此重新为ASP.NET MVC量身定制一个AJAX解决方案似乎更为可行。虽然我们不会苛求一个新生事物从诞生开始就趋向完美,但即使只是一个原型,它也必须严格遵守的一些原则:

◆不得破坏MVC中的协议(协作,职责等等)

◆ 对开发人员尽可能地透明Nikhil Kothari曾经提出了他在ASP.NET MVC框架下的AJAX解决方案。如果您还不了解他的做法,那么我先在这里进行一点概括。Nikhil扩展了Controller使之支持一种Ajax操作,于是我们在代码中就可以写如下代码:

public class TaskListController : AjaxController {

public void CompleteTask(int taskID) {
if (String.IsNullOrEmpty(Request.Form["deleteTask"]) == false) {
InvokeAction("DeleteTask");
return;
}

Task task = _taskDB.GetTask(taskID);
if (task != null) {
_taskDB.CompleteTask(task);
}

if (IsAjaxRequest) {
if (task != null) {
RenderPartial("TaskView", task);
}
}
else {
RedirectToAction("List");
}
}

}

与AjaxController类似,Nikhil也为ViewPage和ViewControl提供了一些扩展方法,因此目前在View(List.aspx)中我们就能看到如下的代码:

<div id="taskList">
<% foreach (Task task in Tasks) { %>
<div>
<% this.RenderPartial("TaskView", task); %>
</div>
<% } %>
</div>

在 View和Controller中都存在对于RenderPartiel方法的调用,它们的作用就是向客户端输出一个“Partial Template”生成的HTML代码。而在ASP.NET MVC的默认配置中,Partial Template即为User Control。而在TaskView这个Partial Template中可以看到一些辅助方法:

<div id="taskItem<%= Task.ID %>< span style="color: #800000;">" class="taskPanel">
<% Ajax.Initialize(); %>
<% this.RenderBeginAjaxForm(
Url.Action("CompleteTask"),
new {
Update = "taskItem" + Task.ID,
UpdateType = "replace",
Completed = "endUpdateTask"}); %>

<input type="hidden" name="taskID" value="<%= Task.ID %>" />
<input type="submit" class="completeButton" name="completeTask" value="Done!" />
<input type="submit" class="deleteButton" name="deleteTask" value="Delete" />
<span><%= Html.Encode(Task.Name) %></span>

<% this.RenderEndForm(); %>
<% Ajax.RenderScripts(); %>
</div>
这些辅助方法的作用是生成一些触发AJAX更新的标签及脚本,当用户点击RenderBeginAjaxForm与RenderEndForm方法生成的 tag之间的提交按钮时,网页将会向服务器端发出一个AJAX请求,而服务器端的Action并最终会通过RenderPartial方法输出一个 Partial Template生成的HTML。

服务器端最终输出的HTML将会被替换或添加到页面的某个元素内。这就形成了一个 AJAX效果。这个解决方案从某些方面看上去很酷,尤其是生成的代码可以添加到某个元素中,而不单单是如同UpdatePanel的替换,例如 Nikhil在他的例子中就使用了这个特性实现了一个添加功能。不过如果使用之前提出的原则来衡量的话,似乎这个解决方案并不十分理想。

原因很简单,因为不够透明。

也有评论认为,Controller中的逻辑不该根据一个请求AJAX与否而进行不同处理(Nikhil的解决方案使用RenderPartial来替代 RenderView为AJAX操作进行输出),因此这个解决方案破坏了MVC的职责。我不这么认为,但是我希望能做到这一点,因为做到这一点即意味着绝对的透明。绝对透明则意味着Controller将一个应用程序是否AJAX的决定权完全交给了客户端,这点非常理想,因为AJAX完全是一个表现层的概念。ASP.NET AJAX中的UpdatePanel在这方面的表现可圈可点(虽然还远不够完美),因此我最后决定也为ASP.NET MVC开发一款类似UpdatePanel的组件。值得庆幸的是,ASP.NET MVC默认使用WebForm页面作为视图模板,在这个强大的模型之下,构建出这样一个AJAX解决方案(的原形)似乎并不十分困难。

我将这个控件命名为MvcAjaxPanel。MvcAjaxPanel与UpdatePanel最大的区别在于后者接收的是PostBack,而前者接收的只是普通的HTTP请求。Post“Back”意味着Post过后回到了原来的Page,而ASP.NET MVC的请求往往会被引导至不同的页面。因此如何跨页面进行内容更新是MvcAjaxPanel首要解决的问题。最终我选择了为每个 MvcAjaxPanel指定一个UpdateAreaID的做法。

<mvc:MvcAjaxPanel runat="server" ID="mvcAjaxPanel" UpdateAreaID="Header">

</mvc:MvcAjaxPanel>

当页面向服务器端发出一个AJAX请求时将会附带页面中的UpdateAreaID信息,而服务器端的Action并不会意识到这一点,因此依旧按照寻常逻辑指定一个视图模版并输出HTML。不过,如果视图模板中的MvcAjaxPanel发现这个请求实际上是一个符合约定的AJAX请求(请注意,只有 View组件意识到这是个请求的性质),则会使用新的方法来替换标准的输出。这时候模板就会根据客户端传递过来的UpdateAreaID,寻找页面上具有同样属性值的MvcAjaxPanel,有选择性地输出内容。在客户端就会有对应的JavaScript代码接收服务器端的数据,并且更新页面中的相应区域。

很明显,MvcAjaxPanel的工作原理与UpdatePanel有颇多相似之处,也做到了一定程度上的透明。而且与 Nikhil的解决方案相比,一个非常重要的优势就是可以一次更新页面中的多个区域——其实这也就是 UpdatePanel的特性之一。而且这种对 Controller透明的做法又有一个天然的特点,那就是能够轻松地在不支持AJAX的浏览器中使用传统的方式切换页面。

相关阅读
栏目导航
推荐软件