404错误消息 - 无法找到SignalR / Hub

时间:2016-02-28 20:41:38

标签: c# asp.net-mvc asp.net-mvc-5 signalr owin

我知道这个问题已经发布在其他地方,但无法找到有效的解决方案。 我有2个应用程序:1是另一个的旧版本,从VS2015运行一个SignalR聊天应用程序(使用IIS Express),其他应用程序基本相同,除了其他地方的更改(它的购物车),但聊天页面,脚本和引用是相同的(包括路径)。 Web.config,global.cs,startup都是相同的,都运行MVC5。 较旧的应用程序使用标准HTML页面并使用以下内容引用SignalR / Hubs(没有404错误): 这是agent.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。 startup.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 - 可能是可疑的)。 我只是不知道在哪里寻找差异可以解释为什么旧版本的应用程序工作而新版本不工作(所有内容都加载到新版本,脚本,CSS,页面等除外可怕的SignalR / Hubs)。我错过了什么地方?

1 个答案:

答案 0 :(得分:3)

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

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

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