Building Web Apps with SignalR, Part 1

In the first installment of app-building with SignalR, learn how to build a real-time chat application.

More on this topic:

Are you sick of that dreaded page refresh? Want to turn your Web application up to 11? If you've answered yes to either question, SignalR is for you. With SignalR, you can provide content to your users in real-time, all from ASP.NET. Most importantly, it's compatible with browsers ranging all the way back to IE6! SignalR uses WebSockets on supported browsers and will fall back to server-side events, Forever Frame, or AJAX long polling if needed. This means you can use a single library and not have to worry about that minutia.

There are two approaches you can use with SignalR to achieve real-time communications: a persistent connection or a hub. The persistent connection API allows you to keep open a persistent connection between the client and server to send and receive data. The hub API is an abstraction above the persistent connection API, and is suitable for remote procedure calls (RPC).

This article will focus on the persistent connection API. I believe the best way to learn a new technology is to build something useful with it, so we'll create a chat client using SignalR. To get started, create a new C# ASP.NET MVC 4 project from Visual Studio 2012, then select the Web API option for your project type. Next, install the Microsft SignalR pre-release NuGet package through the NuGet Package Manager (Figure 1).


[Click on image for larger view.]
Figure 1. Installing the SignalR pre-release NuGet package.

In order to support IE 6 and 7, install the JSON-js-json2 NuGet Package as well, as shown inFigure 2.


[Click on image for larger view.]
Figure 2. JSON2 NuGet package installation.

Without further ado, let's get started on this app. First create a new folder in the project named Chat. Then create a new class named ChatConnection within the Chat directory that inherits from PersistentConnection. You'll need to add a using statement for the Microsoft.AspNet.SignalR namespace.

Now open up the RouteConfig class under the App_Start folder in the project. Add a using statement for the Microsoft.Asp.Net.Signal namespace to the RouteConfig class:

using Microsoft.AspNet.SignalR;

Next, register the ChatConnection class to the "chat" route in the RegisterRoutes method in the RouteConfig class:

RouteTable.Routes.MapConnection<ChatConnection>("chat","chat/{*operation}");

Your completed RouteConfig class should resemble Listing 1.

Now to create the ChatData data structure that will be used to interchange data between the client and the server. Create a new class named ChatData with Message and Name string data type properties:

namespace VSMSignalRSample.Chat
{
public class ChatData
{
public string Name { get; set; }
public string Message { get; set; } public ChatData()
{
} public ChatData(string name, string message)
{
Name = name;
Message = message;
}
}
}

Now it's time to finish implementing the ChatConnection class, which will receive and broadcast chat messages. Add using statements for the System.Threading.Tasks and Newtonsoft.Json namespaces. Next, add a private Dictionary<string, string> to store the clients that connect to the chat room:

private Dictionary<string, string> _clients = new Dictionary<string, string>();

The PersistentConnection base class includes functionality for dealing asynchronously with a few critical server-side events such as a new connection, disconnection, reconnection and data retrieval. Let's implement the OnConnectedAsync event handler first. When a new user first joins the room, they're added to the _clients Dictionary object, which will be used to map the user's chosen chat name with their connectionId. Then a broadcast message is sent to all users, letting them know a new user has joined the chat room:

protected override Task OnConnectedAsync(IRequest request, string connectionId)
{
_clients.Add(connectionId, string.Empty);
ChatData chatData = new ChatData("Server", "A new user has joined the room.");
return Connection.Broadcast(chatData);
}

Now it's time to tackle data retrieval from a connected client through the OnReceivedAsync event handler. First, the JSON data object from the client is desterilized into a ChatData object through JSON.NET. Then the user's name is stored in the _clients dictionary. Finally, the user's ChatData is broadcast to all users:

protected override Task OnReceivedAsync(IRequest request, string connectionId, string data)
{
ChatData chatData = JsonConvert.DeserializeObject<ChatData>(data);
_clients[connectionId] = chatData.Name;
return Connection.Broadcast(chatData);
}

