- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我知道这个问题已在其他地方发布,但找不到可行的解决方案。我有 2 个应用程序:1 个是另一个的旧版本,从 VS2015(使用 IIS Express)运行 SignalR 聊天应用程序就好了,另一个应用程序基本相同,除了其他地方的变化(它的购物车),但聊天页面、脚本和引用是相同的(包括路径)。 Web.config、global.cs、启动都是相同的,都运行 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/集线器)。是否有我遗漏的设置?
最佳答案
我的天哪!我知道答案必须非常简单!这是!首先,我将 OWIN 安全升级到最新版本(不确定这是否是真正的问题)。然后,我在 Web.config 文件中看到了一个新的 key (或者我上次错过了)叫做:
<appSettings>
<add key="owin:AutomaticAppStartup" value="true" />
...
</appSettings>
我将值从 false 更改为 true,现在可以使用了。通过查看其他论坛帖子进行了 3 天的代码调整和反复试验后,我很高兴它是如此简单。希望这对其他人有帮助。然而,让我感到困扰的是,旧应用程序的 web.config 中没有这样的设置(请看图)——没有它它也能工作。
关于c# - 404 错误消息 - 找不到 SignalR/Hubs,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35687998/
#include using namespace std; class C{ private: int value; public: C(){ value = 0;
这个问题已经有答案了: What is the difference between char a[] = ?string?; and char *p = ?string?;? (8 个回答) 已关闭
关闭。此题需要details or clarity 。目前不接受答案。 想要改进这个问题吗?通过 editing this post 添加详细信息并澄清问题. 已关闭 7 年前。 此帖子已于 8 个月
除了调试之外,是否有任何针对 c、c++ 或 c# 的测试工具,其工作原理类似于将独立函数复制粘贴到某个文本框,然后在其他文本框中输入参数? 最佳答案 也许您会考虑单元测试。我推荐你谷歌测试和谷歌模拟
我想在第二台显示器中移动一个窗口 (HWND)。问题是我尝试了很多方法,例如将分辨率加倍或输入负值,但它永远无法将窗口放在我的第二台显示器上。 关于如何在 C/C++/c# 中执行此操作的任何线索 最
我正在寻找 C/C++/C## 中不同类型 DES 的现有实现。我的运行平台是Windows XP/Vista/7。 我正在尝试编写一个 C# 程序,它将使用 DES 算法进行加密和解密。我需要一些实
很难说出这里要问什么。这个问题模棱两可、含糊不清、不完整、过于宽泛或夸夸其谈,无法以目前的形式得到合理的回答。如需帮助澄清此问题以便重新打开,visit the help center . 关闭 1
有没有办法强制将另一个 窗口置于顶部? 不是应用程序的窗口,而是另一个已经在系统上运行的窗口。 (Windows, C/C++/C#) 最佳答案 SetWindowPos(that_window_ha
假设您可以在 C/C++ 或 Csharp 之间做出选择,并且您打算在 Windows 和 Linux 服务器上运行同一服务器的多个实例,那么构建套接字服务器应用程序的最明智选择是什么? 最佳答案 如
你们能告诉我它们之间的区别吗? 顺便问一下,有什么叫C++库或C库的吗? 最佳答案 C++ 标准库 和 C 标准库 是 C++ 和 C 标准定义的库,提供给 C++ 和 C 程序使用。那是那些词的共同
下面的测试代码,我将输出信息放在注释中。我使用的是 gcc 4.8.5 和 Centos 7.2。 #include #include class C { public:
很难说出这里问的是什么。这个问题是含糊的、模糊的、不完整的、过于宽泛的或修辞性的,无法以目前的形式得到合理的回答。如需帮助澄清此问题以便重新打开它,visit the help center 。 已关
我的客户将使用名为 annoucement 的结构/类与客户通信。我想我会用 C++ 编写服务器。会有很多不同的类继承annoucement。我的问题是通过网络将这些类发送给客户端 我想也许我应该使用
我在 C# 中有以下函数: public Matrix ConcatDescriptors(IList> descriptors) { int cols = descriptors[0].Co
我有一个项目要编写一个函数来对某些数据执行某些操作。我可以用 C/C++ 编写代码,但我不想与雇主共享该函数的代码。相反,我只想让他有权在他自己的代码中调用该函数。是否可以?我想到了这两种方法 - 在
我使用的是编写糟糕的第 3 方 (C/C++) Api。我从托管代码(C++/CLI)中使用它。有时会出现“访问冲突错误”。这使整个应用程序崩溃。我知道我无法处理这些错误[如果指针访问非法内存位置等,
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 我们不允许提问寻求书籍、工具、软件库等的推荐。您可以编辑问题,以便用事实和引用来回答。 关闭 7 年前。
已关闭。此问题不符合Stack Overflow guidelines 。目前不接受答案。 要求我们推荐或查找工具、库或最喜欢的场外资源的问题对于 Stack Overflow 来说是偏离主题的,因为
我有一些 C 代码,将使用 P/Invoke 从 C# 调用。我正在尝试为这个 C 函数定义一个 C# 等效项。 SomeData* DoSomething(); struct SomeData {
这个问题已经有答案了: Why are these constructs using pre and post-increment undefined behavior? (14 个回答) 已关闭 6
我是一名优秀的程序员,十分优秀!