Мне удалось создать и получить сообщения от концентратора SignalR со страницы html, aspx и клиента Xamarin - приложения, которое мне действительно нужно для использования Microsoft.AspNet.SignalR.Client v2.4.1 с использованием Xamarin в Visual Studio 2017. Как только мое приложение Xamarin аутентифицирует пользователя, я запускаю соединение с концентратором, затем подключаю событие для получения сообщений. Все это прекрасно работает, и я могу получать сообщения в приложении для Android независимо от того, какое действие является текущим, благодаря событию, которое подключено. Теперь, когда у меня есть эта работа, я хочу иметь возможность отправлять сообщения от клиента на концентратор без создания другого соединения с концентратором. Я посмотрел на статические классы, но не могу заставить это работать. Мой код:
Это код, который выполняется после аутентификации пользователя:
// 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);
}
}
}
Теперь мне нужно отправить сообщение на концентратор, используя соединение, созданное сразу после входа в систему, для распространения среди всех подключенных пользователей. Я не могу понять, как это сделать, я пытался использовать статический класс и пытался использовать методы, которые я нашел в Интернете, но, похоже, ничего не работает.
Код моего концентратора:
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;
}
}
Есть много других вещей, которые я буду делать в хабе, но сейчас мне нужно, чтобы клиент отправлял сообщения без создания другого соединения
Есть ли способ получить доступ к соединению, созданному после аутентификации пользователя в других представлениях / действиях?
* Обновление *
Я изменил свой код в соответствии с ответом Лео Чжу ниже, однако я получаю сообщение об ошибке при попытке создать экземпляр класса в строке:
Client client = new Client.GetInstance(MyUser.Firstname + " " + MyUser.Lastname, MyUser.Username);
GetInstance does not exist
когда это действительно так. Понятия не имею, почему он не "найден".
* Обновление *
Удалено ключевое слово new
из строки:
Client client = new Client.GetInstance(MyUser.Firstname + " " + MyUser.Lastname, MyUser.Username);
Теперь оно гласит:
Client client = Client.GetInstance(MyUser.Firstname + " " + MyUser.Lastname, MyUser.Username);
Работает как шарм.