我正在使用 SignalR 为我的网站制作一个聊天应用程序。由于该网站是用 ASP.NET Web 窗体开发的,因此我根据这篇 CodeProject 文章 建模了我的代码,因为它确实是我能找到的 Web 窗体的唯一示例(我知道,Web 窗体已经过时了,我应该可能正在使用 MVC)。
为简单起见,我将从文章中复制相关的主要三个 C# 文件。
Startup.cs
using Microsoft.Owin;
using Owin;
[assembly: OwinStartup(typeof(WebApplication1.Startup))]
namespace WebApplication1
{
public class Startup
{
public void Configuration(IAppBuilder app)
{
app.MapSignalR();
}
}
}
ChatHub.cs
public class ChatHub : Hub
{
static List<Users> ConnectedUsers = new List<Users>();
static List<Messages> CurrentMessage = new List<Messages>();
ConnClass ConnC = new ConnClass();
public void Connect(string userName)
{
var id = Context.ConnectionId;
if (ConnectedUsers.Count(x => x.ConnectionId == id) == 0)
{
string UserImg = GetUserImage(userName);
string logintime = DateTime.Now.ToString();
ConnectedUsers.Add(new Users { ConnectionId = id, UserName = userName, UserImage = UserImg, LoginTime = logintime });
Clients.Caller.onConnected(id, userName, ConnectedUsers, CurrentMessage);
Clients.AllExcept(id).onNewUserConnected(id, userName, UserImg, logintime);
}
}
public void SendMessageToAll(string userName, string message, string time)
{
string UserImg = GetUserImage(userName);
AddMessageinCache(userName, message, time, UserImg);
Clients.All.messageReceived(userName, message, time, UserImg);
}
private void AddMessageinCache(string userName, string message, string time, string UserImg)
{
CurrentMessage.Add(new Messages { UserName = userName, Message = message, Time = time, UserImage = UserImg });
if (CurrentMessage.Count > 100)
CurrentMessage.RemoveAt(0);
}
public string GetUserImage(string username)
{
string RetimgName = "images/dummy.png";
try
{
string query = "select Photo from tbl_Users where UserName='" + username + "'";
string ImageName = ConnC.GetColumnVal(query, "Photo");
if (ImageName != "")
RetimgName = "images/DP/" + ImageName;
}
catch (Exception ex)
{ }
return RetimgName;
}
public override System.Threading.Tasks.Task OnDisconnected(bool stopCalled)
{
var item = ConnectedUsers.FirstOrDefault(x => x.ConnectionId == Context.ConnectionId);
if (item != null)
{
ConnectedUsers.Remove(item);
var id = Context.ConnectionId;
Clients.All.onUserDisconnected(id, item.UserName);
}
return base.OnDisconnected(stopCalled);
}
}
Chat.aspx (JavaScript)
$(function() {
var chatHub = $.connection.chatHub;
registerClientMethods(chatHub);
$.connection.hub.start().done(function () {
registerEvents(chatHub);
});
function registerEvents(chatHub) {
var name = '<%= this.UserName %>';
if (name.length > 0) {
chatHub.server.connect(name);
}
}
function registerClientMethods(chatHub) {
chatHub.client.onConnected = function (id, userName, allUsers, messages, times) {
console.log("Connected");
}
chatHub.client.onNewUserConnected = function (id, name, UserImage, loginDate) {
console.log("User Connected");
}
chatHub.client.onUserDisconnected = function (id, userName) {
console.log("User Disconnected");
}
chatHub.client.messageReceived = function (userName, message, time, userimg) {
console.log("Message Received");
AddMessage(userName, message, time, userimg);
}
}
});
中心的任何客户端方法(除了
messageReceived
)都不会在必要时被触发,从没有出现 console.log()
消息即可看出。本文使用 SignalR 版本 2.2.2,而我使用的是最新的 2.4.3。但是,我已经尝试了两个版本,但仍然没有成功。此行调用 Connect()
方法:
chatHub.server.connect(name);
而在服务器端,
OnConnected()
在Connect()
中被调用:
Clients.Caller.onConnected(id, userName, ConnectedUsers, CurrentMessage);
因此,它应该触发 JavaScript 函数
chatHub.client.onConnected
,但没有。
这是网络活动:
请注意,
negotiate
、start
和 send
方法会立即提供 200 个 HTTP 状态,但 connect
方法永远不会完成。
我尝试在 JS 中添加对集线器的订阅来强制连接,但这不起作用。如果还有其他通过 Web 表单使用 SignalR 的示例,我非常乐意接受。
我在这里犯了一个菜鸟错误。如果我只在 Azure 中启用 Web 套接字,该代码就可以正常工作。此 Web 应用程序部署到 Azure 应用程序服务,由于 SignalR 使用 Web 套接字,因此必须打开它们,但 Azure 默认情况下禁用它们。只需登录到 Azure 门户,转到应用程序服务 > 配置 > 常规设置,然后将 Web 套接字切换为“打开”即可。