65.9K
CodeProject 正在变化。 阅读更多。
Home

使用jQuery全局AJAX事件处理程序的示例

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.81/5 (11投票s)

2012 年 5 月 11 日

CPOL

7分钟阅读

viewsIcon

90178

downloadIcon

1809

本文介绍一个使用 jQuery 全局 AJAX 事件处理程序的示例。

介绍 

本文介绍一个使用 jQuery 全局 AJAX 事件处理程序的示例。

背景  

jQuery 提供了一系列 全局 AJAX 事件处理程序。如果 jQuery.ajaxSetup() 中的 global 属性为 true(默认即为 true),则每个 AJAX 请求都会触发这些全局事件。

  • .ajaxStart - 注册一个处理程序,在第一个 AJAX 请求开始时调用;
  • .ajaxSend - 附加一个函数,在发送 AJAX 请求之前执行;
  • .ajaxError - 注册一个处理程序,在 AJAX 请求发生错误完成时调用;
  • .ajaxSuccess - 附加一个函数,在每次 AJAX 请求成功完成时执行;
  • .ajaxComplete - 注册一个处理程序,在 AJAX 请求完成时调用;
  • .ajaxStop - 注册一个处理程序,在所有 AJAX 请求都完成后调用。

将所有 AJAX 请求通用的操作放在这些事件处理程序中是理想的做法,以简化每个请求的实现。在本文中,我将向您展示如何使用这些事件处理程序来实现以下功能:

  • 在 AJAX 请求进行过程中显示忙碌图标并阻止 UI;
  • 在遇到 AJAX 错误时显示错误消息;
  • 在 AJAX 请求时,如果 Web 会话过期,则将用户重定向到登录页面。

附件项目是使用 Visual Studio 2010 开发的 MVC 3 应用程序。

此示例应用程序使用了以下 JavaScript 库:

  • jquery-1.7.2.min.js - 示例开发时 jQuery 的最新版本。
  • jquery.blockUI-2.39.js - jQuery BlockUI 插件。此插件用于在 AJAX 请求进行过程中显示忙碌图标并阻止 UI。
  • jquery.colorbox-min.js - "ColorBox" 插件。此插件用于在遇到 AJAX 错误时显示消息。

除了这些 JavaScript 库,示例应用程序还包含以下主要组件:

  • AjaxGlobalHandler.js 文件是使用 jQuery 全局事件处理程序的地方;
  • Login\Index.cshtml 文件是用户可以登录 Web 应用程序的网页;
  • Home\Index.cshtml 文件是使用 AjaxGlobalHandler.js 文件中实现的功能的网页;
  • ActionFilters\AjaxSessionActionFilter.cs 文件实现了一个 Action Filter。它将用于检查用户的登录会话。如果会话过期,它将根据控制器操作是被 AJAX 请求访问还是常规 Web 请求访问,来将网页重定向到登录页面或向调用方发送预定义的 HTTP 状态码。
  • LoginController.csHomeController.cs 文件是这两个网页的控制器。

我将首先介绍 AjaxGlobalHandler.js 文件以及 ActionFilters\AjaxSessionActionFilter.cs 文件中实现的 Action Filter。然后,我将向您展示如何在网页中使用它们。

"AjaxGlobalHandler.js" 文件  

AjaxGlobalHandler.js 文件是一个非常简单的 JavaScript 文件,其实现如下: 

var AjaxGlobalHandler = {
    Initiate: function (options) {
        $.ajaxSetup({ cache: false });
    
        // Ajax events fire in following order
        $(document).ajaxStart(function () {
            $.blockUI({
                message: options.AjaxWait.AjaxWaitMessage,
                css: options.AjaxWait.AjaxWaitMessageCss
            });
        }).ajaxSend(function (e, xhr, opts) {
        }).ajaxError(function (e, xhr, opts) {
            if (options.SessionOut.StatusCode == xhr.status) {
                document.location.replace(options.SessionOut.RedirectUrl);
                return;
            }
    
            $.colorbox({ html: options.AjaxErrorMessage });
        }).ajaxSuccess(function (e, xhr, opts) {
        }).ajaxComplete(function (e, xhr, opts) {
        }).ajaxStop(function () {
            $.unblockUI();
        });
    }
};

