Reputation: 253
Trying to write Hub in my server to broadcast notifications to clients
In my Server: 1 - Installed the nuget. 2 - Created Startup.cs with app.MapSignalR(); 3 - Created hub:
[HubName("NotificationHub")]
public class NotificationHub : Hub
{
// required to let the Hub to be called from other server-side classes/controllers, using static methods
private static IHubContext hubContext = GlobalHost.ConnectionManager.GetHubContext<NotificationHub>();
// Send the data to all clients (may be called from client JS)
public void GetNotifications()
{
Clients.All.GetNotifications();
}
// Send the data to all clients (may be called from server C#)
public static void GetNotificationsStatic()
{
hubContext.Clients.All.GetNotifications();
}
}
4 - Created controller with Get and Add notifications.
In my client: followed this guide: https://medium.com/@ghanshyamshukla/implementation-of-signalr-in-angular-5-app-with-asp-net-web-api-2-0-f09672817d4d (in my angular.json instead of '../node_modules..' I've fixed to './node_modules..'
and this is my connection function:
connectToSignalRHub() {
const signalRServerEndPoint = environment.baseURL;
this.connection = $.hubConnection(signalRServerEndPoint);
this.proxy = this.connection.createHubProxy('notificationHub');
this.proxy.on('messageReceived', () => {
console.log('new notifications');
});
this.connection.start().done((data: any) => {
console.log('Connected to Notification Hub');
}).catch((error: any) => {
console.log('Notification Hub error -> ' + error);
});
}
Then when I run my app,
when trying to connect with this.connection.start()
I get to the error section with error:
Error: Error during negotiation request. at Object.error (jquery.signalR.min.js:9)
and I see in my console this error:
Access to XMLHttpRequest at 'https://localhost:44328/signalr/negotiate?clientProtocol=2.1&connectionData=%5B%7B%22name%22%3A%22notificationhub%22%7D%5D&_=1563949114481' from origin 'http://localhost:8083' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
Needless to say I've enabled CORS for my app
Upvotes: 2
Views: 2157
Reputation: 1479
Took me several head-scratching hours, but I finally got it working with a combination of http and https, together with removing the trailing /
after the port number!
In ConfigureServices method in startup.cs
services.AddCors(options => options.AddPolicy("CorsPolicy", builder =>
{
builder.AllowAnyMethod()
.AllowAnyHeader()
.AllowCredentials()
.WithOrigins("http://localhost:4200");
}
));
services.AddSignalR();
In the Configure method in startup.cs
app.UseCors("CorsPolicy");
app.UseSignalR(routes => routes.MapHub<NotifyHub>("/notify"));
Client js:
const connection = new signalR.HubConnectionBuilder()
.withUrl('https://localhost:44394/notify')
.configureLogging(signalR.LogLevel.Debug)
.build();
connection.start().then(() => {
console.log('Connected!');
}).catch((err) => {
return console.error(err.toString());
});
There may be other combinations that are successful, but it feels like I tried every single one and I’m not ready to keep trying when it’s finally working…
Upvotes: 1
Reputation: 253
So the problem was that I've enabled CORS in my WebApiConfig:
config.EnableCors();
var corsAttr = new EnableCorsAttribute("*", "*", "*");
config.EnableCors(corsAttr);
Thanks to vasily.sib in the comment section, and this link he's refered me to: CORS Article
I've changed my Startup.cs Configuration method to:
app.Map("/signalr", map =>
{
// Setup the CORS middleware to run before SignalR.
// By default this will allow all origins. You can
// configure the set of origins and/or http verbs by
// providing a cors options with a different policy.
map.UseCors(CorsOptions.AllowAll);
var hubConfiguration = new HubConfiguration
{
// You can enable JSONP by uncommenting line below.
// JSONP requests are insecure but some older browsers (and some
// versions of IE) require JSONP to work cross domain
// EnableJSONP = true
};
// Run the SignalR pipeline. We're not using MapSignalR
// since this branch already runs under the "/signalr"
// path.
map.RunSignalR(hubConfiguration);
});
And now it works.
Upvotes: 0
Reputation: 2772
this is working for me:
I use AspNetCore 2.1
(important version) in server side.
in startup.cs:
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
services.AddCors(options => options.AddPolicy("CorsPolicy",
builder =>
{
builder.AllowAnyMethod()
.AllowAnyHeader()
.AllowAnyOrigin()
.AllowCredentials();
}));
services.AddSignalR();
}
The ordering of services
is also important.
Configure method:
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseBrowserLink();
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
}
app.UseCors("CorsPolicy");
app.UseStaticFiles();
app.UseSignalR(route =>
{
route.MapHub<NotificationHub>("/notificationHub"); // name of js file
});
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});
}
enter code here
and in Hub class:
[HubName("NotificationHub")]
public class NotificationHub: Hub
{
public Task SendMessage(string user, string message)
{
return Clients.All.SendAsync("ReceiveMessage", user, message); // ReceiveMessage => name of method in client
}
}
Upvotes: 1