写在前面:由于工作需要,本人刚接触asp.net mvc,虽然webform的项目干过几个。但是也不是很精通。抛开asp.net webform和asp.net mvc的各自优劣和诸多差异先不说。我认为虽然mvc和webform有诸多不同,但是也只是为了达到相同的目的而在各自的机制下采取了不同的手段而已。更何况它们都是基于asp.net框架的。因此在解决mvc开发过程中的问题时,我很容易联想到在webform下同样的问题是如何解决的。以此来作为对照。我姑且把这种方法叫做迁移学习法吧。我以"小孩之心"来揣测肯定有很多前辈也做样做过吧。
前几天有人问起一个问题:在webform中,异步请求可以跳转到当前页面后台的一个方法吗?就像mvc中跳转到当前控制器的action一样。我当时给出了参考方案:使用webmethod。是的,今天就围绕这个话题来展开。简单地讲讲在webform和mvc中的ajax异步请求。
webfrom中的ajax异步请求
先来扯个蛋。我们知道为了实现模型显示和逻辑的分离,webform采用了事件驱动。也就是事先注册好对应的操作的事件操作。这么一来,每次服务器控件的事件触发,都会page load一下。然后才执行相应的事件逻辑。这样做的一个后果是每次都要初始化页面的数据。为了平衡,又采用了viewstate,在Page_Load事件中加上if(Page.IsPostBack)的判断来过滤重复的初始化绑定工作。当然即使这样,还是引发了服务器回传,会导致页面全局的刷新(虽然省去了初始化数据绑定时的数据请求)。那么说了这么多废话,你自然而然的会想到要使用一种什么办法来阻止这种行为的发生。我们知道aspx页面实际上最后请求的是页面本身(也就是form表单生成的action指向自己)。在这之中,我们似乎可以察觉点什么。也就是如何实现请求自身的同时还能不导致界面的全部刷新,那么很自然地就想到了一种技术:回调。说了这么多,来段代码回顾下webform中使用jquery实现异步请求。
aspx: <%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Index.aspx.cs" Inherits="weixin_api.Index" %> <!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head runat="server"> <script src="Scripts/jquery-1.4.1.min.js"></script> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title></title> <script> $(function () { $("#btnTest").click(function () { $.ajax({ type: "POST", contentType: "application/json", url: "Index.aspx/SayHello", data: null, dataType: "json", success: function (msg) { alert(msg.d); } }); }); }); </script> </head> <body> <form id="form1" runat="server"> <div> <input type="button" id="btnTest" value="Test" /> </div> </form> </body> </html> aspx.cs: [System.Web.Services.WebMethod] public static string SayHello() { return "Hello"; }
从WebMethod属性不难看出这实际上还是应用了webservice组件的方式来实现的。当然ajax实现异步请求的资源可以使aspx、ashx、webservice等,其用法基本差不多,此处不作赘述。
mvc中的ajax异步请求
由于mvc采用基于路由映射,所以Controller中的Action可以直接通过url请求。下面是mvc中实现jquery局部刷新的实例
@model IEnumerable<MvcAppDemo.Models.MovieDB> @{ ViewBag.Title = "List"; } <p> <a href="#" id="Add">添加</a> <div id="create"></div> </p> <table> <tr> <th> @Html.DisplayNameFor(model => model.Title) </th> <th> @Html.DisplayNameFor(model => model.Director) </th> <th> @Html.DisplayNameFor(model => model.Date) </th> <th> Delete </th> </tr> @if (Model != null && Model.Count() != 0) { foreach (var item in Model) { <tr> <td> @Html.DisplayFor(modelItem => item.Title) </td> <td> @Html.DisplayFor(modelItem => item.Director) </td> <td> @Html.DisplayFor(modelItem => item.Date) </td> <td></td> </tr> } } </table> <script src="~/Scripts/jquery-1.8.2.min.js"></script> <script type="text/javascript"> $("#Add").click(function () { $.get("/Movies/Create", function (response) { $("#create").html(response); }); return false; }); }