尽管 jQuery 有六个全局 AJAX 事件,但为了实现本示例的目标,我只使用了 .ajaxStart.ajaxError.ajaxStop 事件。在此示例中,我对其余事件中的每个事件都提供了一个空处理程序。空处理程序的目的是仅仅在此保留记录,以备将来在其他项目中使用。

  • .ajaxSetup 事件中,初始化 BlockUI 以告知用户 AJAX 请求正在进行。它还会阻止可能的用户交互。
  • .ajaxError 事件中,代码会检查错误是否是由于 Web 会话过期引起的。如果是,它会将页面重定向到登录页面。否则,将在 ColorBox 中显示一条错误消息。
  • .ajaxStop 事件中,移除 BlockUI,以告知用户 AJAX 请求已完成。 

在向您展示如何使用这个小型 JavaScript 文件之前,我将首先向您介绍 Action Filter。 

"AjaxSessionActionFilter.cs" 文件 

AjaxSessionActionFilter.cs 文件实现了一个 Action Filter: 

using System.Web.Mvc;
using AjaxGlobalEventExample.Constants;
    
namespace AjaxGlobalEventExample.ActionFilters
{
    public class AjaxSessionActionFilter : ActionFilterAttribute
    {
        public override void OnActionExecuting(ActionExecutingContext filterContext)
        {
            var request = filterContext.HttpContext.Request;
            var response = filterContext.HttpContext.Response;
            var session = filterContext.HttpContext.Session;
    
            if (session[SessionVariables.IsLoggedIn] == null)
            {
                if (request.IsAjaxRequest())
                {
                    response.StatusCode = 590;
                }
                else
                {
                    var url = new UrlHelper(filterContext.HttpContext.Request.RequestContext);
                    response.Redirect(url.Action("Index", "Login"));
                }
    
                filterContext.Result = new EmptyResult();
            }
    
            base.OnActionExecuting(filterContext);
        }
    }
}

如果配置得当,此 Action Filter 将在控制器操作执行之前执行。如果 Web 会话不存在,并且,

  • 如果请求是 AJAX 请求,它将向客户端发送 状态码 590;
  • 如果请求是常规 Web 请求,它将把页面重定向到登录页面。 

状态码 590 是一个自定义定义的。通过将此代码发送到客户端,客户端将识别出 Web 会话不存在。 

登录页面和控制器  

Login\Index.cshtml 文件实现如下:

@{ Layout = null; }
    
<!DOCTYPE html>
    
<html>
<head>
    <title>Login</title>
    <link href="@Url.Content("~/Content/Site.css")" 
              rel="stylesheet" type="text/css" />
    
    <style type="text/css">
        .outerdiv {width: 100%;}
        .innerdiv {width: 250px; margin-left: auto; margin-right: auto;}
    </style>
        
    <script type="text/javascript">
        function Login() {
            document.location.replace('@Url.Action("LoginAction", "Login")');
        }
    </script>
</head>
<body>
    <div class="outerdiv">
        <div class="innerdiv">
            <table style="margin: 0px">
                <tr><td style="text-align: center">Everyone is welcome to login</td></tr>
                <tr>
                    <td style="text-align: center">
                        <a href="#" class="CoolButton" style="width: 200px"
                           onclick="return Login()">Click to log in</a>
                    </td>
                </tr>
            </table>
        </div>
    </div>
</body>
</html>

cshtml 页面只有一个按钮。单击此按钮将调用 LoginController.cs 文件中实现的 LoginAction 操作方法。

using System.Web.Mvc;
using AjaxGlobalEventExample.Constants;
	