The last event to handle is client disconnection, via the OnDisconnectedAsync method. When a user disconnects, he or she is removed from the _clients dictionary. Then a message is broadcast to all users, letting them know a user has left the room:

protected override Task OnDisconnectAsync(IRequest request, string connectionId)
{
string name = _clients[connectionId];
ChatData chatData = new ChatData("Server", string.Format("{0} has left the room.", name));
_clients.Remove(connectionId);
return Connection.Broadcast(chatData);
}

Now it's time to create the client-side JavaScript that will communicate with the persistent chat connection to display incoming chat messages and chat room events to the user. Create a new JavaScript file named ChatR.js within the Scripts folder. The first step is to retrieve the server chat connection object through the SignalR JavaScript plug-in:

var myConnection = $.connection("/chat");

Next, the received event is set up to display a received chat message as a new list item element in the messages unordered list DOM element:

myConnection.received(function (data) {
$("#messages").append("<li>" + data.Name + ': ' + data.Message + "</li>");
});

After that, the error handler for the connection is set up to display a console warning. This is mainly to ease debugging of the chat connection:

myConnection.error(function (error) {
console.warn(error);
});

Lastly, a connection is initiated to the chat server and a continuation is set up to handle the message send button-click event. Within the button-click event handler, the user's name and message are retrieved from the name and message text boxes, respectively. Then the user's name and message are sent to the chat server as a JSON object, as shown in Listing 2.

Now it's time to set up the UI for the Web application. Add a new MVC View class to the Home directory, named ChatR, that binds to the Chat.ChatData model. In the bottom of the view add a script reference to the ~/Sciprts/ChatR.js script created earlier:

@{
ViewBag.Title = "Chat";
} <h2>Chat</h2> @using (Html.BeginForm()) {
@Html.EditorForModel(); <input id="send" value="send" type="button" />
<ul id="messages" style="list-style:none;"></ul>
} @section Scripts { <script src="~/Scripts/ChatR.js"></script> }

Now, add a controller action method named ChatR to the HomeController that returns a new view bound to an empty Chat.ChatData object:

public ActionResult ChatR()
{
var vm = new Chat.ChatData();
return View(vm);
}

That's it: sit back, relax and invite a few friends to try out your new chat app, shown in Figure 3.


[Click on image for larger view.]
Figure 3. The completed real-time chat application.

As you can, see SignalR is quite easy to work with and the PersistentConnection API is very flexible. With SignalR, you can tackle a plethora of real-time Web app use cases from business to gaming. Stay tuned for the next installment, which covers how to use the SignalR Hub API to create a dynamic form.

More on this topic:

About the Author

Eric Vogel is a Sr. Software Developer at Kunz, Leigh, & Associates in Okemos, MI. He is the president of the Greater Lansing User Group for .NET. Eric enjoys learning about software architecture and craftsmanship, and is always looking for ways to create more robust and testable applications. Contact him at vogelvision@gmail.com.

