404 错误消息 - 找不到 SignalR/中心

本文关键字:SignalR 中心 找不到 错误 消息 | 更新日期: 2023-09-27 18:36:47

我知道这个问题已经发布在这里的其他地方,但找不到可行的解决方案。我有 2 个应用程序:一个是另一个的旧版本,从 VS2015 运行一个 SignalR 聊天应用程序(使用 IIS Express),另一个应用程序基本相同,除了其他地方的更改(它是一个购物车),但聊天页面、脚本和引用是相同的(包括路径)。Web.config、global.cs、startup 都是相同的,都运行 MVC5。较旧的应用使用标准 HTML 页面,并引用 SignalR/集线器即可(无 404 错误),如下所示:这是代理.html页面:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <title>LiveChat</title>
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link href="../Scripts/JqueryUI/jquery-ui.css" rel="stylesheet" type="text/css" />
    <link href="assets/chat.css" rel="stylesheet" />   
    <script src="../Scripts/jquery-1.11.0.min.js" type="text/javascript"></script>
    <script src="../Scripts/jquery-ui-1.11.3.min.js" type="text/javascript"></script>
    <script src="../Scripts/json2.min.js" type="text/javascript"></script>
</head>
<body style="background-color: #fff;">
    <div class="topbar">
        <div style="float: left; margin-left: 30px;">
            <ul>
                <li><a href="/CHAT/Agent.html">Chat Agent Panel</a></li>
                <li><a href="#" id="show-real-time-visits">Show Real Time Visits</a></li>
                <li><a href="#" id="show-internal-chat">Agent to Agent Chat</a></li>
                <li><a href="/CHAT/Install.html">Configure Chat</a></li>
            </ul>
        </div>
        <div style="float: right; margin-right: 30px;">
            <ul>
                <li>Logged in as:</li>
                <li><a href="#" id="change-status">Not logged in</a></li>
            </ul>
        </div>
    </div>
    <div>
        <h2>Chat Sessions</h2>
        <div id="chat-sessions"></div>
        <div id="chat-content">
            <div id="login">
                <h3>Log In to Start Accepting Chat Requests</h3>
                <div id="login-alerts"></div>
                <fieldset>
                    <legend>Enter your agent name and password</legend>
                    <p>
                        <label>Agent Name</label>
                        <input id="login-name" type="text" class="form-control" placeholder="agent name">
                    </p>
                    <p>
                        <label>Agent Password</label>
                        <input id="login-pass" class="form-control" type="password">
                    </p>
                    <br />
                    <button id="login-btn" type="submit" class="button-1">Start accepting chat ></button>
                </fieldset>
            </div>
            <div id="agent-chat">
                <div id="real-time-visits">
                    <h2>Real time visits</h2>
                    <table id="current-visits">
                        <thead>
                            <tr>
                                <th>Visited on</th>
                                <th>Page</th>
                                <th>Referrer</th>
                                <th>City</th>
                                <th>Country</th>
                                <th>In Chat</th>
                                <th>Invite</th>
                            </tr>
                        </thead>
                        <tbody></tbody>
                    </table>
                </div>
                <div id="all-chatbox">
                    <div id="chatmsgsinternal" class="chat-msgs"></div>
                </div>
                <div id="chat-controls">
                    <input id="post-msg" type="text" style="width: 100%;" placeholder="Enter your text here. Enter /list for a list of available commands" />
                    <br />
                    <button id="post-btn" class="button-1" style="margin-top: 6px;">Send</button>
                </div>
            </div>
        </div>
        <div id="modal-cmd">
            <div class="modal-body">
            </div>
        </div>
    </div>
    <script src="assets/js/jquery.timeago.js" type="text/javascript"></script>
    <script src="../Scripts/jquery.signalR-2.2.0.min.js" type="text/javascript"></script>
    <script type="text/javascript">
        $(function () {
            $("#login-name").keypress(function (e) {
                if ((e.which && e.which == 13) || (e.keyCode && e.keyCode == 13)) {
                    $("#login-btn").click();
                    return false;
                } else {
                    return true;
                }
            });
            $("#login-pass").keypress(function (e) {
                if ((e.which && e.which == 13) || (e.keyCode && e.keyCode == 13)) {
                    $("#login-btn").click();
                    return false;
                } else {
                    return true;
                }
            });
        });
    </script>
    <script src="/signalr/hubs" type="text/javascript"></script>
    <script src="agent.js" type="text/javascript"></script>
 </body>