namespace AjaxGlobalEventExample.Controllers
{
    public class LoginController : Controller
    {
        public ActionResult Index()
        {
            return View();
        }
	
        public ActionResult LoginAction()
        {
            // Any request to login is granted and session is set
            Session[SessionVariables.IsLoggedIn] = true;
            return new RedirectResult(Url.Action("Index", "Home"));
        }
    }
}

为简单起见,LoginAction 方法不要求任何用户凭据。它只是启动 Web 会话。这意味着任何人都可以登录 Web 应用程序。一旦建立 Web 会话,用户将被重定向到 Home\Index.cshtml 页面。  

"Home\Index.cshtml" 页面和控制器 

Home\Index.cshtml 页面实现如下: 

@{ Layout = null; }
    
<!DOCTYPE html>
    
<html xmlns="http://www.w3.org/1999/xhtml">
    <head>
        <title>Global Ajax Event Handler</title>
            
        <link href="@Url.Content("~/Content/Site.css")"
            rel="stylesheet" type="text/css" />
        <link href="@Url.Content("~/Content/ColorBox/colorbox.css")"
            rel="stylesheet" type="text/css" />
            
        <script src="@Url.Content("~/Scripts/jquery/jquery-1.7.2.min.js")"
            type="text/javascript"></script>
        <script src="@Url.Content("~/Scripts/ColorBox/jquery.colorbox-min.js")"
            type="text/javascript"></script>
        <script src="@Url.Content("~/Scripts/jquery/jquery.blockUI-2.39.js")"
            type="text/javascript"></script>
        <script src="@Url.Content("~/Scripts/AjaxGlobalHandler.js")"
            type="text/javascript"></script>
    
        <script type="text/javascript">
            var waitimageUrl = '@Url.Content("~/Content/images/Wait.gif")';
            var sessionoutRedirect = '@Url.Action("Index", "Login")';
            $(document).ready(function () {
                var options = {
                    AjaxWait: {
                        AjaxWaitMessage: "<img style='height: 40px' src='"
                            + waitimageUrl + "' />",
                        AjaxWaitMessageCss: { width: "50px", left: "45%" }
                    },
                    AjaxErrorMessage: "<h6>Error! please contact the monkey!</h6>",
                    SessionOut: {
                        StatusCode: 590,
                        RedirectUrl: sessionoutRedirect
                    }
                };
    
                AjaxGlobalHandler.Initiate(options);
            });
        </script>
            
        <script type="text/javascript">
            var urlSuccess = '@Url.Action("ExampleAjaxAction", "Home")';
            var urlError = '@Url.Action("ExampleAjaxError", "Home")';
            var urlClearSession = '@Url.Action("ExampleAjaxClearSession", "Home")';
    
            $(document).ready(function () {
                $("#btnSuccessAjax").click(function () {
                    $.ajax({
                        url: urlSuccess,
                        success: function (data) {
                            $("#divMessage").html(data.Message);
                        }
                    });
                });
    
                $("#btnErrorAjax").click(function () {
                    $.ajax({ url: urlError });
                });
    
                $("#btnClearSession").click(function () {
                    $.ajax({
                        url: urlClearSession,
                        success: function (data) {
                            $("#divMessage").html(data.Message);
                        }
                    });
                });
    
            });
        </script>
    </head>
    
    <body>
        <div id="divMessage" style="font-weight: bold; color: green"></div>
        <div style="margin-top: 5px">
            <a href="#" class="CoolButton" id="btnSuccessAjax">Success Call</a>
            <a href="#" class="CoolButton" id="btnErrorAjax">Error Call</a>
            <a href="#" class="CoolButton" id="btnClearSession">Clear Session</a>
        </div>
    </body>
</html> 

