I have a simple SignalR based timer on the server which updates my dashboard panel. Everything works fine on VS2012, however when I deploy to azure or IIS7.5 it can't stablish a connection. Here are the errors from console.
This is my hub:
public class BroadCastHub : Hub
{
// Is set via the constructor on each creation
//private readonly Broadcaster _broadcaster;
private readonly TimeSpan BroadcastInterval = TimeSpan.FromMilliseconds(AppConfig.Instance.Tracing.RefreshRate * 1000);
public BroadCastHub() {
if (AppConfig.Instance.Tracing.EnableServerAutoUpdates)
{
// Start the broadcast loop
var _broadcastLoop = new Timer(
UpdatePanel,
null,
BroadcastInterval,
BroadcastInterval);
}
}
public void UpdatePanel()
{
UpdatePanel(null);
}
public void UpdatePanel(object o)
{
var appService = DependencyResolver.Current.GetService<IApplicationService>();
var applications = appService.GetSummaryCollection();
var model = applications.Select(c => new ApplicationState
{
id = c.id,
lastRunTime = c.lastRunTime.GetValueOrDefault(),
totalTraces = c.totalTraces,
status = appService.GetStatus(c.lastRunTime, c.lastTraceType, c.traceInterval)
}.InjectFrom(c)).Cast<ApplicationState>().AsQueryable();
Clients.All.updatePanel(model);
}
}
This is my JS code (Angular):
function init() {
var broadCastHub = $.connection.broadCastHub;
broadCastHub.client.updatePanel = function(apps) {
console.log('Broadcasting');
};
$.connection.hub.start()
.done(function () {
console.log('Now connected, connection ID=' + $.connection.hub.id);
})
.fail(function () { console.log('Could not Connect!'); });
//listenBroadcast();
}
EDIT:
Curiously, I saw a similar article and implemented like this:
public class Broadcaster
{
private readonly IApplicationService _applicationService;
private readonly static Lazy<Broadcaster> _instance = new Lazy<Broadcaster>(() => new Broadcaster());
// We're going to broadcast to all clients a maximum of 25 times per second
private readonly TimeSpan BroadcastInterval = TimeSpan.FromMilliseconds(AppConfig.Instance.Tracing.RefreshRate * 1000);
private readonly IHubContext _hubContext;
private Timer _broadcastLoop;
public Broadcaster()
{
_applicationService = DependencyResolver.Current.GetService<IApplicationService>();
// Save our hub context so we can easily use it
// to send to its connected clients
_hubContext = GlobalHost.ConnectionManager.GetHubContext<BroadCastHub>();
if (AppConfig.Instance.Tracing.EnableServerAutoUpdates) {
// Start the broadcast loop
_broadcastLoop = new Timer(
UpdatePanel,
null,
BroadcastInterval,
BroadcastInterval);
}
}
public void UpdatePanel(object state)
{
var applications = _applicationService.GetSummaryCollection();
var model = applications.Select(c => new ApplicationState
{
id = c.id,
lastRunTime = c.lastRunTime.GetValueOrDefault(),
totalTraces = c.totalTraces,
status = _applicationService.GetStatus(c.lastRunTime, c.lastTraceType, c.traceInterval)
}.InjectFrom(c)).Cast<ApplicationState>().AsQueryable();
_hubContext.Clients.All.updatePanel(model);
}
public static Broadcaster Instance
{
get
{
return _instance.Value;
}
}
}
My hub:
public class BroadCastHub : Hub
{
// Is set via the constructor on each creation
private readonly Broadcaster _broadcaster;
public BroadCastHub()
: this(Broadcaster.Instance)
{
}
public BroadCastHub(Broadcaster broadcaster)
{
_broadcaster = broadcaster;
}
public void UpdatePanel()
{
_broadcaster.UpdatePanel(null);
}
}
Thanks for the article, I'll take a deeper look.
Related
I am trying to write Xamarin.Forms UI tests using Moq to mock my authentication interface: [previous question][1]. I have refactored my application so that my SignIn(string username, string password) method is inside a class that implements the IAuthService. I am now having issues with mocking the IAuthService to essentially 'replace' the actual sign in verification that occurs when clicking the Sign In button. In my CloudAuthService class (which implements IAuthService), I am authenticating to Amazon Cognito, but I want to mock this result within the UI test so it is not calling the cloud service.
EDIT: after many suggestions, I have decided to include my current implementation below. This still doesn't appear to fully work despite the
output from Console.WriteLine(App.AuthApi.IsMockService()); within the BeforeEachTest() method results in true (as expected).
However, running the same thing within the App() constructor method results in false. So it doesn't appear to be running before the app actually starts, is there a way to have UITest code that runs before the app initializes?
LoginPage
[XamlCompilation(XamlCompilationOptions.Compile)]
public sealed partial class LoginPage
{
private readonly IBiometricAuthentication _bioInterface;
private static readonly Lazy<LoginPage>
Lazy =
new Lazy<LoginPage>
(() => new LoginPage(App.AuthApi));
public static LoginPage Instance => Lazy.Value;
private string _username;
private string _password;
private LoginPageViewModel _viewModel;
private IAuthService _authService;
public LoginPage(IAuthService authService)
{
InitializeComponent();
_authService = authService;
_viewModel = new LoginPageViewModel();
BindingContext = _viewModel;
}
private void LoginButtonClicked(object sender, EventArgs args)
{
_username = UsernameEntry.Text;
_password = PasswordEntry.Text;
LoginToApplication();
}
public async void LoginToApplication()
{
AuthenticationContext context = await _authService.SignIn(_username, _password);
}
}
App Class
public partial class App
{
public static IAuthService AuthApi { get; set; } = new AWSCognito()
public App()
{
Console.WriteLine(AuthApi.IsMockService())
// AuthApi = new AWSCognito(); // AWSCognito implements IAuthService
InitializeComponent();
MainPage = new NavigationPage(new LoginPage(AuthApi));
}
}
Test Class
class LoginPageTest
{
IApp app;
readonly Platform platform;
public LoginPageTest(Platform platform)
{
this.platform = platform;
}
[SetUp]
public void BeforeEachTest()
{
var mocker = new Mock<IAuthService>();
var response = new AuthenticationContext(CognitoResult.Ok)
{
IdToken = "SUCCESS_TOKEN"
};
mocker.Setup(x => x.SignIn(It.IsAny<string>(), It.IsAny<string>())).Returns(() => new MockAuthService().SignIn("a", "a"));
mocker.Setup(x => x.IsMockService()).Returns(() => new MockAuthService().IsMockService());
App.AuthApi = mocker.Object;
Console.WriteLine(App.AuthApi.IsMockService());
app = AppInitializer.StartApp(platform);
}
[Test]
public void ClickingLoginWithUsernameAndPasswordStartsLoading()
{
app.WaitForElement(c => c.Marked("Welcome"));
app.EnterText(c => c.Marked("Username"), new string('a', 1));
app.EnterText(c => c.Marked("Password"), new string('a', 1));
app.Tap("Login");
bool state = app.Query(c => c.Class("ProgressBar")).FirstOrDefault().Enabled;
Assert.IsTrue(state);
}
}
Your problem seems to be that you've injected the mock after you run through the test. This means when it's executing it's using the original AuthService. If we rearrange the code to move the injection before anything gets executed we should see the result we expect:
// let's bring this mock injection up here
var mocker = new Mock<IAuthService>();
mocker.Setup(x => x.SignIn(It.IsAny<string>(), It.IsAny<string>())).Returns(Task.FromResult(response)).Verifiable();
App.AuthApi = mocker.Object;
// now we try to login, which should call the mock methods of the auth service
app.WaitForElement(c => c.Marked("Welcome to Manuly!"));
app.EnterText(c => c.Marked("Username"), new string('a', 1));
app.EnterText(c => c.Marked("Password"), new string('a', 1));
app.Tap("Login");
var response = new AuthenticationContext(CognitoResult.Ok)
{
IdToken = "SUCCESS_TOKEN",
};
bool state = app.Query(c => c.Class("ProgressBar")).FirstOrDefault().Enabled;
Assert.IsTrue(state);
Now try executing it, and it should do as you desire.
EDIT:
As pointed out in the comments by Nkosi the static Auth service is set in the constructor preventing this.
SO this will need to be changed too:
public partial class App
{
public static IAuthService AuthApi { get; set; } =new AWSCognito(); // assign it here statically
public App()
{
// AuthApi = new AWSCognito(); <-- remove this
InitializeComponent();
MainPage = new NavigationPage(new LoginPage(AuthApi));
}
}
Description
I want to create an object of a class with dependency injection. If I set the parameter manually I got the exception Cannot access a disposed of the object..
This Application is a Blazor wasm with Dotnet core 3.1. I´ve created a Middleware that should connect to a query console. So I have a static list that contains all query clients. If a client is missing it will be created.
Invoke Async in the middleware:
public async Task InvokeAsync(HttpContext context,
IConfiguration configuration,
IInstanceControlRepository instanceControlRepository,
IServiceProvider serviceProvider)
{
_configuration = configuration;
_instanceControlRepository = instanceControlRepository;
long timestamp = new DateTimeOffset(DateTime.Now).ToUnixTimeSeconds();
var instances = _instanceControlRepository.GetAllInstances();
if (_time + 3 <= timestamp)
{
_time = timestamp;
// Remove
foreach(var client in TeamspeakInstanceQueryClients.ToList())
{
var cl = instances.ToList().Find(el => el.Id == client.Instance.Id);
if(cl == null)
{
client.Dispose();
TeamspeakInstanceQueryClients.RemoveAll(el => el.Instance.Equals(client.Instance));
}
}
// Create & Update
foreach (var instance in instances)
{
var queryClient = TeamspeakInstanceQueryClients.Find(el => el.Instance.Id == instance.Id);
if(queryClient == null)
{
//var test = ActivatorUtilities.CreateInstance<ApplicationDbContext>(serviceProvider);
//var dbContext = serviceProvider.GetService<ApplicationDbContext>();
//queryClient = new TeamspeakInstanceQueryClient(new InstancesControlRepository(ActivatorUtilities.CreateInstance<ApplicationDbContext>(serviceProvider)));
queryClient = new TeamspeakInstanceQueryClient(serviceProvider);
_ = queryClient.Connect(instance);
TeamspeakInstanceQueryClients.Add(queryClient);
}
else
{
_ = queryClient.CheckInstanceData(instance);
}
}
}
await _next(context);
}
TeamspeakInstanceQueryClient.cs
public partial class TeamspeakInstanceQueryClient : ITeamspeakInstanceQueryClient
{
private IInstanceControlRepository _instanceControlRepository;
private const short MAX_RETRYS = 3;
private const short TIME_TO_RETRY = 10;
private EventHandler OnConnected;
public Instance Instance { get; internal set; }
public TeamSpeakClient Client { get; internal set; }
public bool IsSelected { get; internal set; }
private short _connectionTrys = 0;
public TeamspeakInstanceQueryClient(IServiceProvider serviceProvider)
{
_instanceControlRepository = new InstancesControlRepository(ActivatorUtilities.CreateInstance<ApplicationDbContext>(serviceProvider));
Init();
}
}
InstancesControlRepository.cs
public class InstancesControlRepository : IInstanceControlRepository
{
private readonly ApplicationDbContext _applicationDbContext;
public InstancesControlRepository(ApplicationDbContext applicationDbContext)
{
_applicationDbContext = applicationDbContext;
}
}
Startup.cs
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<ApplicationDbContext>(option =>
option.UseMySql(
Configuration.GetConnectionString("DefaultConnection"),
mySqlOptions => mySqlOptions.ServerVersion(new System.Version(10, 4, 13), ServerType.MariaDb)
)
);
services.AddScoped<IInstanceControlRepository, InstancesControlRepository>();
services.AddScoped<IServerQueryRepository, ServerQueryRepository>();
What I´ve tried
I´ve tried to create the class with the service provider but it comes to the same error
I´ve tried to create the missing parameters with the service provider in the created class. But I need to inject the service provider which also creates the exception Cannot access a disposed of the object. Object name: 'IServiceProvider'.
I´ve tried to make the service provider static so it can´t be disposed but it is disposed.
It seems that instance of IServiceProvider is a scoped one and it is disposed when the scope ends (in the end of request I assume). You can try define singleton factory for your TeamspeakInstanceQueryClient and use it:
class ClientFactory
{
private IServiceProvider _sp { get; set; }
private IServiceScope _scope { get; set; }
public MyClass(IServiceProvider sp)
{
_sp = sp;
_scope = sp.CreateScope();
}
public TeamspeakInstanceQueryClient Create() => new TeamspeakInstanceQueryClient(_scope.ServiceProvider);
}
// register it as singleton
services.AddSingleton<ClientFactory>();
and use it in InvokeAsync:
var factory = serviceProvider.GetRequiredService<ClientFactory>();
queryClient = factory.Create();
P.S. this code can be improved vastly and is used only for demonstration purposes.
I want to Create WebSocket Example in which i do not want to refresh the page for getting latest data.
I Create one Html page in which create one object of websocket.
E.g
ClientSide Implementation
var ws = new WebSocket(hostURL);
ws.onopen = function ()
{
// When Connection Open
};
ws.onmessage = function (evt)
{
// When Any Response come from WebSocket
}
ws.onclose = function (e)
{
// OnClose of WebSocket Conection
}
Server Side Implementation
public class WebSocketManager : WebSocketHandler
{
private static WebSocketCollection WebSocketObj4AddMessage = new WebSocketCollection();
public override void OnOpen()
{
// Do when Connection Is Open
}
public override void OnClose()
{
// Close Connection
}
public override void OnMessage(string message)
{
// When Any Message Sent to Client
}
}
Is I am doing right way to use WebSocket ?
Please help me to clear out in this section.
Here a sample.
First you have to install Asp.net SignalR package along with its dependenies.
You have call the SignalR when the app starts
namespace ABC
{
public partial class Startup
{
public void Configuration(IAppBuilder app)
{
ConfigureAuth(app);
app.MapSignalR(); <--{Add this line}
}
}
}
You have start the SqlDependency when app start and stop when app stops in the Global.asax file.
string ConnectionString = ConfigurationManager.ConnectionStrings["ConnectionStringsName"].ConnectionString;
protected void Application_Start()
{
SqlDependency.Start(ConnectionString);
}
protected void Application_End()
{
SqlDependency.Stop(ConnectionString);
}
You have to create custom Hubclass extending Hub Base class
public class MessagesHub : Hub
{
[HubMethodName("sendMessages")]
public void SendMessages()
{
IHubContext context = GlobalHost.ConnectionManager.GetHubContext<MessagesHub>();
context.Clients.All.updateMessages();
}
}
Then in the client page, you have add these code in the javascript section
$(function () {
// Declare a proxy to reference the hub.
var notifications = $.connection.messagesHub;
//debugger;
// Create a function that the hub can call to broadcast messages.
notifications.client.updateMessages = function () {
getAllMessages()
};
// Start the connection.
$.connection.hub.start().done(function () {
getAllMessages();
}).fail(function (e) {
alert(e);
});
});
function getAllMessages() {
$.ajax({
url: '../../Notifications/GetNotificationMessages',
.
.
}
The server call this function when there there is any change in the database table using sqlDependency
The getAllMessages() is the controller for your code to handle, that should be shown in the view page and it will be call when the app starts and any change in db
public ActionResult GetNotificationMessages()
{
NotificationRepository notification = new NotificationRepository();
return PartialView("_NotificationMessage");
}
The in model class
public class NotificationRepository
{
readonly string connectionString = ConfigurationManager.ConnectionStrings["InexDbContext"].ConnectionString;
public IEnumerable<Notification> GetAllMessages(string userId)
{
var messages = new List<Notification>();
using(var connection = new SqlConnection(connectionString))
{
connection.Open();
using (var command = new SqlCommand(#"SELECT [NotificationID], [Message], [NotificationDate], [Active], [Url], [userId] FROM [dbo].[Notifications] WHERE [Active] = 1 AND [userId] ='" + userId + "'", connection))
{
command.Notification = null;
var dependency = new SqlDependency(command);
dependency.OnChange += new OnChangeEventHandler(dependency_OnChange);
if (connection.State == ConnectionState.Closed)
{
connection.Open();
}
var reader = command.ExecuteReader();
while (reader.Read())
{
messages.Add(item: new Notification { NotificationID = (int)reader["NotificationID"], Message = (string)reader["Message"], Url = (string)reader["Url"] });
}
}
}
return messages;
}
private void dependency_OnChange(object sender, SqlNotificationEventArgs e)
{
if (e.Type == SqlNotificationType.Change)
{
MessagesHub message = new MessagesHub();
message.SendMessages();
}
}
}
This well show latest data when the database table is updated. the message will shown at runtime.
Hope this helps
You are on the right path
You can refer this if I am not late ...This is working example
CLIENT SIDE
var ws;
var username = "JOHN";
function startchat() {
var log= $('log');
var url = 'ws://<server path>/WebSocketsServer.ashx?username=' + username;
ws = new WebSocket(url);
ws.onerror = function (e) {
log.appendChild(createSpan('Problem with connection: ' + e.message));
};
ws.onopen = function () {
ws.send("I am Active-" +username);
};
ws.onmessage = function (e) {
if (e.data.toString() == "Active?") {
ws.send("I am Active-" + username);
}
else {
}
};
ws.onclose = function () {
log.innerHTML = 'Closed connection!';
};
}
</script>
<div id="log">
</div>
Server Side in Websocketserver.ashx page
public class WebSocketsServer : IHttpHandler
{
public void ProcessRequest(HttpContext context)
{
if (context.IsWebSocketRequest)
{
context.AcceptWebSocketRequest(new MicrosoftWebSockets());
}
}
public bool IsReusable
{
get
{
return false;
}
}
}
Add below class in the server side
public class MicrosoftWebSockets : WebSocketHandler
{
private static WebSocketCollection clients = new WebSocketCollection();
private string msg;
public override void OnOpen()
{
this.msg = this.WebSocketContext.QueryString["username"];
clients.Add(this);
clients.Broadcast(msg);
}
public override void OnMessage(string message)
{
clients.Broadcast(string.Format(message));
}
public override void OnClose()
{
clients.Remove(this);
clients.Broadcast(string.Format(msg));
}
add this dll to the above class
using Microsoft.Web.WebSockets;
I donot remeber where I got the reference ...but above code is derived from my current working application
I have application in which I am showing data from sensors using SignalR. It uses ASP.net membership to authenticate the users. It all works fine if I only open one browser window(e.g. Firefox). If I open same website in another browser e.g. Chrome at the same time then signalR connection to firefox browser drops even if the user is different. This is what I am using to broadcast message:
Hub
[Authorize]
public class DataHub:Hub
{
private readonly RealTimeData _sensor;
public DataHub() : this(RealTimeData.Instance) { }
public DataHub(RealTimeData data)
{
_sensor = data;
}
public override Task OnConnected()
{
// _sensor.UserId = Context.ConnectionId; changed to
_sensor.UserId = Membership.GetUser().ProviderUserKey.ToString();
return base.OnConnected();
}
}
public class RealTimeData
{
//User Id
public String UserId { get; set; }
private readonly static Lazy<RealTimeData> _instance = new Lazy<RealTimeData>(() => new RealTimeData(GlobalHost.ConnectionManager.GetHubContext<DataHub>().Clients));// Singleton instance
private IHubConnectionContext Clients;
private void BroadcastDataOfAllSensors(List<SensorDetails> sensor)
{
//Clients.Client(UserId).updateDashboard(sensor);changed to
Clients.User(UserId).updateDashboard(sensor);
}
}
Application Startup
public class StartUp
{
public void Configuration(IAppBuilder app)
{
var idProvider = new UserIdProvider();
GlobalHost.DependencyResolver.Register(typeof(IUserIdProvider), () => idProvider);
app.MapSignalR();
}
}
UserId
public class UserIdProvider : IUserIdProvider
{
public string GetUserId(IRequest request)
{
var userId = Membership.GetUser().ProviderUserKey;
return userId.ToString();
}
}
I have a signalr client that I want to be global.
I think creating the signalr client in the Init() of the endpointconfig would be best.
public class EndpointConfig : IConfigureThisEndpoint, AsA_Server, IWantCustomInitialization
{
public static HubConnection hubConnection;
public static IHubProxy hubProxy;
public void Init()
{
Configure.With()
.DefiningEventsAs(t => t.Namespace != null && t.Namespace.Contains(".Events."))
.DefiningMessagesAs(t => t.Namespace != null && t.Namespace.Contains(".Messages."))
.StructureMapBuilder(new Container(new DependencyRegistry()));
Configure.Serialization.Json();
hubConnection = new HubConnection("http://localhost:58120");
hubProxy = hubConnection.CreateHubProxy("AmsHub");
hubProxy.On<string>("receiveServerPush", x => System.Diagnostics.Debug.WriteLine(x));
hubConnection.Start().Wait();
}
public class DependencyRegistry : Registry
{
public DependencyRegistry()
{
Scan(x =>
{
x.AssembliesFromApplicationBaseDirectory();
x.ExcludeNamespace("StructureMap");
x.WithDefaultConventions();
});
}
}
}
What I'm confused about, is how am I supposed to reference the hubConnection and hubProxy in a message handler? I seems like I'm jerry rigging NServicebus.
public class TestHandler : IHandleMessages<AMS.Infrastructure.Events.IEvent>
{
public void Handle(AMS.Infrastructure.Events.IEvent message)
{
EndpointConfig.hubProxy.Invoke("ServerFunction", "yodle");
}
}
PS: the reason I need the connection and proxy to be global is because spawning up a new hubConnection is expensive according to the signalr people. They highly discourage creating and destroying hubconnections over and over again. They found that making the hubconnection global/static(?) ok though.
In this case, your Hub Connection/Proxy really are unrelated to the EndPointConfiguration class. They don't use nor require any data from this type in order to function.
I would recommend placing them in their own lazy initialized singleton, and start them automatically upon first access. This would look like:
public class Hub
{
private static Lazy<Hub> instance = new Lazy<Hub>(() => new Hub());
public static Hub Instance { get { return instance.Value; } }
private Hub()
{
this.Connection = new HubConnection("http://localhost:58120");
this.Proxy = Connection.CreateHubProxy("AmsHub");
this.Proxy.On<string>("receiveServerPush", x => System.Diagnostics.Debug.WriteLine(x));
this.Connection.Start().Wait();
}
public HubConnection Connection { get; private set; }
public IHubProxy Proxy { get; private set; }
}
Your consumers then just use:
public class TestHandler : IHandleMessages<AMS.Infrastructure.Events.IEvent>
{
public void Handle(AMS.Infrastructure.Events.IEvent message)
{
Hub.Instance.Proxy.Invoke("ServerFunction", "yodle");
}
}
This has the benefit of not creating and starting until first use, and isolates this type into it's own class.
Given that you're also handling the subscription internally, you also could, optionally, encapsulate your methods to simplify usage:
public class Hub
{
private static Lazy<Hub> instance = new Lazy<Hub>(() => new Hub());
public static Hub Instance { get { return instance.Value; } }
private Hub()
{
this.Connection = new HubConnection("http://localhost:58120");
this.Proxy = Connection.CreateHubProxy("AmsHub");
this.Proxy.On<string>("receiveServerPush", x => System.Diagnostics.Debug.WriteLine(x));
this.Connection.Start().Wait();
}
private HubConnection Connection { get; set; }
private IHubProxy Proxy { get; set; }
public static Task Invoke(string method, params Object[] args)
{
return Instance.Proxy.Invoke(method, args);
}
public static Task<T> Invoke<T>(string method, params Object[] args)
{
return Instance.Proxy.Invoke<T>(method, args);
}
}
With the above, you could just use: Hub.Invoke("ServerFunction", "yodle");
#reed-copsey Old post, but thanks for your reply, it helped me a lot.
In my case I am creating an Azure Function, which will connect to an SignalR Hub which is part of an ASP.NET MVC site. I needed the connection to be secure / authenticated before sending a notification.
So my example included authenticating and getting a cookie.
public class Hub
{
private static readonly string HOMEPAGE = ConfigurationManager.AppSettings["Homepage"];
private static readonly string NOTIFICATION_USER = ConfigurationManager.AppSettings["NotificationUser"];
private static readonly string NOTIFICATION_PASSWORD = ConfigurationManager.AppSettings["NotificationPassword"];
private static Lazy<Hub> instance = new Lazy<Hub>(() => new Hub());
public static Hub Instance { get { return instance.Value; } }
private Hub()
{
ClientHandler = new HttpClientHandler();
ClientHandler.CookieContainer = new CookieContainer();
using (Client = new HttpClient(ClientHandler))
{
var content = string.Format("Email={0}&Password={1}", NOTIFICATION_USER, NOTIFICATION_PASSWORD);
var response = this.Client.PostAsync(HOMEPAGE + "/Account/Login", new StringContent(content, Encoding.UTF8, "application/x-www-form-urlencoded")).Result;
}
Connection = new HubConnection($"{HOMEPAGE}/");
Connection.CookieContainer = ClientHandler.CookieContainer;
Proxy = Connection.CreateHubProxy("notificationsHub");
//this.Proxy.On<string>("receiveServerPush", x => System.Diagnostics.Debug.WriteLine(x));
Connection.Start().Wait();
}
public HttpClientHandler ClientHandler { get; private set; }
public HttpClient Client { get; private set; }
public HubConnection Connection { get; private set; }
public IHubProxy Proxy { get; private set; }
public static Task Invoke(string method, params Object[] args)
{
return Instance.Proxy.Invoke(method, args);
}
public static Task<T> Invoke<T>(string method, params Object[] args)
{
return Instance.Proxy.Invoke<T>(method, args);
}
}