Signalr not recognizing updates to SQL database. - asp.net

I'm using Signalr for a realtime notifications for when you get a new message or friend request, and when you view them it changes a "HasBeenViewed" field to true in the database.
The problem is that when Signalr checks for new notifications it doesn't see the changed "HasBeenViewed" field, it thinks it is still false. In the database itself i can confirm that HasBeenViewed has been changed correctly.
The query in Signalr does correctly recognize if a new message/friend request has been added, or if one has been removed. It just doesn't see the updated value for HasBeenViewed.
If I restart IIS then it Signalr finally does see the updated HasBeenViewed value and displays the notifications correctly. However, if a new notification gets sent and viewed, then it is back to not recognizing the viewed status on the new notifications.
Here is my code for the notification check. Using ASP.NET Core. I'm querying from a repository to an MS SQL database.
public void NotificationCheck(string userName)
{
var user = _repo.Query<ApplicationUser>().Where(u => u.UserName == userName).Include(u => u.FreindRequests).Include(u => u.Messages).FirstOrDefault();
var messageCount = user.Messages.Where(m => m.HasBeenViewed == false).Count();
var friendRequests = user.FreindRequests.Where(f => f.HasBeenViewed == false).Count();
Clients.Caller.notificationCount(friendRequests + messageCount);
}
I'm not sure what the problem is. I'm guessing there is some interaction between the query and signalr hub where it is storing it in memory instead of getting the new information every time, but i'm not sure what to do to fix it.
Thanks for any help

Without using SQLDependency triggers, your best option is the manage the message state in the client, and just use the sql database for long term persistence, that way you can get the status of messages when the user logs in, and you have immediate access to state in the client.

Related

signalR: how to send a message to the user once, not to the number of ConnectionId

In the signalr, for each tag that opens, the ConnectionId registers for the user.
I use the following code to send messages to users.
1
2
hubContext.Clients.Clients (user.ConnectionIds.ToLi st ()); receiveNotification (message, userID, link);
The problem I have is that I want to send a message to the user once, not to the number of ConnectionId.
How can I find one of its active ConnectionIds and just send that message?
Is there a better way?
I also worked on this link
https://stackoverflow.com/questions/...ovider-new-2-0
But because of
I do not use request.User.Identity.Name, this method does not work. I'm using my user id. I'm reading the table.
value of request.User.Identity.Name in my app is empty because i'm reading user information from table in database
Thanks for your advice
You can retain connection and user information in a Map that is stored in memory.
private readonly Dictionary<T, HashSet<string>> _connections =
new Dictionary<T, HashSet<string>>();
You can find the fulle example here :
https://learn.microsoft.com/en-us/aspnet/signalr/overview/guide-to-the-api/mapping-users-to-connections

Why alive subscriber get only last published message

M2mqtt incorporate in my asp.net mvc project. Face problem to synch subscribe informations.
When more than one clients published on one specific topic, client can subscribe them easily.
suppose in one situation when published happen then client is down/offline when he alive then only get the last published message not all published messages.
What to do?Is it a problem on MQTT?How alive client get all published messages.
M2mqtt connection with broker use by bellow syntax
public static MqttClient SmartHomeMQTT { get; set; }
SmartHomeMQTT = new MqttClient(brokerAddress, MqttSettings.MQTT_BROKER_DEFAULT_SSL_PORT, true, new X509Certificate(Resource.ca), null, MqttSslProtocols.TLSv1_2, client_RemoteCertificateValidationCallback);
SmartHomeMQTT.Connect("6ea592c5-4b2f-481a-bb0a-eccbe8579d14", "####", "####", false, 3600);
**Note:**Connect method parameter four set to false for clean_session property but it's not work.
To ensure that subscribers receive all messages, even ones that are published when they are offline (known as message persistence), you need to do a few things:
Make sure that 'Clean Session' is turned off in the subscribers
Ensure that each subscriber is using a unique Client ID
Use a QoS of 1 or 2
You don't say which MQTT server you are using, but you need to ensure that the server implementation supports it too.

Meteor updating client whenever a server variable changes