此页面引用了 AjaxGlobalHandler.js 文件。jQuery 全局事件处理程序在 $(document).ready() 事件中初始化。处理程序使用以下信息进行初始化:

  • 在 AJAX 请求进行过程中要显示的图像;
  • 在 AJAX 调用期间发生错误时要显示的错误消息;
  • Web 会话过期时要将用户重定向到的页面。

此页面还有三个按钮。单击每个按钮将向 HomeController.cs 类中实现的相应操作方法发出 AJAX 调用。

using System;
using System.Threading;
using System.Web.Mvc;
using AjaxGlobalEventExample.ActionFilters;
    
namespace AjaxGlobalEventExample.Controllers
{
    [AjaxSessionActionFilter]
    public class HomeController : Controller
    {
        public ActionResult Index()
        {
            return View();
        }
    
        public ActionResult ExampleAjaxAction()
        {
            Thread.Sleep(500);
            string msg = "Ajax call succeeded @ " + DateTime.Now.ToLongTimeString();
            return Json(new { Message = msg }, JsonRequestBehavior.AllowGet);
        }
    
        public ActionResult ExampleAjaxError()
        {
            Thread.Sleep(500);
            // Return the famous 500 staus to create an artificial error
            Response.StatusCode = 500;
            Response.End();
            return new EmptyResult();
        }
    
        public ActionResult ExampleAjaxClearSession()
        {
            Thread.Sleep(500);
            Session.Clear();
            string msg = "Web session cleared @ " + DateTime.Now.ToLongTimeString();
            return Json(new { Message = msg }, JsonRequestBehavior.AllowGet);
        }
    }
}
  • ExampleAjaxAction 方法仅返回一个 JSON 对象,表示 AJAX 请求成功;
  • ExampleAjaxError 方法向客户端发送著名的状态码 500,表示 AJAX 错误;
  • ExampleAjaxClearSession 方法清除 Web 会话。

我在每个操作方法中人为地添加了半秒的延迟,以便 Web 应用程序能够更好地向我们展示 AJAX 请求过程。您还应该注意到,此控制器类已用先前实现的 AjaxSessionActionFilter Action Filter 进行了注解。 

运行应用程序 

现在我们完成了这个示例 Web 应用程序,可以进行测试运行了。 

应用程序启动时,由于没有 Web 会话,用户将被重定向到登录页面。如果我们单击“Click to log in”按钮,Web 会话将建立,我们就会进入应用程序的主页面。 

如果我们单击“Success Call”按钮,将发出 AJAX 调用,并且我们可以看到 UI 被阻止,并且显示了忙碌图标。

如果我们单击“Error Call”按钮,将发生一个人为的 AJAX 错误,并显示错误消息。 

我们可以单击“Clear Session”按钮来清除 Web 会话。 

由于我们已清除 Web 会话,单击任何按钮都将把我们重定向到登录页面。 

兴趣点

  • 本文介绍了一个使用 jQuery 全局 AJAX 事件处理程序的示例。 
  • 您可以通过多种方式使用这些全局事件处理程序。在本示例中,我只展示了一个非常简单的用法,以解决一些非常常见的问题,从而简化 AJAX 调用。
  • 如果您有时间,可以将 AjaxGlobalHandler.js 文件扩展成一个 jQuery 插件。本文中我没有考虑这个扩展,而且我们已经有很多 jQuery 插件了。
  • 此示例还向我们展示了如何使用 Action Filters 来简化 MVC 编程。
  • 理想情况下,您应该在母版页中引用并初始化 AjaxGlobalHandler.js,这样它的功能就可以在应用程序的每个页面中使用了。在本示例中,我只是将其放入网页本身,以避免涉及母版页的复杂性。
  • 在您的应用程序中,您可能会遇到不需要这些全局事件触发的情况。在这些情况下,您可以在 AJAX 请求的实现中简单地设置 “global: false”。
  • 希望您喜欢我的帖子,希望本文能以任何方式帮助您。 

历史

  • 首次修订 - 2012/5/11。
© . All rights reserved.