I use signalr in React.Js and have a problem that when I go to the pages by clicking the menu link and redirect with Route, it is not working. The back-end singleton class constructor is not called, but when I refresh a page or type the route manually in the address bar, it is works and connects to the back-end.
import $ from "jquery";
window.jQuery = $;
require("signalr");
{componentDidMount() {
var connection = $.hubConnection("http://localhost:1425/");
proxy = connection.createHubProxy("myHub");
connection
.start({ withCredentials: false })
.done(function () {
console.log("Now connected, connection ID=" + connection.id);
})
.fail(function () {
console.log("Could not connect");
});
}
Why does this happen and can anyone guide me on how should I fix that?
Related
I'm working on chat application with c# as a server and angular as a client. I'm using SignalR for chatting between clients. My app is working well but I'm having trouble with getting a list of all connected users.
I know for sure that the client is reaching the server with http get request (after connecting to SignalR) because I console.log the connected users list and I'm getting the data:
The problem is that when I try to print the items of the list - it's not rendering and the fields are staying empty:
I expect seeing in the list myself (my details) and later on if I'm connecting to the app from Incognito to update the connected users list. But right now as you can see, I don't see my info.
I'm putting only the relevent parts of my code:
user component ts-
export class UsersComponent implements OnInit {
private signalrConnectionUrl='https://localhost:7014/userHub';
private addClientUrl='https://localhost:7014/Contacts/AddChatClient';
private sendMessageToAllUrl='https://localhost:7014/Contacts/SendMessageToAll';
chatClientId= getClientId();
chatMessage: string="";
userName=getUserName();
users: ConnectedClientModel[]=[];
constructor(public signalRService: SignalrService, private userService: UsersService, private http: HttpClient) { }
ngOnInit(): void {
this.startSignalrConnection();
};
startSignalrConnection(): void {
this.signalRService.startSignalrConnection(this.signalrConnectionUrl)
.then((signalrHubConnectionId) => {
firstValueFrom(this.http.post(this.addClientUrl,
buildNewChatClientConnectionModel(this.chatClientId, signalrHubConnectionId, this.userName!)))
.then((response) => {
this.signalRService.addListeners();
//getting all connected users
this.userService.getConnectedUsers().subscribe((users)=>{
this.users=users;
console.log(this.users);
})
console.log("Signalr started successfully with connectionId: " + signalrHubConnectionId + " And ready to get messages");
})
.catch((error) => {
console.log("Error while adding new chat client:", error);
alert("Error while adding new chat client:" + error);
console.log("chatClientId: " + this.chatClientId);
console.log("signalrHubConnectionId: " + signalrHubConnectionId);
});
})
.catch((error) => {
console.log("Error while establishing signalr connection:", error);
alert("Error while establishing signalr connection:" + error);
});
}
user component html (only the user list part)-
<h4 class="mb-3">List of Users</h4>
<div *ngFor="let user of users">
<div class="mb-2 mt-2">
<div><strong>Name</strong>{{user.Name}}</div>
<div><strong>Id</strong>{{user.ChatClientId}}</div>
<hr>
</div>
</div>
user service-
export class UsersService {
private getConnectedUsersUrl='https://localhost:7014/Contacts/GetConnectedUsers';
constructor(private http: HttpClient) { }
getConnectedUsers(): Observable<ConnectedClientModel[]> {
return this.http.get<ConnectedClientModel[]>(this.getConnectedUsersUrl);
}
}
ConnectedClientModel-
import { Guid } from "guid-typescript"
export interface ConnectedClientModel {
ChatClientId: Guid,
ConnectionId: string,
Name: string
}
Server get request-
[HttpGet("GetConnectedUsers")]
public async Task<IActionResult> GetConnectedUsers()
{
var allConnectedUsers = _signalrService.GetAllConnectedUsers();
return Ok(allConnectedUsers.Entity);
}
The properties coming from your backend start with a lowercase letter, yet in your Angular-model their first letter is capitalized. As a consequence the mapping might not be working anymore.
Can you once try to modify your model as follows?:
import { Guid } from "guid-typescript"
export interface ConnectedClientModel {
chatClientId: Guid,
connectionId: string,
name: string
}
And then also adapt the following two lines of your html:
<div><strong>Name</strong>{{user.name}}</div>
<div><strong>Id</strong>{{user.chatClientId}}</div>
I currently have a Message page which displays all the new messages which are sent to the user. These messages are stored in a database along with a NewMessageCount. if the user has one new message a small notification will get displayed next to the Message which is selected from NewMessagecount. I am using SignalR to achieve this and I'm very new to SignalR so do excuse me if I'm making a obvious mistake.
I have two function in the Hub which work fine because they filter and update correct fields. However my question is I can't seem get both of these functions to run one after another on the message page. I want when the user clicks on the message tab the notifications.server.removeNotification(); to run
<script type="text/javascript">
$(function () {
var notifications = $.connection.notificationHub;
notifications.client.recieveNotification = function (totalNewMessages) {
$('#NewMessages').text(totalNewMessages);
};
notifications.client.removeNotification = function (totalNewMessages) {
$('.Message').click(function () {
$('#NewMessages').text(totalNewMessages);
});
};
// Start the connection.
$.connection.hub.start(function () {
notifications.server.sendNotifications();
notifications.server.removeNotification(); //This is what i want to run on the click event?? But don't know how to
}).fail(function (e) {
alert(e);
});
});
</script>
Thanks in advance
With the help of #IlyaLuzyanin comment I manage to solve the issue by adding the click handler inside the hub.start
$.connection.hub.start(function () {
notifications.server.sendNotifications();
$('.removemessage').click(function () {
notifications.server.removeNotifications();
})
});
I'm a serious MVC & SignalR newbie!
I found this tutorial online that shows how to use Database Change notifications and display the data in an MVC app. The issue I'm having is replicating the MVC side of things. I've managed I think to work through the tutorial correctly and spin up the application, however, I'm getting an Undefined connection and the app bombs out.
Does anyone know where I might find the associated source files for this example, or has anyone managed to successfully implement this and can shed some light on the configuration of this from an MVC point of view.
Thanks!
To display real time updates from the SQL Server by using SignalR and SQL Dependency I've done these steps:
Step 1: Enable Service Broker on the database
The following is the query that need to enable the service broker
ALTER DATABASE BlogDemos SET ENABLE_BROKER WITH ROLLBACK IMMEDIATE ;
Step 2: Enable SQL Dependency
//Start SqlDependency with application initialization
SqlDependency.Start(connString);
Step 3: Create the hub Class
public class MessagesHub : Hub
{
private static string conString = ConfigurationManager.ConnectionStrings["DefaultConnection"].ToString();
public void Hello()
{
Clients.All.hello();
}
[HubMethodName("sendMessages")]
public static void SendMessages()
{
IHubContext context = GlobalHost.ConnectionManager.GetHubContext<MessagesHub>();
context.Clients.All.updateMessages();
}
}
Step 4: Get the Data from the Repository
Create MessagesRepository to get the messages from the database when data is updated.
public class MessagesRepository
{
readonly string _connString = ConfigurationManager.ConnectionStrings["DefaultConnection"].ConnectionString;
public IEnumerable<Messages> GetAllMessages()
{
var messages = new List<Messages>();
using (var connection = new SqlConnection(_connString))
{
connection.Open();
using (var command = new SqlCommand(#"SELECT [MessageID], [Message], [EmptyMessage], [Date] FROM [dbo].[Messages]", 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 Messages { MessageID = (int)reader["MessageID"], Message = (string)reader["Message"], EmptyMessage = reader["EmptyMessage"] != DBNull.Value ? (string) reader["EmptyMessage"] : "", MessageDate = Convert.ToDateTime(reader["Date"]) });
}
}
}
return messages;
}
private void dependency_OnChange(object sender, SqlNotificationEventArgs e)
{
if (e.Type == SqlNotificationType.Change)
{
MessagesHub.SendMessages();
}
}
}
Step 5: Register SignalR at startup class
app.MapSignalR();
Step 6: then use the method to show real time at your view
<script src="/Scripts/jquery.signalR-2.1.1.js"></script>
<!--Reference the autogenerated SignalR hub script. -->
<script src="/signalr/hubs"></script>
<script type="text/javascript">
$(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 () {
alert("connection started")
getAllMessages();
}).fail(function (e) {
alert(e);
});
});
function getAllMessages()
{
var tbl = $('#messagesTable');
$.ajax({
url: '/home/GetMessages',
contentType: 'application/html ; charset:utf-8',
type: 'GET',
dataType: 'html'
}).success(function (result) {
tbl.empty().append(result);
}).error(function () {
});
}
</script>
Hope this helps :)
You should provide your code, it's easier to figure out what the problem is that way.
From what you have mentioned, I can think of only two things.
1) The tutorial you used, it's using SignalR 1.0. If you are using SignalR 2.0, you should not follow the tutorial exactly.
A few things changed in SignalR 2.0, you can read about it using below link:
http://www.asp.net/signalr/overview/signalr-20/getting-started-with-signalr-20/upgrading-signalr-1x-projects-to-20
2) If you are using SignalR 1.0, make sure you include the "jquery" file correctly, and if it's correct, try to change the hub proxy path like below:
<script src="/signalr/Hubs"></script>
Hope it helps
I have two SignalR hubs in my MVC app, ChatHub and AnotherHub. ChatHub is working nicely, but I can't connect to the other one. I know that SignalR recognises that AnotherHub exists, because I'm getting the following JavaScript in /signalr/hubs:
signalR.chatHub = {
_: {
hubName: 'ChatHub',
ignoreMembers: ['post'],
connection: function () { return signalR.hub; }
},
post: function (room, message) {
return invoke(this, "Post", $.makeArray(arguments));
}
};
signalR.anotherHub = {
_: {
hubName: 'AnotherHub',
ignoreMembers: ['doSomething'],
connection: function () { return signalR.hub; }
},
doSomething: function (thing) {
return invoke(this, "DoSomething", $.makeArray(arguments));
}
};
On the chat page, Fiddler tells me the following when connecting with /signalr/signalr/connect:
connectionData [{"name":"chathub"}]
tid 10
However, when trying to connect to anotherHub, Fiddler says:
connectionData []
tid 3
My javascript on the chat page:
cn = $.connection.chatHub;
$.connection.hub.start();
and on the another page:
cn = $.connection.anotherHub;
$.connection.hub.start();
Now, a curious thing; when I change anotherHub to chatHub on the another page, the connection works. When I change chatHub to anotherHub on the chat page, that also works. The only combination that doesn't is anotherHub on the another page. (I've confirmed this by server-side breakpoints on the hubs' constructors and checking fiddler for the ConnectionData parameter). Any ideas?
Are you sure you have referenced all of the same JS libraries (especially /signalr/hubs) on the another page?
I am using the following code in my facebook application. The when loading the application in facebook has no problem in chrome/firefox/ie8. When it runs in IE9 it is reporting that OAuthException has been thrown.
public string GetFacebookId() {
if (!FacebookWebContext.Current.IsAuthorized())
return string.Empty;
var client = new FacebookWebClient();
dynamic me = client.Get("me");
return me.id;
}
(OAuthException) An active access token must be used to query
information about the current user.
any suggestions would be appreciated.
thanks.
EDIT:
window.fbAsyncInit = function () {
FB.init({
appId: '#(Facebook.FacebookApplication.Current.AppId)', // App ID
//channelURL: '//facebook.thefarmdigital.com.au/moccona/premium/FacebookChannel/', // Channel File
status: true, // check login status
cookie: true, // enable cookies to allow the server to access the session
oauth: true, // enable OAuth 2.0
xfbml: true // parse XFBML
});
FB.Canvas.setAutoGrow();
};
$(function () {
$('#custom_login').click(function () {
FB.getLoginStatus(function (response) {
if (response.authResponse) {
//should never get here as controller will pass to logged in page
} else {
FB.login(function (response) {
if (response.authResponse) {
window.location = '#(Request.Url.AbsoluteUri.Replace(Request.Url.PathAndQuery, ""))' + $('#custom_login').attr('href');
} else {
window.location = '#(Request.Url.AbsoluteUri.Replace(Request.Url.PathAndQuery, ""))' + $('#custom_login').attr('dataFail');
}
}, { scope: 'publish_stream' });
}
});
return false;
});
});
I'm not familiar with FB's C# SDK, but judging from the code you gave, it does not seem that you are doing any user authentication with FB. It might be that it works in Chrome and Firefox only because you are somehow already logged into your FB app in those browsers.