Building Web Apps with SignalR, Part 1的更多相关文章

  1. Building Modern Web Apps-构建现代的 Web 应用程序

    Building Modern Web Apps-构建现代的 Web 应用程序 视频长度:1 小时左右 视频作者:Scott Hunter 和 Scott Hanselman 视频背景:Visual ...

  2. Isomorphic JavaScript: The Future of Web Apps

    Isomorphic JavaScript: The Future of Web Apps At Airbnb, we’ve learned a lot over the past few years ...

  3. Why mobile web apps are slow

    http://sealedabstract.com/rants/why-mobile-web-apps-are-slow/ I’ve had an unusual number of interest ...

  4. Isomorphic JavaScript: The Future of Web Apps(译)

                                                                                                 Isomorp ...

  5. appium(4)-Automating mobile web apps

    Automating mobile web apps If you’re interested in automating your web app in Mobile Safari on iOS o ...

  6. 在线文档预览方案-office web apps续篇

    上一篇在线文档预览方案-office web apps发布后收到很多网友的留言提问,所以准备再写一篇,一来介绍一下域控服务器安装,总结一下大家问的多的问题,二来宣传预览服务安装与技术支持的事情. 阅读 ...

  7. 安装部署完office web apps 后,无法浏览Word

    安装部署完office web apps 后,在sharepoint 2010浏览器中浏览Word提示:“由于出现意外错误,Word Web App 无法打开此 文档 进行查看. 要查看此 文档,请在 ...

  8. 在线文档预览方案-office web apps

    最近在做项目时,要在手机端实现在线文档预览的功能.于是百度了一下实现方案,大致是将文档转换成pdf,然后在通过插件实现预览.这些方案没有具体实现代码,也没有在线预览的地址,再加上项目时间紧迫.只能考虑 ...

  9. 免费电子书:Azure Web Apps开发者入门

    (此文章同时发表在本人微信公众号"dotNET每日精华文章",欢迎右边二维码来关注.) 题记:之前介绍过微软正在逐步出版一个名为Azure Essential的入门系列教程,最近刚 ...

随机推荐

  1. [置顶] COcos2d-X 中文API

    本文来自http://blog.csdn.net/runaying ,引用必须注明出处! COcos2d-X 中文API 温馨提醒:使用二维码扫描软件,就可以在手机上访问我的博客啦!另外大家可以访问另 ...

  2. HDU 5266 pog loves szh III (线段树+在线LCA转RMQ)

    题目地址:HDU 5266 这题用转RMQ求LCA的方法来做的很easy,仅仅须要找到l-r区间内的dfs序最大的和最小的就能够.那么用线段树或者RMQ维护一下区间最值就能够了.然后就是找dfs序最大 ...

  3. Zend框架2入门(二) (转)

    Zend框架2使用一个模块系统,和你组织内每个你的主应用程序特定代码模块.骨架提供的应用程序模块是用于提供引导,错误和路由配置到整个应用程序.它通常是用来提供应用水平控制器,比如说,应用程序的主页,但 ...

  4. javascript中的继承用法

    本文实例汇总了javascript关于继承的用法,希望本文所述对大家的javascript程序设计有所帮助.分享给大家供大家参考.具体如下:代码如下: /** * 实现子类继承父类,但不会产生多余的属 ...

  5. VS中批量删除cs代码中的#region和#endregion

    Visual Studio中如何批量删除cs代码中的#region和#endregion,不删除它们中间的代码,只删除这两个标记及标记的注解的方法.Vs中提供了很强大的文本查找与替换功能,简单的替换只 ...

  6. 线段树---HDU1754 I hate it

    这个题也是线段树的基础题,有了上一个题的基础,在做这个题就显得比较轻松了,大体都是一样的,那个是求和,这个改成求最大值,基本上思路差不多,下面是代码的实现 #include <cstdio> ...

  7. jdbc03 使用servlet实现

    <%@page import="cn.bdqn.bean.News"%> <%@page import="cn.bdqn.service.impl.Ne ...

  8. C#总结项目《影院售票系统》编写总结完结篇

    回顾:昨天总结了影院售票系统核心部分-售票,整个项目也就完成了2/3了,需求中也要求了对销售信息的保存,今天就继续总结销售信息的保存以及加载销售信息. 分析:退出程序时将已售出票集合中的对象循环写入到 ...

  9. 使用HighCharts实现实时数据展示

    在众多的工业控制系统领域常常会实时采集现场的温度.压力.扭矩等数据,这些数据对于监控人员进行现场态势感知.进行未来趋势预测具有重大指导价值.工程控制人员如果只是阅读海量的数据报表,对于现场整个态势的掌 ...

  10. java反射机制 struts2 获取 action、method、invocation、proxy

    ActionInvocation invocation = ActionContext.getContext().getActionInvocation(); Object action = invo ...