尽管 AJAX 取得成功并得到采用,但仍缺乏不借助 Silverlight 或 Flash 即可在 Web 应用程序中显示上下文相关进度栏的被广泛接受的综合解决方案。
这个月,我重新讨论同一主题,但我将讨论如何使用以下仍在不断完善的新库构建进度栏: SignalR。
它提供了一些前景极为光明的功能,而这些功能正是 .NET Framework 当前不曾具有的,并且是越来越多的开发者所需要的。
SignalR 概览
对话通过永久连接进行,允许客户端向服务器发送多个消息,并允许服务器做出相应答复,值得注意的是,还允许服务器向客户端发送异步消息。
客户端通过向服务器发送消息来开始对话;服务器(ASP.NET 终结点)答复并持续侦听新请求。
中看到的其他包用于其他特定目的,例如提供 .NET 客户端、Ninject 依赖关系解析程序和基于 HTML5 Web 套接字的备用传输机制。
图 1 NuGet 平台上提供的 SignalR 包
深入探讨聊天示例
但请注意,SignalR 不是已发布项目。
在 ASP.NET MVC 项目的上下文中,您首先引用一些脚本文件,如下所示:
- <script src="@Url.Content("~/Scripts/jquery-1.6.4.min.js")"
- type="text/javascript"></script>
- <script src="@Url.Content("~/Scripts/jquery.signalr.min.js")"
- type="text/javascript"></script>
- <script src="@Url.Content("~/signalr/hubs")"
- type="text/javascript"></script>
请注意,SignalR 中没有任何内容是特定于 ASP.NET MVC 的,此库同样可用于 Web 窗体应用程序。
还请注意,如果您打算支持低于 Internet Explorer 8 版的版本,则需要 JSON2 库。
代码将脚本处理程序绑定到 HTML 元素(非介入式 JavaScript)并准备 SignalR 对话。
图 2 为聊天示例建立 SignalR 库
- <script type="text/javascript">
- $(document).ready(function () { // Add handler to Send button
- $("#sendButton").click(function () {
- chat.send($('#msg').val());
- });
- // Create a proxy for the server endpoint
- var chat = $.connection.chat;
- // Add a client-side callback to process any data
- // received from the server
- chat.addMessage = function (message) {
- $('#messages').append('<li>' + message + '</li>');
- };
- // Start the conversation
- $.connection.hub.start();
- });
- </script>
中的客户端代码如果没有强大的服务器端对应部分,则没有多大意义(和作用)。
下面是类签名:
- using System;
- using SignalR.Hubs;
- namespace SignalrProgressDemo.Progress
- {
- public class Chat : Hub
- {
- public void Send(String message)
- {
- Clients.addMessage(message);
- }
- }
- }
中的 Chat 对象具有 addMessage 方法,所以要求服务器端 Chat 对象也公开相同的 addMessage 方法。
准备进度栏演示
下面是签名:
- public class BookingHub : Hub
- {
- ...
- }
例如,让我们添加一个方法来预订机票:
- public void BookFlight(String from, String to)
- {
- ...
- }
假设 BookFlight 方法的框架如下所示:
- public void BookFlight(String from, String to)
- {
- // Book first leg var ref1 = BookFlight(from, to); // Book return flight
- var ref2 = BookFlight(to, from);
- // Handle payment
- PayFlight(ref1, ref2);
- }
然后,让我们转到客户端。
首先,获取服务器对象的代理:
- var bookingHub = $.connection.bookingHub;
- // Some config work
- ...
- // Open the connection
- $.connection.hub.start();
您可以将单击处理程序添加到 HTML 按钮中并通过 AJAX 启动服务器操作,如下所示:
- bookingHub.bookFlight("fco", "jfk");
例如,您可以在客户端代理上定义接收消息并通过 HTML 范围标记显示消息的 displayMessage 方法:
- bookingHub.displayMessage = function (message) {
- $("#msg").html(message);
- };
您决定传递什么内容和要求任何输入是什么类型。
显示了 Hub 类的最终版本。
图 3 Hub 类的最终版本
- public void BookFlight(String from, String to)
- {
- // Book first leg
- Clients.displayMessage( String.Format("Booking flight: {0}-{1} ...", from, to));
- Thread.Sleep(2000);
- // Book return
- Clients.displayMessage( String.Format("Booking flight: {0}-{1} ...", to, from));
- Thread.Sleep(3000);
- // Book return
- Clients.displayMessage( String.Format("Booking flight: {0}-{1} ...", to, from));
- Thread.Sleep(2000);
- // Some return value
- Clients.displayMessage("Flight booked successfully.");
- }
如果您将它错误键入为 DisplayMessage 之类,则不会获得任何异常,但也不会执行任何代码。
Hub 代码作为 Task 对象实现,因此它获取自己的线程来运行,并且不会影响 ASP.NET 线程池。
当收到消息并且有要执行的工作时,将使用 ASP.NET 工作线程。
使用 HTML 的真正进度栏
您可以通过合适的 CSS 类来更改 HTML 元素的外观。
图 4 创建基于 HTML 的规杆
- var GaugeBar = GaugeBar || {};
- GaugeBar.generate = function (percentage) {
- if (typeof (percentage) != "number")
- return;
- if (percentage > 100 || percentage < 0)
- return;
- var colspan = 1;
- var markup = "<table class='gauge-bar-table'><tr>" +
- "<td style='width:" + percentage.toString() +
- "%' class='gauge-bar-completed'></td>";
- if (percentage < 100) {
- markup += "<td class='gauge-bar-tobedone' style='width:" +
- (100 - percentage).toString() +
- "%'></td>";
- colspan++;
- }
- markup += "</tr><tr class='gauge-bar-statusline'><td colspan='" +
- colspan.toString() +
- "'>" +
- percentage.toString() +
- "% completed</td></tr></table>";
- return markup;
- }
您从按钮单击处理程序调用此方法:
- bookingHub.updateGaugeBar = function (perc) {
- $("#bar").html(GaugeBar.generate(perc));
- };
您可以将以前使用的 displayMessage 替换为 Hub 方法中的 updateGaugeBar。
不仅是 Web 客户端
您可以为 .NET 桌面应用程序下载客户端,而且将很快发布支持 Windows Phone 客户端的另一个客户端。
请继续关注。