Is it possible to update a Client template whenever a Server variable changes in a Meteor app?
Based on Meteor docs and searching the web, the only way discussed several times to get the Client side updated whenever Server variable changes is by using a Collection then insert a new document whenever the Server variable change, then through Publish/ Subscribe the client side can get notified, but I was wondering if it there is any other way I can get the Client notified whenever the Server variable changes without the need to use the collections approach. Thanks for your time
even that you have already written about collection to share data between client and server, I suppose, that you do not like the "default" consequence to have a mongodb collection for that.
That is not necessary at all. Lets say, you have a server side state object:
ServerStates = {
version: "1.0",
date: "2015-07-07"
}
This should be send out to all clients (broadcast) who are subscribed
server.js
Meteor.publish("server_states", function() {
// we setup the collection to client just return just on record
this.insert("server_states", "ServerStates", ServerStates);
// signal ready
this.ready();
});
On Client you can use now a minimongo collection to get those information
client.js
ServerStates = new Meteor.Collection("server_states");
Meteor.subscribe("server_states")
If you change a value somewhere on server, you can use my answer from meteor - get all subscriber session handles for a publisher method to publish to all active subscribers.
// publish updated values to all subscribers
function publish_server_state_to_all() {
_.each(Meteor.server.stream_server.open_sockets, function(connection) {
_.each(connection._meteorSession._namedSubs, function(sub) {
if (sub._name == "server_state") {
sub.changed("server_state", "ServerState", ServerState);
}
})
});
}
So if you change a value from ServerState on server side you can do and inform by
ServerState.version = "1.1"
publish_server_state_to_all()
Hope that fits your thoughts
Tom

How can I create a method for retrieving user email address that is available on the client and server?

I've got facebook, google and regular registration/login turned on on my website. The problem I have is that the email address is stored in different fields depending on how the user first joined.
For regular users, it is in field emails[0].address. For facebook and google authenticated users it is in field services[0].email.
At various places in the client (templates, events) and on the server (method), I just want to call one method that works out which field to use and returns the email address. I also want to do something similar for the verification field.
I'm fairly new to meteor and the only ways I've found to do the above so far is to repeat the same logic in the client and on the server which doesn't sit well with me.
The best thing to do would be to transfer the email address to 'emails' if they log in with facebook, google or another services for the first time. This would also make it more future proof incase you add other services, since meteor will always use emails.address (including in other packages)
Server side code:
Accounts.onCreateUser(function(user) {
user.emails = user.emails || []; //If its null set it to an empty array
if(user.services.facebook) {
user.emails.push({address: user.services.facebook.email, verified: false});
}else if(user.services.google) {
user.emails.push({address: user.services.google.email, verified: false});
}
return user;
});
Then you can just check Meteor.user().emails[0].address every time.
Note: If not published due to the autopublish package you may have to publish the emails field for it to work on the client.
You may also have to run this the first time for users who have already logged in before:
Meteor.startup(function() {
Meteor.users({'emails':{$exists: false}}).fetch().forEach(function(user) {
var email = (user.services.facebook || user.services.google).email;
if(email) Meteor.users.update({_id: user._id},{$push:{emails:{address: email, verified: false}}});
});
});
I'm not sure if facebook and google both use email in the services key, if they do the above should work fine. If they don't you can edit out the key that is used for google or facebook, in case one is emailAddress instead of email for example.

The Access Token is Valid but We get OAuthException: An active access token error

We've been working on an application for about 2 months, and everything was going perfectly.
we were using PHP SDK and offline mode in permissions for login
But since some days ago after recent changes in Facebook api and removing offline mode we started facing the problem of "Uncaught OAuthException: An active access token must be used to query information about the current user."
The main problem is that it does happen after a while working in our app (about 10 mins) but at the same time when we check the validity of the token via this link
we see that the token is still valid on the other hand the cookie does still exist and it doesn't expire but we get this error :
"Uncaught OAuthException: An active access token must be used to query information about the current user"
I've already visited this link
and I downloaded the latest version but it didn't help could anyone help us please where might be making mistake?
Thanks for responses, I think same as yacon
it seems there's a bug when accessing facebook->api(/me) at the moment we are handling
some parts of the app with javascript which is a real headache to use javascript sdk
and PhP sdk alongside with each other
You can solve this simply store accesstoken to session variable after getLoginUrl
$facebook->getLoginUrl(...)
then whenever you initialize facebook
$facebook = new Facebook(array(
'appId' => Yii::app()->params['facebook_appId'],
'secret' => Yii::app()->params['facebook_appSecret'],
));
get the accesstoken from session and set it using setAccessToken
$facebook->setAccessToken(Yii::app()->session['access_token']);
I handle this situation in this way
1.i get the access token for 1 hour validity
2.extend the token to 60 days validity
3.save that token to session and use it for all project queries.
try{
$facebook_uid = $facebook->getUser();
$facebook->setExtendedAccessToken();
$accessToken = $facebook->getAccessToken();
$fbuser = $facebook->api('/me');
$session['api_me'] = $fbuser;
$session['tokenValue'] = $accessToken;
}catch (Exception $e) {
facebook_uid =null;
}
I think there is a bug in the api. When I use $facebook->api('/'.$facebook_uid) instead of ->api('/me') it works.

Resources