I have created a simple SignalR hub inside a console application:
class Program
{
static void Main(string[] args)
{
using (WebApp.Start<Startup>("http://localhost:1968"))
{
Console.WriteLine("Server running!");
Console.ReadLine();
}
}
}
public static class UserHandler
{
public static HashSet<string> ConnectedIds = new HashSet<string>();
}
[HubName("echo")]
public class EchoHub : Hub
{
public void Say(string message)
{
Trace.WriteLine("hub: "+message);
Clients.All.AddMessage(message);
}
public override Task OnConnected()
{
UserHandler.ConnectedIds.Add(Context.ConnectionId);
return base.OnConnected();
}
public override Task OnDisconnected()
{
UserHandler.ConnectedIds.Remove(Context.ConnectionId);
return base.OnDisconnected();
}
}
class Startup
{
public void Configuration(IAppBuilder app)
{
app.MapSignalR();
}
}
When I try to connect this from a Silverlight App, it succeeds:
static Microsoft.AspNet.SignalR.Client.HubConnection signalR { get; set; }
public static Microsoft.AspNet.SignalR.Client.IHubProxy signalRhub { get; set; }
public static void StartSignalR()
{
var url = "http://localhost:1968";
signalR = new Microsoft.AspNet.SignalR.Client.HubConnection(url);
signalR.Received += signalR_Received;
signalRhub = signalR.CreateHubProxy("echo");
signalR.Start().Wait();
signalRhub.Invoke("Say", "hub invoked");
}
My next step is to connect the SignalR hub from jquery:
<script src="../Scripts/jquery-1.6.4.js"></script>
<script src="../Scripts/jquery.signalR-2.1.0.js"></script>
<script>
$(function ()
{
var connection = $.hubConnection("http://localhost:1968");
connection.start()
.done(function () {
console.log('connected');
connection.send("success?");
})
.fail(function (a) {
console.log('not connected'+a);
});
});
</script>
When I try to run this script, it gives the error:
"XMLHttpRequest cannot load localhost:1968/signalr/negotiate?clientProtocol=1.4&_=1404978593482. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin <code>http://localhost:55282</code> is therefore not allowed access."
Why can I connect to the hub from my Silverlight page (hosted in localhost:3926)
and fails it when I run the jquery script (hosted in localhost:55282)?
What can I do to get a working connection between my jQuery and SignalR hub?
Change
$(function ()
{
var connection = $.hubConnection("http://localhost:1968");
connection.start()
.done(function () {
console.log('connected');
connection.send("success?");
})
.fail(function (a) {
console.log('not connected'+a);
});
});
to
$(function ()
{
var connection = $.hubConnection("http://localhost:1968");
var hub = connection.createHubProxy("echo");
hub.on("AddMessage", Method);
connection.start({ jsonp: true })
.done(function () {
console.log('connected');
hub.say("success?");
})
.fail(function (a) {
console.log('not connected'+a);
});
});
function Method(messageFromHub)
{
alert(messageFromHub);
}
and
class Startup
{
public void Configuration(IAppBuilder app)
{
app.MapSignalR();
}
}
to
class Startup
{
public void Configuration(IAppBuilder app)
{
app.MapSignalR(new HubConfiguration() { EnableJSONP = true });}
}
It should do.
app.MapSignalR(new HubConfiguration() { EnableJSONP = true });}
and
connection.start({ jsonp: true })
Will allow cross site request
RPC on Server in SignalR with createHubProxy():
Thanks to the answer from Vishal Ravlani
But for me
hub.say("success?");
doesn't work! (Does it work for you?)
I have to write:
hub.invoke('say','success?');
And SignalR has automatically detected CrossOrigin on Client.
On Server I have used:
app.Map("/signalr", map =>
{
map.UseCors(CorsOptions.AllowAll);
map.RunSignalR();
});
which was described on: http://www.asp.net/signalr/overview/signalr-20/hubs-api/hubs-api-guide-javascript-client#crossdomain
Related
I have developed an application in ASP .NET MVC using SignalR Everything is perfect the only issue I am facing is when I perform CRUD some of the clients are updated using SignalR and some of them are not updated.
Please help me to figure out this issue
public class Startup
{
public void Configuration(IAppBuilder app)
{
app.UseCors(CorsOptions.AllowAll);
app.MapSignalR();
}
}
public class SettingHub : Hub
{
public static void BroadcastData()
{
IHubContext context = GlobalHost.ConnectionManager.GetHubContext<SettingHub>();
context.Clients.All.updatedData();
}
}
$(function () {
var notificationFromHub = $.connection.settingHub;
$.connection.hub.start().done(function () {
FetchSettings();
});
notificationFromHub.client.updatedData = function () {
FetchSettings();
};
});
I just shuffle the code and it works
public class Startup
{
public void Configuration(IAppBuilder app)
{
app.UseCors(CorsOptions.AllowAll);
app.MapSignalR();
}
}
public class SettingHub : Hub
{
public static void BroadcastData()
{
IHubContext context = GlobalHost.ConnectionManager.GetHubContext<SettingHub>();
context.Clients.All.updatedData();
}
}
$(function () {
var notificationFromHub = $.connection.settingHub;
notificationFromHub.client.updatedData = function () {
FetchSettings();
};
});
$.connection.hub.start().done(function () {
FetchSettings();
});
I'm creating an ASP.NET Core Application running on 4.7 with an Angular front-end. As I need to notify the users about status changes I'm trying to add SignalR. I'm using following versions:
AspNetCore 2.0.1
Angular 5.x
SignalR 1.0.0-alpha2-final
Below you can see my code. If I run this app I can see in the logs that both hub connections get started. If I open a second browser tab with the same URL, only one connection is successful. For the second hub I always get this error:
Error: Not Found
at XMLHttpRequest.xhr.onload [as __zone_symbol__ON_PROPERTYload] (http://localhost:51616/dist/estructuring_main.js?v=fBx34vrzWnqBIPjAm71NaWQz0TEeQZWcx2ixKnjADWI:36168:28)
at XMLHttpRequest.wrapFn (http://localhost:51616/dist/vendor.js?v=rp1X6LsN5SJnsTJrd-749xunuUaKAA_WINwoqzbaeqE:120085:39)
at ZoneDelegate.invokeTask (http://localhost:51616/dist/vendor.js?v=rp1X6LsN5SJnsTJrd-749xunuUaKAA_WINwoqzbaeqE:119340:31)
at Object.onInvokeTask (http://localhost:51616/dist/vendor.js?v=rp1X6LsN5SJnsTJrd-749xunuUaKAA_WINwoqzbaeqE:5013:33)
at ZoneDelegate.invokeTask (http://localhost:51616/dist/vendor.js?v=rp1X6LsN5SJnsTJrd-749xunuUaKAA_WINwoqzbaeqE:119339:36)
at Zone.runTask (http://localhost:51616/dist/vendor.js?v=rp1X6LsN5SJnsTJrd-749xunuUaKAA_WINwoqzbaeqE:119107:47)
at ZoneTask.invokeTask [as invoke] (http://localhost:51616/dist/vendor.js?v=rp1X6LsN5SJnsTJrd-749xunuUaKAA_WINwoqzbaeqE:119415:34)
at invokeTask (http://localhost:51616/dist/vendor.js?v=rp1X6LsN5SJnsTJrd-749xunuUaKAA_WINwoqzbaeqE:120436:14)
at XMLHttpRequest.globalZoneAwareCallback (http://localhost:51616/dist/vendor.js?v=rp1X6LsN5SJnsTJrd-749xunuUaKAA_WINwoqzbaeqE:120462:17)
The error says 404 not found even though I can see the request in my request-middleware.
What do I need to change that the hub connections also work with multiple tabs?
Startup.cs
public IServiceProvider ConfigureServices(IServiceCollection services)
{
services.AddSignalR();
services.AddSingleton(typeof(IUserTracker<>), typeof(InMemoryUserTracker<>));
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory, IApplicationLifetime appLifetime)
{
app.UseSignalR(routes =>
{
routes.MapHub<StatusHub>("status", (options) =>
{
options.Transports = TransportType.LongPolling;
});
routes.MapHub<AutopricerHub>("autopricer", (options) =>
{
options.Transports = TransportType.LongPolling;
});
});
}
InMemoryUserTracker.cs
public class InMemoryUserTracker<THub> : IUserTracker<THub>
{
private readonly ConcurrentDictionary<HubConnectionContext, UserDetails> usersOnline
= new ConcurrentDictionary<HubConnectionContext, UserDetails>();
public IEnumerable<UserDetails> UsersOnline()
=> usersOnline.Values.AsEnumerable();
public Task AddUser(HubConnectionContext connection, UserDetails userDetails)
{
usersOnline.TryAdd(connection, userDetails);
return Task.CompletedTask;
}
public Task RemoveUser(HubConnectionContext connection)
{
usersOnline.TryRemove(connection, out var userDetails);
return Task.CompletedTask;
}
}
BaseHubWithPresence.cs
public abstract class BaseHubWithPresence : Hub
{
protected readonly IUserTracker<BaseHubWithPresence> userTracker;
protected BaseHubWithPresence(IUserTracker<BaseHubWithPresence> userTracker)
{
this.userTracker = userTracker;
}
public virtual async Task Join(long userId)
{
await userTracker.AddUser(Context.Connection, new UserDetails(Context.ConnectionId, userId));
await Task.CompletedTask;
}
public virtual async Task Leave()
{
await userTracker.RemoveUser(Context.Connection);
await Task.CompletedTask;
}
}
AutopricerHub.cs
public class AutopricerHub : BaseHubWithPresence
{
public AutopricerHub(IUserTracker<AutopricerHub> userTracker)
: base(userTracker) {}
public async Task SendToAll()
{
await Clients.All.InvokeAsync("All", "data");
}
public async Task SendUpdateAsync(long userId)
{
foreach (var user in userTracker.UsersOnline().Where(o => o.UserId == userId))
{
await Clients.Client(user.ConnectionId).InvokeAsync("Update", "data");
}
}
}
StatusHub.cs
public class StatusHub : BaseHubWithPresence
{
public StatusHub(IUserTracker<BaseHubWithPresence> userTracker)
: base(userTracker)
{
}
public async Task SendSingleAsync(long listener)
{
foreach (var user in userTracker.UsersOnline().Where(o => o.UserId == listener))
{
await Clients.Client(user.ConnectionId).InvokeAsync("Update", "data");
}
}
public async Task SendMultipleAsync(IReadOnlyCollection<long> listeners)
{
foreach (var listener in listeners)
{
foreach (var user in userTracker.UsersOnline().Where(o => o.UserId == listener))
{
await Clients.Client(user.ConnectionId).InvokeAsync("Update", "data");
}
}
}
}
price-notification.service.ts
#Injectable()
export class PriceNotificationService {
private hubConnection: HubConnection;
private destroy$ = new Subject<boolean>();
constructor(
private appContextService: AppContextService,
private messageService: MessageService) {
this.init();
}
private init(): void {
this.hubConnection = new HubConnection('/autopricer', { transport: TransportType.LongPolling });
this.hubConnection.start()
.then(() => {
this.appContextService.getAppContext().takeUntil(this.destroy$).subscribe(appContext => {
this.hubConnection.invoke('join', appContext.FirmuserId);
});
DEBUG.init && debug('Price Notification Hub connection started');
})
.catch(err => {
DEBUG.init && debug('Error while establishing Price Notification Hub connection');
});
this.hubConnection.onclose = e => {
DEBUG.functionCalls && debug('On close Price Notification Hub connection');
this.hubConnection.invoke('leave');
};
this.hubConnection.off('leave', null);
}
private showUpdateNotification(data: string) {
}
private showAllNotification(data: string) {
}
}
status-notification.service.ts
#Injectable()
export class StatusNotificationService {
private hubConnection: HubConnection;
private destroy$ = new Subject<boolean>();
constructor(
private appContextService: AppContextService,
private messageService: MessageService) {
this.init();
}
private init(): void {
this.hubConnection = new HubConnection('/status', { transport: TransportType.LongPolling });
this.hubConnection.start()
.then(() => {
this.appContextService.getAppContext().takeUntil(this.destroy$).subscribe(appContext => {
this.hubConnection.invoke('join', appContext.FirmuserId);
});
DEBUG.init && debug('Status Notification Hub connection started');
})
.catch(err => {
DEBUG.init && debug('Error while establishing Status Notification Hub connection');
});
this.hubConnection.onclose = e => {
DEBUG.functionCalls && debug('On close Status Notification Hub connection');
this.hubConnection.invoke('leave');
};
this.hubConnection.off('leave', null);
}
private showUpdateNotification(data: string) {
}
}
The service provider for each of these Angular service is in a separate component.
Browser network tab:
I'm trying to use SignalR 1.0.0 alpha2 in my Angular 4 & .NET Core 2.0 application, based on this article. Here is my CommentsComponent:
import { Component, OnInit } from '#angular/core';
import { AuthService } from "angular4-social-login";
import { SocialUser } from "angular4-social-login";
import { AuthenticationService } from "../services/auth/auth.service";
import { Http } from '#angular/http';
import { UserComment } from './UserComment';
import { HubConnection } from '#aspnet/signalr-client';
import { User } from "../login/User";
#Component({
selector: 'app-comments',
templateUrl: './comments.component.html',
styleUrls: ['./comments.component.css']
})
export class CommentsComponent implements OnInit {
private loggedUserName: string = "";
private _hubConnection: HubConnection;
public async: any;
private commentTitle: string;
private commentText: string;
private commentAutor: string;
messages: string[] = [];
private Comments: Array<UserComment> = new Array<UserComment>();
constructor(private authService: AuthenticationService,
private httpService: Http) {
this.checkUser();
this.authService.getLoggedInName.subscribe(name => this.changeName(name));
}
private changeName(name: string): void {
this.loggedUserName = name;
}
ngOnInit() {
this._hubConnection = new HubConnection('http://localhost:4200/commentsPublisher');
this._hubConnection.on('Send', (data: any) => {
const received = `Received: ${data}`;
this.messages.push(received);
});
this._hubConnection.start()
.then(() => {
console.log('Hub connection started')
})
.catch(err => {
console.log('Error while establishing connection')
});
}
But every time when i try to open connection on my client side i'm getting the error: Error: Failed to start the connection. SyntaxError: Unexpected token G in JSON at position 0
Of course, my Startup.cs file was configured, and class derived from HUB was created.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
app.UseSignalR(routes =>
{
routes.MapHub<CommentsPublisher>("commentsPublisher");
});
app.UseCors("AllowAny");
//another stuff
}
And my comments publisher:
public class CommentsPublisher : Hub
{
public Task PublishReport(string data)
{
return Clients.All.InvokeAsync("OnCommentsPublisher", data);
}
}
So, any ideas ?
UPDATE: I'm fixed my problem with updating packages to version 4.4.6 and refusing the Identity Authentication.
I want to access session value on my hub class
My jquery code is as below
var con = $.connection.MyHub;
$.connection.hub.start().done(function () {
con.server.send().done(function (data) {
displayservices(data);
})
})
con.client.addmessege = function (data) {
displayservices(data);
//alertSound();
};
My hub class is as bellow
public Class MyHub : Hub
{
public void send(string msg)
{
client.all.addmessage(msg)
}
}
How can I access session value in my hub class
You can get the current session from HttpContext, like this:
var sessionVar = HttpContext.Current.Session["SessionVar"];
I make an asp.net Messenger WebProject using XSockes.
When run this project onopen and onconnected events its happens.
but wen send message does not work.
what is my fault?
Startup Code:
[assembly: OwinStartupAttribute(typeof(XsocketTest1.Startup))]
public class Startup
{
public void Configuration(IAppBuilder app)
{
app.UseXSockets(true);
}
}
Starter Code:
[assembly: PreApplicationStartMethod(typeof(XsocketTest1.Starter), "Start")]
namespace XsocketTest1
{
public class Starter
{
private static IXSocketServerContainer container;
public static void Start()
{
container = XSockets.Plugin.Framework.Composable.GetExport<IXSocketServerContainer>();
container.Start();
}
}
}
Controller Code:
public class Chat : XSocketController
{
public string UserName { get; set; }
public void ChatMessage(string message)
{
this.InvokeToAll(message, "chatmessage");
}
}
And JavaScript Code:
$(function () {
try{
var controler = new XSockets.WebSocket('ws://localhost:34853', ['chat']);
var conn = controler.controller('chat');
conn.onopen = function () {
}
conn.onconnected = function () {
console.log('socket connected');
conn.controller('chat').chatmessage = function (data) {
console.log(data.Text);
};
};
}
catch(e)
{
alert(e);
}
$(document).ready(function () {
$("#btnSend").click(function () {
try{
conn.invoke('chatmessage', {
Text: 'Calling chatmessage on server and passing a part of the complex object'
});
}
catch(e)
{ alert(e);}
});
});
});
The code looks pretty weird...
Take a look here: http://xsockets.net/docs/4/installing-xsocketsnet
And you will see that you have duplicate startup classes... All you need is the "usexsockets" part if you use owin and win8+ (also mentioned in the docs).
Your JavaScript might work but is very confusing since it seems like you have misunderstood the difference between a connection and a controller in xsockets.