</html>

这在旧应用程序中工作正常,但未创建自动生成的信号器/集线器 javascript。创业.cs:

using System;
using System.Threading.Tasks;
using Microsoft.Owin;
using Owin;
[assembly: OwinStartup(typeof(WEBCHAT.Startup))]
namespace WEBCHAT
{
    public class Startup
    {
        public void Configuration(IAppBuilder app)
        {
            app.MapSignalR();
        }
    }
}

ChatHub.cs(再一次,它可以在旧的而不是新的中找到)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using Microsoft.AspNet.SignalR;
using System.Threading.Tasks;
using System.IO;
using System.Security.Cryptography;
using System.Text;
using System.Net.Mail;
using System.Collections.Concurrent;
using System.Diagnostics;
namespace WEBCHAT
{
    public class ChatHub : Hub
    {
        private const string CONFIG_FILE = "webchat.dat";
        private static ConcurrentDictionary<string, Agent> Agents;
        private static ConcurrentDictionary<string, string> ChatSessions;
        public void AgentConnect(string name, string pass)
        {
            if (Agents == null)
                Agents = new ConcurrentDictionary<string, Agent>();
            if (ChatSessions == null)
                ChatSessions = new ConcurrentDictionary<string, string>();
            string hashPass = ToHash(pass);
            var config = GetConfig();
            if (config == null || config.Length < 2)
            {
                Clients.Caller.loginResult(false, "config", "");
            }
            else if ((config[0] == hashPass) || (config[1] == hashPass))
            {
                var agent = new Agent()
                {
                    Id = Context.ConnectionId,
                    Name = name,
                    IsOnline = true
                };
                // if the agent is already signed-in
                if (Agents.Any(x => x.Key == name))
                {
                    agent = Agents[name];
                    Clients.Caller.loginResult(true, agent.Id, agent.Name);
                    Clients.All.onlineStatus(Agents.Count(x => x.Value.IsOnline) > 0);
                }
                else if (Agents.TryAdd(name, agent))
                {
                    Clients.Caller.loginResult(true, agent.Id, agent.Name);
                    Clients.All.onlineStatus(Agents.Count(x => x.Value.IsOnline) > 0);
                }
                else
                {
                    Clients.Caller.loginResult(false, "error", "");
                }
            }
            else
                Clients.Caller.loginResult(false, "pass", "");
        }
        public void ChangeStatus(bool online)
        {
            var agent = Agents.SingleOrDefault(x => x.Value.Id == Context.ConnectionId).Value;
            if (agent != null)
            {
                agent.IsOnline = online;
                Clients.All.onlineStatus(Agents.Count(x => x.Value.IsOnline) > 0);
            }
        }
        public void EngageVisitor(string connectionId)
        {
            var agent = Agents.SingleOrDefault(x => x.Value.Id == Context.ConnectionId).Value;
            if (agent != null)
            {
                ChatSessions.TryAdd(connectionId, agent.Id);
                Clients.Caller.newChat(connectionId);
                Clients.Client(connectionId).setChat(connectionId, agent.Name, false);
                Clients.Caller.addMessage(connectionId, "system", "You invited this visitor to chat...");
                Clients.Client(connectionId).addMessage(agent.Name, "Hey there. I'm " + agent.Name + " let me know if you have any questions.");
            }
        }
        public void LogVisit(string page, string referrer, string city, string region, string country, string existingChatId)
        {
            if (Agents == null)
                Agents = new ConcurrentDictionary<string, Agent>();
            Clients.Caller.onlineStatus(Agents.Count(x => x.Value.IsOnline) > 0);
            var cityDisplayName = GetCityDisplayName(city, region);
            var countryDisplayName = country ?? string.Empty;
            if (!string.IsNullOrEmpty(existingChatId) &&
                ChatSessions.ContainsKey(existingChatId))
            {
                var agentId = ChatSessions[existingChatId];
                Clients.Client(agentId).visitorSwitchPage(existingChatId, Context.ConnectionId, page);
                var agent = Agents.SingleOrDefault(x => x.Value.Id == agentId).Value;
                if (agent != null)
                    Clients.Caller.setChat(Context.ConnectionId, agent.Name, true);
                string buffer = "";
                ChatSessions.TryRemove(existingChatId, out buffer);
                ChatSessions.TryAdd(Context.ConnectionId, agentId);
            }
            foreach (var agent in Agents)
            {
                var chatWith = (from c in ChatSessions
                                join a in Agents on c.Value equals a.Value.Id
                                where c.Key == Context.ConnectionId
                                select a.Value.Name).SingleOrDefault();
                Clients.Client(agent.Value.Id).newVisit(page, referrer, cityDisplayName, countryDisplayName, chatWith, Context.ConnectionId);
            }
        }
        public void RequestChat(string message)
        {
            // We assign the chat to the less buzy agent
            var workload = from a in Agents
                           where a.Value.IsOnline
                           select new
                           {
                               Id = a.Value.Id,
                               Name = a.Value.Name,
                               Count = ChatSessions.Count(x => x.Value == a.Value.Id)
                           };
            if (workload == null)
            {
                Clients.Caller.addMessage("", "No agent are currently available.");
                return;
            }
            var lessBuzy = workload.OrderBy(x => x.Count).FirstOrDefault();
            if (lessBuzy == null)
            {
                Clients.Caller.addMessage("", "No agent are currently available.");
                return;
            }
            ChatSessions.TryAdd(Context.ConnectionId, lessBuzy.Id);
            Clients.Client(lessBuzy.Id).newChat(Context.ConnectionId);
            Clients.Caller.setChat(Context.ConnectionId, lessBuzy.Name, false);
            Clients.Client(lessBuzy.Id).addMessage(Context.ConnectionId, "visitor", message);
            Clients.Caller.addMessage("me", message);
        }
        public void Transfer(string connectionId, string agentName, string messages)
        {
            if (!Agents.ContainsKey(agentName))
            {
                Clients.Caller.addMessage(Context.ConnectionId, "system", "This agent does not exists: " + agentName);
                return;
            }
            var agent = Agents[agentName];
            if (!agent.IsOnline)
            {
                Clients.Caller.addMessage(Context.ConnectionId, "system", agentName + " is not online at the moment.");
                return;
            }
            if (!ChatSessions.ContainsKey(connectionId))
            {
                Clients.Caller.addMessage(Context.ConnectionId, "system", "This chat session does not exists anymore.");
                return;
            }
            string currentAgentId = "";
            if (ChatSessions.TryRemove(connectionId, out currentAgentId) &&
                ChatSessions.TryAdd(connectionId, agent.Id))
            {
                Clients.Client(agent.Id).newChat(connectionId);
                Clients.Client(agent.Id).addMessage(connectionId, "system", "New chat transfered to you.");
                Clients.Client(agent.Id).addMessage(connectionId, ">>", "Starting previous conversation");
                Clients.Client(agent.Id).addMessage("", messages);
                Clients.Client(agent.Id).addMessage(connectionId, "<<", "End of previous conversation");
                Clients.Client(connectionId).addMessage("", "You have been transfered to " + agent.Name);
                Clients.Client(connectionId).setChat(connectionId, agent.Name, true);
                Clients.Caller.addMessage(connectionId, "system", "Chat transfered to " + agentName);
            }
        }
        public void Send(string data)
        {
            Clients.Caller.addMessage("me", data);
            if (ChatSessions.ContainsKey(Context.ConnectionId))
            {
                var opId = ChatSessions[Context.ConnectionId];
                Clients.Client(opId).addMessage(Context.ConnectionId, "visitor", data);
            }
            else
            {
                Debug.WriteLine("Chat Session not found.");
                var workload = from a in Agents
                               where a.Value.IsOnline
                               select new
                               {
                                   Id = a.Value.Id,
                                   Name = a.Value.Name,
                                   Count = ChatSessions.Count(x => x.Value == a.Value.Id)
                               };
                if (workload == null)
                {
                    Clients.Caller.addMessage("", "No agent are currently available.");
                    return;
                }
                var lessBuzy = workload.OrderBy(x => x.Count).FirstOrDefault();
                if (lessBuzy == null)
                {
                    Clients.Caller.addMessage("", "No agent are currently available.");
                    return;
                }
                ChatSessions.TryAdd(Context.ConnectionId, lessBuzy.Id);
                Clients.Client(lessBuzy.Id).newChat(Context.ConnectionId);
                Clients.Caller.setChat(Context.ConnectionId, lessBuzy.Name, false);
                Clients.Client(lessBuzy.Id).addMessage(Context.ConnectionId, "system", "This visitor appear to have lost their chat session.");
                Clients.Client(lessBuzy.Id).addMessage(Context.ConnectionId, "visitor", data);
            }
        }
        public void OpSend(string id, string data)
        {
            var agent = Agents.SingleOrDefault(x => x.Value.Id == Context.ConnectionId).Value;
            if (agent == null)
            {
                Clients.Caller.addMessage(id, "system", "We were unable to send your message, please reload the page.");
                return;
            }
            if (id == "internal")
            {
                foreach (var a in Agents.Where(x => x.Value.IsOnline))
                    Clients.Client(a.Value.Id).addMessage(id, agent.Name, data);
            }
            else if (ChatSessions.ContainsKey(id))
            {
                Clients.Caller.addMessage(id, "you", data);
                Clients.Client(id).addMessage(agent.Name, data);
            }
        }
        public void CloseChat(string id)
        {
            if (ChatSessions.ContainsKey(id))
            {
                Clients.Client(id).addMessage("", "The agent close the chat session.");
                string buffer = "";
                ChatSessions.TryRemove(id, out buffer);
            }
        }
        public void LeaveChat(string id)
        {
            // was it an agent
            var agent = Agents.SingleOrDefault(x => x.Value.Id == id).Value;
            if (agent != null)
            {
                Agent tmp = null;
                if (Agents.TryRemove(agent.Name, out tmp))
                {
                    var sessions = ChatSessions.Where(x => x.Value == agent.Id);
                    if (sessions != null)
                    {
                        foreach (var session in sessions)
                            Clients.Client(session.Key).addMessage("", "The agent was disconnected from chat.");
                    }
                    Clients.All.updateStatus(Agents.Count(x => x.Value.IsOnline) > 0);
                }
            }
            // was it a visitor
            if (ChatSessions.ContainsKey(id))
            {
                var agentId = ChatSessions[id];
                Clients.Client(agentId).addMessage(id, "system", "The visitor close the connection.");
            }
        }
        public override Task OnDisconnected(bool stopCalled)
        {
            return Clients.All.leave(Context.ConnectionId);
        }
        public void SendEmail(string from, string message)
        {
            if (ValidateEmail(from) == true)
            {
                var msg = new MailMessage();
                msg.To.Add(new MailAddress(from));
                msg.Subject = "WEBCHAT - Offline Contact";
                msg.Body = "You received an offline contact from your WEBCHAT chat widget.'r'n'r'n" + Nop.Core.Html.HtmlHelper.FormatText(message, true, false, false, false, false, false);
                try
                {
                    string emResult = eMail.SendEmail(msg.Subject, msg.Body, from, "xxx@xxx.com", "mail.xxx.com", "xxx@xxx.com", "password", from, "My Chat Agent", false, null, 25, from, MailPriority.High, DeliveryNotificationOptions.None);
                }
                catch
                {
                }
            }
        }
        #region Install and config methods
        public void getInstallState()
        {
            var config = GetConfig();
            if (config != null && config.Length >= 2)
                Clients.Caller.installState(true, config[0]);
            else
                Clients.Caller.installState(false, "chattemptoken");
        }
        public void AdminRequest(string pass)
        {
            var config = GetConfig();
            if (config != null && config.Length >= 2)
            {
                if (config[0] == ToHash(pass))
                    Clients.Caller.adminResult(true, config[0]);
                else
                    Clients.Caller.adminResult(false, "");
            }
            else
                Clients.Caller.adminResult(false, "");
        }
        public void SetConfig(string token, string adminPass, string agentPass)
        {
            bool shouldSave = false;
            var config = GetConfig();
            if (config != null && config.Length >= 2)
            {
                if (config[0] == token)
                    shouldSave = true;
            }
            if (token == "chattemptoken")
                shouldSave = true;
            if (shouldSave)
            {
                string configPath = HttpContext.Current.Server.MapPath("~/App_Data/" + CONFIG_FILE);
                File.WriteAllText(
                    configPath,
                    ToHash(adminPass) + "'n" + ToHash(agentPass));
                Clients.Caller.setConfigResult(true, "Config file updated.");
            }
            else
                Clients.Caller.setConfigResult(false, "Unable to save the config file.");
        }
        private string GetCityDisplayName(string city, string region)
        {
            var displayCity = string.Empty;
            if (!string.IsNullOrEmpty(city))
            {
                displayCity = city;
                if (!string.IsNullOrEmpty(region))
                {
                    displayCity += ", " + region;
                }
            }
            return displayCity;
        }
        private string[] GetConfig()
        {
            string configPath = HttpContext.Current.Server.MapPath("~/App_Data/" + CONFIG_FILE);
            if (File.Exists(configPath))
            {
                return File.ReadAllLines(configPath);
            }
            return null;
        }
        public string ToHash(string password)
        {
            if (string.IsNullOrEmpty(password))
                return "";
            var provider = new SHA1CryptoServiceProvider();
            var encoding = new UnicodeEncoding();
            return Convert.ToBase64String(provider.ComputeHash(encoding.GetBytes(password)));
        }
        #endregion
        public bool ValidateEmail(string strCheck)
        {
            try
            {
                System.Net.Mail.MailAddress vEmailAddress = new System.Net.Mail.MailAddress(strCheck);
            }
            catch (Exception ex)
            {
                //_logger.Error(string.Format("Error validating e-mail. {0}", ex.Message), ex);
                return false;
            }
            return true;
        }
    }
    public class eMail
    {
        public static string SendEmail(string emailSubject, string emailBody, string senderAddress, string recipientAddress, string emailServer, string accountName, string accountPassword, string senderName = "", string recipientName = "", bool isHTML = true, List<string> attachmentPaths = null, int portNumber = 25, string replyToAddress = "", System.Net.Mail.MailPriority priority = MailPriority.Normal, DeliveryNotificationOptions deliveryNotification = DeliveryNotificationOptions.None)
        {
            //this will return a string of "success", if successful and an error message if not
            string retval = string.Empty;
            if (senderName.Length == 0)
            {
                senderName = senderAddress;
            }
            if (recipientName.Length == 0)
            {
                recipientName = recipientAddress;
            }
            MailMessage msg = new MailMessage(new MailAddress(senderAddress, senderName), new MailAddress(recipientAddress, recipientName));
            SmtpClient mailClient = null;
            mailClient = new SmtpClient(emailServer, portNumber);
            msg.Subject = emailSubject;
            msg.IsBodyHtml = isHTML;
            msg.Body = emailBody;
            if (attachmentPaths != null)
            {
                foreach (var attPath in attachmentPaths)
                {
                    if (File.Exists(attPath))
                    {
                        msg.Attachments.Add(new Attachment(attPath));
                    }
                }
            }
            if (accountName.Length > 0 && accountPassword.Length > 0)
            {
                System.Net.NetworkCredential userSMTPAccount = new System.Net.NetworkCredential(accountName, accountPassword);
                mailClient.UseDefaultCredentials = false;
                mailClient.Credentials = userSMTPAccount;
            }
            else
            {
                mailClient.Credentials = System.Net.CredentialCache.DefaultNetworkCredentials;
            }
            msg.DeliveryNotificationOptions = deliveryNotification;
            try
            {
                mailClient.Send(msg);
                retval = "success";
            }
            catch (SmtpException ex)
            {
                retval = ex.Message;
            }
            catch (Exception ex2)
            {
                retval = ex2.Message; //for general errors
            }
            finally
            {
                msg.Dispose();
            }
            return retval;
        }

    }
}

还有更多,所有代码在旧版本上都可以正常工作,但在新版本上则不然。所有必需的 DLL 都在 BIN 文件夹中。package.config 是相同的(除了旧版本的 OWIN - 这可能是可疑的)。我只是不知道还有什么地方可以寻找差异来解释为什么旧版本的应用程序有效而新版本不起作用(除了可怕的 SignalR/Hub 之外,所有内容都加载到新版本、脚本、css、页面等中)。是否有我错过的设置?

404 错误消息 - 找不到 SignalR/中心

天哪!我知道答案一定很简单!是的!首先,我将OWIN安全性升级到最新版本(不确定这是否是真正的问题)。然后,我在 Web.config 文件中看到了一个新键(或者我上次错过了它),名为:

<appSettings>
   <add key="owin:AutomaticAppStartup" value="true" />
    ...
</appSettings>

我将值从 false 更改为 true,现在它可以工作了。经过 3 天的代码调整和通过查看其他论坛帖子的反复试验,我很高兴它这么简单。希望这对其他人有所帮助。然而,让我烦恼的是,旧应用程序的 web.config 中没有这样的设置(去图) - 它没有它就可以工作。