|
|
|
SignalR กระจายข้อมูลให้แต่ล่ะ client ตาม userId ได้หรือไม่ครับ |
|
|
|
|
|
|
|
ทำไว้ตั้งแต่ ปี 57 แถมเป็น win phone อีก
แนวทางก็คือ
สร้าง hub
ถ้าส่งเป็น group ก็ต้องสั่งให้ client join group ก่อน
ถ้าส่งให้ client เลยก็ delegate ไป
อย่างของ win phone ซึ่งเป็น mobile app มันจะแยกเป็น 2 ส่วน คือ server กับ mobile
ถ้าจะเอามาปรับใช้เป็น web ก็ไม่ต้องแยกโปรเจ็ค
officer xaml
private async void CommandInvokedHandler(IUICommand command)
{
if (command.Label == "OK")
{
App.StatusBar.ShowProgressIndicator();
bool status = (bool)command.Id;
IMobileServiceTable<TouristSos> soses = App.MobileService.GetTable<TouristSos>();
MobileServiceCollection<TouristSos, TouristSos> sosesCollection = await soses.Where(s => s.Id == sosID).ToCollectionAsync();
TouristSos sos = sosesCollection.SingleOrDefault();
IMobileServiceTable<TouristProfile> tourists = App.MobileService.GetTable<TouristProfile>();
MobileServiceCollection<TouristProfile, TouristProfile> touristsCollection = await tourists.Where(t => t.TouristID == sos.TouristID).ToCollectionAsync();
TouristProfile tourist = touristsCollection.SingleOrDefault();
if (status)
{
sos.StatusCode = "F";
await soses.UpdateAsync(sos);
tourist.Lock = false;
await tourists.UpdateAsync(tourist);
IMobileServiceTable<Rating> Ratings = App.MobileService.GetTable<Rating>();
Rating newRating = new Rating()
{
SosID = sos.Id,
OfficerID = App.Settings.OfficerID,
Score = 0,
CreateDate = DateTime.Now
};
await Ratings.InsertAsync(newRating);
IMobileServiceTable<OfficerResponse> offcerResponses = App.MobileService.GetTable<OfficerResponse>();
OfficerResponse newResponse = new OfficerResponse()
{
SosID = sos.Id,
OfficerID = App.Settings.OfficerID,
StatusCode = sos.StatusCode,
CreateDate = DateTime.Now
};
await offcerResponses.InsertAsync(newResponse);
IMobileServiceTable<SosLog> sosLogs = App.MobileService.GetTable<SosLog>();
SosLog newLog = new SosLog()
{
SosID = sosID,
StatusCode = sos.StatusCode,
CreateDate = System.DateTime.Now
};
await sosLogs.InsertAsync(newLog);
App.SignalR.OfficerCloseJob(sos.TouristUserID);
}
else
{
sos.StatusCode = "P";
await soses.UpdateAsync(sos);
tourist.Prank += 1;
tourist.Lock = false;
await tourists.UpdateAsync(tourist);
IMobileServiceTable<OfficerResponse> offcerResponses = App.MobileService.GetTable<OfficerResponse>();
OfficerResponse newResponse = new OfficerResponse()
{
SosID = sos.Id,
OfficerID = App.Settings.OfficerID,
StatusCode = sos.StatusCode,
CreateDate = DateTime.Now
};
await offcerResponses.InsertAsync(newResponse);
IMobileServiceTable<SosLog> sosLogs = App.MobileService.GetTable<SosLog>();
SosLog newLog = new SosLog()
{
SosID = sosID,
StatusCode = sos.StatusCode,
CreateDate = System.DateTime.Now
};
await sosLogs.InsertAsync(newLog);
App.SignalR.OfficerClosePrank(sos.TouristUserID);
}
//OfficerCloseJobRequest request = new OfficerCloseJobRequest()
//{
// Status = (bool)command.Id,
// TouristUserID = sos.TouristUserID
//};
//await App.MobileService.InvokeApiAsync<OfficerCloseJobRequest, string>("OfficerCloseJob", request);
App.StatusBar.HideProgressIndicator();
this.Frame.Navigate(typeof(MainPage));
}
}
hub ในส่วนของ office mobile app
using Microsoft.AspNet.SignalR.Client;
using Microsoft.WindowsAzure.MobileServices;
using SosThailand.Officer.DataModels;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Windows.UI.Core;
namespace SosThailand.Officer.Services.SignalR
{
public class SosThailandSignalRHub
{
private HubConnection _connection;
private IHubProxy _proxy;
private readonly CoreDispatcher _dispatcher;
public event EventHandler NewSosArrived;
public event EventHandler LostBidding;
public event EventHandler CancelBidding;
public event EventHandler WonBidding;
public event SosBiddingLogEventHandler ReceiveBiddingLog;
public SosThailandSignalRHub()
{
_dispatcher = CoreWindow.GetForCurrentThread().Dispatcher;
}
public async Task ConnectAsync(MobileServiceUser user)
{
_connection = new HubConnection(App.MobileService.ApplicationUri.AbsoluteUri);
DebugTextWriter writer = new DebugTextWriter();
_connection.TraceWriter = writer;
_connection.TraceLevel = TraceLevels.All;
_connection.Closed += () => writer.WriteLine("hubConnection.Closed");
_connection.ConnectionSlow += () => writer.WriteLine("hubConnection.ConnectionSlow");
_connection.Error += (error) => writer.WriteLine("hubConnection.Error {0}: {1}", error.GetType(), error.Message);
_connection.Reconnected += () => writer.WriteLine("hubConnection.Reconnected");
_connection.Reconnecting += () => writer.WriteLine("hubConnection.Reconnecting");
_connection.StateChanged += (change) => writer.WriteLine("hubConnection.StateChanged {0} => {1}", change.OldState, change.NewState);
if (user != null)
{
_connection.Headers["x-zumo-auth"] = user.MobileServiceAuthenticationToken;
}
else
{
_connection.Headers["x-zumo-application"] = App.MobileService.ApplicationKey;
}
_proxy = _connection.CreateHubProxy("SosThailandSignalRHub");
_proxy.On("NewSosArrived", () => SignalR_OnNewSosArrived());
_proxy.On("LostBidding", () => SignalR_OnLostBidding());
_proxy.On("CancelBidding", () => SignalR_OnCancelBidding());
_proxy.On("WonBidding", () => SignalR_OnWonBidding());
_proxy.On<BiddingLog>("SendBiddingLog", (log) => SignalR_OnReceiveBiddingLog(log));
await _connection.Start();
}
public async void Join(string group)
{
await _proxy.Invoke("JoinGroup", group);
}
public async void Leave(string group)
{
await _proxy.Invoke("LeaveGroup", group);
}
public async void SossArrived(string provinceCode)
{
await _proxy.Invoke("SosArrived", provinceCode);
}
public async void OfficerLost(string officerUserID)
{
await _proxy.Invoke("OfficerLost", officerUserID);
}
public async void BiddingLog(string sosID, BiddingLog log)
{
await _proxy.Invoke("BiddingLog", new object[] { sosID, log });
}
public async void OfficerWon(string sosID)
{
await _proxy.Invoke("OfficerWon", sosID);
}
public async void OfficerCloseJob(string touristUserID)
{
await _proxy.Invoke("OfficerCloseJob", touristUserID);
}
public async void OfficerClosePrank(string touristUserID)
{
await _proxy.Invoke("OfficerClosePrank", touristUserID);
}
private async void SignalR_OnNewSosArrived()
{
await _dispatcher.RunAsync(CoreDispatcherPriority.Normal, delegate
{
if (this.NewSosArrived != null)
{
this.NewSosArrived(this, new EventArgs());
}
});
}
private async void SignalR_OnReceiveBiddingLog(BiddingLog log)
{
await _dispatcher.RunAsync(CoreDispatcherPriority.Normal, delegate
{
if (this.ReceiveBiddingLog != null)
{
this.ReceiveBiddingLog(this, new SosBiddingLogEventArgs(log));
}
});
}
private async void SignalR_OnLostBidding()
{
await _dispatcher.RunAsync(CoreDispatcherPriority.Normal, delegate
{
if (this.LostBidding != null)
{
this.LostBidding(this, new EventArgs());
}
});
}
private async void SignalR_OnCancelBidding()
{
await _dispatcher.RunAsync(CoreDispatcherPriority.Normal, delegate
{
if (this.CancelBidding != null)
{
this.CancelBidding(this, new EventArgs());
}
});
}
private async void SignalR_OnWonBidding()
{
await _dispatcher.RunAsync(CoreDispatcherPriority.Normal, delegate
{
if (this.WonBidding != null)
{
this.WonBidding(this, new EventArgs());
}
});
}
public void Disconnect()
{
_connection.Stop();
_connection.Dispose();
}
}
}
hub ในส่วนของ mobile server ทำหน้าที่เป็นตัวกลาง
using System.Collections.Concurrent;
using System.Threading.Tasks;
namespace SosThailandService.Hubs
{
[HubName("SosThailandSignalRHub")]
public class SosThailandSignalRHub : Hub
{
public void JoinGroup(string group)
{
Groups.Add(Context.ConnectionId, group);
}
public void LeaveGroup(string group)
{
Groups.Remove(Context.ConnectionId, group);
}
public void SentSos(string provinceCode)
{
Clients.OthersInGroup(provinceCode).NewSosArrived();
}
public void BiddingLog(string sosID, BiddingRequest log)
{
Clients.OthersInGroup(sosID).SendBiddingLog(log);
}
public void OfficerLost(string officerUserID)
{
Clients.User(officerUserID).LostBidding();
}
public void OfficerCloseJob(string touristUserID)
{
Clients.User(touristUserID).CloseJob();
}
public void OfficerClosePrank(string touristUserID)
{
Clients.User(touristUserID).ClosePrank();
}
public void OfficerWon(string sosID)
{
Clients.User(sosID).WonBidding();
}
public void TouristCancelBidding(string sosID)
{
Clients.OthersInGroup(sosID).CancelBidding();
}
}
}
hub ในส่วนของ tourist mobile app
using Microsoft.AspNet.SignalR.Client;
using Microsoft.WindowsAzure.MobileServices;
using SosThailand.Tourist.DataModels;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Windows.UI.Core;
namespace SosThailand.Tourist.Services.SignalR
{
public class SosThailandSignalRHub
{
private HubConnection _connection;
private IHubProxy _proxy;
private readonly CoreDispatcher _dispatcher;
public event EventHandler OfficerAcceptJob;
public event EventHandler OfficerFinishJob;
public event EventHandler OfficerCancelJob;
public event SosBiddingLogEventHandler ReceiveBiddingLog;
public SosThailandSignalRHub()
{
_dispatcher = CoreWindow.GetForCurrentThread().Dispatcher;
}
public async Task ConnectAsync(MobileServiceUser user)
{
_connection = new HubConnection(App.MobileService.ApplicationUri.AbsoluteUri);
DebugTextWriter writer = new DebugTextWriter();
_connection.TraceWriter = writer;
_connection.TraceLevel = TraceLevels.All;
_connection.Closed += () => writer.WriteLine("hubConnection.Closed");
_connection.ConnectionSlow += () => writer.WriteLine("hubConnection.ConnectionSlow");
_connection.Error += (error) => writer.WriteLine("hubConnection.Error {0}: {1}", error.GetType(), error.Message);
_connection.Reconnected += () => writer.WriteLine("hubConnection.Reconnected");
_connection.Reconnecting += () => writer.WriteLine("hubConnection.Reconnecting");
_connection.StateChanged += (change) => writer.WriteLine("hubConnection.StateChanged {0} => {1}", change.OldState, change.NewState);
if (user != null)
{
_connection.Headers["x-zumo-auth"] = user.MobileServiceAuthenticationToken;
}
else
{
_connection.Headers["x-zumo-application"] = App.MobileService.ApplicationKey;
}
_proxy = _connection.CreateHubProxy("SosThailandSignalRHub");
_proxy.On("WonBidding", () => SignalR_OnOfficerAcceptJob());
_proxy.On("CloseJob", () => SignalR_OnOfficerFinishJob());
_proxy.On("ClosePrank", () => SignalR_OnOfficerCancelJob());
_proxy.On<BiddingLog>("SendBiddingLog", (log) => SignalR_OnReceiveBiddingLog(log));
await _connection.Start();
}
public async void Join(string group)
{
await _proxy.Invoke("JoinGroup", group);
}
public async void Leave(string group)
{
await _proxy.Invoke("LeaveGroup", group);
}
public async void SentSos(string provinceCode)
{
await _proxy.Invoke("SentSos", provinceCode);
}
public async void TouristCancelBidding(string sosID)
{
await _proxy.Invoke("TouristCancelBidding", sosID);
}
private async void SignalR_OnReceiveBiddingLog(BiddingLog log)
{
await _dispatcher.RunAsync(CoreDispatcherPriority.Normal, delegate
{
if (this.ReceiveBiddingLog != null)
{
this.ReceiveBiddingLog(this, new SosBiddingLogEventArgs(log));
}
});
}
private async void SignalR_OnOfficerAcceptJob()
{
await _dispatcher.RunAsync(CoreDispatcherPriority.Normal, delegate
{
if (this.OfficerAcceptJob != null)
{
this.OfficerAcceptJob(this, new EventArgs());
}
});
}
private async void SignalR_OnOfficerFinishJob()
{
await _dispatcher.RunAsync(CoreDispatcherPriority.Normal, delegate
{
if (this.OfficerFinishJob != null)
{
this.OfficerFinishJob(this, new EventArgs());
}
});
}
private async void SignalR_OnOfficerCancelJob()
{
await _dispatcher.RunAsync(CoreDispatcherPriority.Normal, delegate
{
if (this.OfficerCancelJob != null)
{
this.OfficerCancelJob(this, new EventArgs());
}
});
}
}
}
ยกตัวอย่าง จากใน code
office สั่ง close job จาก xaml ด้วย
Code (C#)
App.SignalR.OfficerCloseJob(sos.TouristUserID);
ทำสั่งก็จะถูก invoke ด้วย hub ของ office
Code (C#)
public async void OfficerCloseJob(string touristUserID)
{
await _proxy.Invoke("OfficerCloseJob", touristUserID);
}
ไปยัง hub ของ server ซึ่งทำหน้าที่เป้นตัวกลางติดต่อกันระหว่าง officer กับ tourist
Code (C#)
public void OfficerCloseJob(string touristUserID)
{
Clients.User(touristUserID).CloseJob();
}
จากนั้น hub ของ tourist ก็จะ delegate เพื่อ update หน้าของตัว
Code (C#)
_proxy.On("CloseJob", () => SignalR_OnOfficerFinishJob());
private async void SignalR_OnOfficerFinishJob()
{
await _dispatcher.RunAsync(CoreDispatcherPriority.Normal, delegate
{
if (this.OfficerFinishJob != null)
{
this.OfficerFinishJob(this, new EventArgs());
}
});
}
|
|
|
|
|
Date :
2017-06-26 09:46:22 |
By :
ห้ามตอบเกินวันละ 2 กระทู้ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Load balance : Server 04
|