从任何 Xamarin 向 SignalR 中心发送消息 (Visual Studio 2017) android activity
Send message to SignalR hub from any Xamarin (Visual Studio 2017) android activity
我已经能够从 html 页面、aspx 页面和 Xamarin 客户端创建和接收来自 SignalR 中心的消息,这是我真正需要它来使用 Microsoft.AspNet.SignalR.Client v2 的应用程序.4.1 在 Visual Studio 2017 年使用 Xamarin。一旦我的 Xamarin 应用程序对用户进行身份验证,我就开始连接到集线器,接下来我连接一个事件来接收消息。所有这一切都工作得很好,我可以在 android 应用程序中接收消息,无论 activity 是当前的 activity 多亏了连接的事件。现在我有了这个工作,我希望能够从客户端向集线器发送消息,而无需创建与集线器的另一个连接。我查看了静态 classes,但无法使其正常工作。我的代码是:
这是用户通过身份验证后执行的代码:
// Start SignalR connection
Client client = new Client(MyUser.Firstname + " " + MyUser.Lastname, MyUser.Username);
await client.Connect();
// Wire up the message received event
client.OnMessageReceived += (sender2, message) => RunOnUiThread(() => showMessage(message));
从这里,用户可以从一个视图导航到另一个视图,并且能够通过事件和 showMessage
方法从中心接收消息。这一切都完美无缺。
我的客户代码:
此代码是从堆栈溢出工作示例中复制的,我根据自己的要求对其进行了修改。
namespace ChatClient.Shared
{
class Client
{
private readonly string _platform;
private readonly HubConnection _connection;
private readonly IHubProxy _proxy;
public event EventHandler<string> OnMessageReceived;
public Client(string platform, string username)
{
string _username = "username=" + username;
_platform = platform;
_connection = new HubConnection("https://Example.com/SignalRhub", _username);
_proxy = _connection.CreateHubProxy("chathub");
}
public async Task Connect()
{
await _connection.Start(); _proxy.On("broadcastMessage", (string platform, string message) =>
{
if (OnMessageReceived != null)
OnMessageReceived(this, string.Format("{0}: {1}", platform, message));
});
Send("Connected");
}
public async Task<List<string>> ConnectedUsers()
{
List<string> Users = await _proxy.Invoke<List<string>>("getConnectedUsers");
return Users;
}
public Task Send(string message)
{
return _proxy.Invoke("Send", _platform, message);
}
}
}
现在我需要做的是使用登录后创建的连接向集线器发送一条消息,以便分发给所有连接的用户。我不知道该怎么做,我试过使用静态 class 并尝试使用我在网上找到的方法,但似乎没有任何效果。
我的中心代码:
public class ChatHub : Hub
{
private static readonly List<User> Users = new List<User>();
public override Task OnConnected()
{
string userName = Context.QueryString["username"];
string firstname = Context.QueryString["firstname"];
string lastname = Context.QueryString["lastname"];
string connectionId = this.Context.ConnectionId;
var user = new User();
user.Name = userName;
user.ConnectionIds = connectionId;
try
{
Users.Add(user);
}
catch (Exception ex)
{
var msg = ex.Message;
}
// send list of connected users to client as a test
Send("Welcome " + userName, "Connected users are:");
foreach (var display in Users)
{
Send("",display.Name.ToString());
}
// test sending to a specific user
SendOne(connectionId, userName, "This is to a specific user.");
return base.OnConnected();
}
public override Task OnDisconnected(bool stopped)
{
string userName = Context.User.Identity.Name;
string connectionId = Context.ConnectionId;
var item = Users.Find(x => x.ConnectionIds == connectionId);
Send(item.Name , " disconnected.");
Users.Remove(item);
return base.OnDisconnected(true);
}
public void SendOne(string connectionId, string userName, string message)
{
Clients.Client(connectionId).broadcastMessage(userName, message);
}
public void Send(string name, string message)
{
// Call the broadcastMessage method to update clients.
Clients.All.broadcastMessage(name, message);
}
public List<string> getConnectedUsers()
{
List<string> UserNames = new List<string>();
foreach (var ConnectedUser in Users)
{
UserNames.Add(ConnectedUser.Name );
}
return UserNames;
}
}
我将在集线器中做很多其他事情,但现在我需要让客户端在不创建另一个连接的情况下发送消息
有没有办法可以访问用户在其他 views/activities 中通过身份验证后创建的连接?
*更新*
我按照 Leo Zhu 下面的回答更改了我的代码,但是当我尝试实例化 class 行时出现错误:
Client client = new Client.GetInstance(MyUser.Firstname + " " + MyUser.Lastname, MyUser.Username);
GetInstance does not exist
实际发生时。不知道为什么不是 "found".
*更新*
从行中删除了 new
关键字:
Client client = new Client.GetInstance(MyUser.Firstname + " " + MyUser.Lastname, MyUser.Username);
现在是:
Client client = Client.GetInstance(MyUser.Firstname + " " + MyUser.Lastname, MyUser.Username);
很有魅力。
或者你可以试试单例模式,比如(提供思路,需要自己编码):
public sealed class Client
{
// A private constructor to restrict the object creation from outside
private Client()
{
...
}
// A private static instance of the same class
private static Client instance = null;
public static Client GetInstance()
{
// create the instance only if the instance is null
if (instance == null)
{
instance = new Client();
}
// Otherwise return the already existing instance
return instance;
}
}
然后你可以通过Client.GetInstance();
打电话
我已经能够从 html 页面、aspx 页面和 Xamarin 客户端创建和接收来自 SignalR 中心的消息,这是我真正需要它来使用 Microsoft.AspNet.SignalR.Client v2 的应用程序.4.1 在 Visual Studio 2017 年使用 Xamarin。一旦我的 Xamarin 应用程序对用户进行身份验证,我就开始连接到集线器,接下来我连接一个事件来接收消息。所有这一切都工作得很好,我可以在 android 应用程序中接收消息,无论 activity 是当前的 activity 多亏了连接的事件。现在我有了这个工作,我希望能够从客户端向集线器发送消息,而无需创建与集线器的另一个连接。我查看了静态 classes,但无法使其正常工作。我的代码是:
这是用户通过身份验证后执行的代码:
// Start SignalR connection
Client client = new Client(MyUser.Firstname + " " + MyUser.Lastname, MyUser.Username);
await client.Connect();
// Wire up the message received event
client.OnMessageReceived += (sender2, message) => RunOnUiThread(() => showMessage(message));
从这里,用户可以从一个视图导航到另一个视图,并且能够通过事件和 showMessage
方法从中心接收消息。这一切都完美无缺。
我的客户代码: 此代码是从堆栈溢出工作示例中复制的,我根据自己的要求对其进行了修改。
namespace ChatClient.Shared
{
class Client
{
private readonly string _platform;
private readonly HubConnection _connection;
private readonly IHubProxy _proxy;
public event EventHandler<string> OnMessageReceived;
public Client(string platform, string username)
{
string _username = "username=" + username;
_platform = platform;
_connection = new HubConnection("https://Example.com/SignalRhub", _username);
_proxy = _connection.CreateHubProxy("chathub");
}
public async Task Connect()
{
await _connection.Start(); _proxy.On("broadcastMessage", (string platform, string message) =>
{
if (OnMessageReceived != null)
OnMessageReceived(this, string.Format("{0}: {1}", platform, message));
});
Send("Connected");
}
public async Task<List<string>> ConnectedUsers()
{
List<string> Users = await _proxy.Invoke<List<string>>("getConnectedUsers");
return Users;
}
public Task Send(string message)
{
return _proxy.Invoke("Send", _platform, message);
}
}
}
现在我需要做的是使用登录后创建的连接向集线器发送一条消息,以便分发给所有连接的用户。我不知道该怎么做,我试过使用静态 class 并尝试使用我在网上找到的方法,但似乎没有任何效果。
我的中心代码:
public class ChatHub : Hub
{
private static readonly List<User> Users = new List<User>();
public override Task OnConnected()
{
string userName = Context.QueryString["username"];
string firstname = Context.QueryString["firstname"];
string lastname = Context.QueryString["lastname"];
string connectionId = this.Context.ConnectionId;
var user = new User();
user.Name = userName;
user.ConnectionIds = connectionId;
try
{
Users.Add(user);
}
catch (Exception ex)
{
var msg = ex.Message;
}
// send list of connected users to client as a test
Send("Welcome " + userName, "Connected users are:");
foreach (var display in Users)
{
Send("",display.Name.ToString());
}
// test sending to a specific user
SendOne(connectionId, userName, "This is to a specific user.");
return base.OnConnected();
}
public override Task OnDisconnected(bool stopped)
{
string userName = Context.User.Identity.Name;
string connectionId = Context.ConnectionId;
var item = Users.Find(x => x.ConnectionIds == connectionId);
Send(item.Name , " disconnected.");
Users.Remove(item);
return base.OnDisconnected(true);
}
public void SendOne(string connectionId, string userName, string message)
{
Clients.Client(connectionId).broadcastMessage(userName, message);
}
public void Send(string name, string message)
{
// Call the broadcastMessage method to update clients.
Clients.All.broadcastMessage(name, message);
}
public List<string> getConnectedUsers()
{
List<string> UserNames = new List<string>();
foreach (var ConnectedUser in Users)
{
UserNames.Add(ConnectedUser.Name );
}
return UserNames;
}
}
我将在集线器中做很多其他事情,但现在我需要让客户端在不创建另一个连接的情况下发送消息
有没有办法可以访问用户在其他 views/activities 中通过身份验证后创建的连接?
*更新*
我按照 Leo Zhu 下面的回答更改了我的代码,但是当我尝试实例化 class 行时出现错误:
Client client = new Client.GetInstance(MyUser.Firstname + " " + MyUser.Lastname, MyUser.Username);
GetInstance does not exist
实际发生时。不知道为什么不是 "found".
*更新*
从行中删除了 new
关键字:
Client client = new Client.GetInstance(MyUser.Firstname + " " + MyUser.Lastname, MyUser.Username);
现在是:
Client client = Client.GetInstance(MyUser.Firstname + " " + MyUser.Lastname, MyUser.Username);
很有魅力。
或者你可以试试单例模式,比如(提供思路,需要自己编码):
public sealed class Client
{
// A private constructor to restrict the object creation from outside
private Client()
{
...
}
// A private static instance of the same class
private static Client instance = null;
public static Client GetInstance()
{
// create the instance only if the instance is null
if (instance == null)
{
instance = new Client();
}
// Otherwise return the already existing instance
return instance;
}
}
然后你可以通过Client.GetInstance();