SignalR 0.5.2 - Context.User is null on disconnect - asp.net-mvc-3

I recently updated to SignalR 0.5.2 from 0.4.0 in my ASP.NET MVC3 application. In SignalR 0.5.2 the "User" property on the Context instance is null when the user disconnects - is this by design?
As seen from the "Immediate Window" snapshot below, all I know about the Context when a client disconnects is the disconnecting client's ConnectionId.
Context
{SignalR.Hubs.HubCallerContext}
ConnectionId: "... some connection id ..."
Headers: null
QueryString: null
RequestCookies: null
ServerVariables: null
User: null
Simplified, my SignalR Hub implementation looks like this:
public class MyHub : Hub, IDisconnect, IConnected
{
// some other code
public Task Disconnect()
{
var user = Context.User; // <-- This is null
// more code
}
}
To sum up - am I forgetting something here or is it by design that Context.User is null? And if so - why? :)

I found the answer in the SignalR wiki. In its section about hubs ( https://github.com/SignalR/SignalR/wiki/Hubs ) it states:
Whenever a client disconnects, the Disconnect method will be invoked on all hubs that implement IDisconnect. When this method is called you can use Context.ConnectionId to access the client that disconnected.
NOTE: This method is called from the server, that means state on the Caller object, any state that was with the connection, as well as the HubContext's User and Cookies will not be populated.

Related

How to disconnect a Stomp client Session from Spring

I know how to disconnect Sessions from Client Side, but I couldn't find a way to disconnect my session from my Spring Boot Backend. I've already seen the following post:
Disconnect client session from Spring websocket stomp server
This would kinda adress my problem, but I thought maybe there is a much more elegant or easier way to solve my problem, since the above mentioned post is already 8 years old. And still i couldn't get it to work as expected.
Trying to sketch my exact problem:
JS-Client-Side looks like this(pseudo code):
![creates a simple request and sends it to my Spring Backend]
function subscribeToUser(){
request = {};
request.type = "USER";
var user = {};
user.userId = userId;
user.email = email;
request.user = user;
send(request);
}
Server-Side:
Here I detect a Subscribe Event, extract the destination, and check if it is valid. If there is some problem
with the destination I want my server to disconnect from that client.(This should happen in line 122)
#EventListener
private void handleSessionSubscribe(SessionSubscribeEvent event){
String destination =
event.getMessage().getHeaders().get("simpDestination").toString();
Principal p = canSubscribeToThatEndpoint(destination,
event.getUser());
}
private Principal canSubscribeToThatEndpoint(String dest, Principal
user){
if(dest.containt("some invalid thing")){
//close the session from server-side
}else return user;
}
I already tried to follow the mentioned StackOverflow Post but I couldn't get it to run. Also another method would be to send a message from the backend and trigger a disconnect Event in JS. But I think it would be convient(if there is a way) to access current client sessions in Backend and disconnect from them if needed.

Internal Server Error (500) when creating a document in DocumentDB from data passed on from Console Application to ASP.NET WebAPI

I have an ASP.NET WebAPI Controller which creates a document in Azure DocumentDB from the data passed on to its POST method from a Console app. The return type of the POST method is HttpResponseMessage which returns a status code for OK (i.e. 200) when the document has been successfully created.
The document gets created successfully from the WebAPI and the status code 200 is returned too. But somewhere then it goes wrong (which I can't figure out where and why) and the status code that my Console app receives after the successful POST is 500 - an Internal Server Error occurred.
public HttpResponseMessage Post([FromBody]GPSDataVM data)
{
if (KeyRepository.IsValid(data.Key))
{
// Creates a document in DocumentDB by calling an async method CreateLiveDataDocument(data);
return new HttpResponseMessage(HttpStatusCode.OK);
}
return new HttpResponseMessage(HttpStatusCode.Unauthorized);
}
Can anyone help me out with the situation? Thanks in advance ..
I found an answer to my problem from the following address:
Web Api + HttpClient: An asynchronous module or handler completed while an asynchronous operation was still pending
I changed the definition to my WebAPI Controller to:
public **async Task<HttpResponseMessage>** Post([FromBody]GPSDataVM data) {
if (KeyRepository.IsValid(data.Key))
{
// Creates a document in DocumentDB by calling an async method
**// Code for CreateLiveDataDocument(data)**
return new HttpResponseMessage(HttpStatusCode.OK);
}
return new HttpResponseMessage(HttpStatusCode.Unauthorized); }

connected users' list in sails socket

i've currently started using sailsJS with angularJs at frontend alognwith socket for realtime communiction.
Sailsjs gives built-in support to websocket through "sails.io.js".On client side after adding this library this code is added to angular's chat controller.
Client side code
io.socket.get('/chat',{token:token},function(users){
console.log(users);
});
chatController's action on sails side is like this.
Server side code
chat: function (req, res) {
console.log(req.isSocket);
//this gives true when called through client.
})
infact very new to sails so i want suggestion that how to maintain connected user's list because m not using redis as storage purpose.adapter is memory.array is not a good idea because it'll vanish when restart a server.m using sails version of 0.11.0.
thanx in advance.
I'm somewhat new but learning fast, these suggestions should get you there unless someone else responds with greatness...
They changed it in 11 but in 10.5 I use sockets.js in config folder and on connect I store the session data in an array with their socket.
I created a service in APIs/service that contains the array and socket associate function.
For v11 you can't do that exactly the same, but you can make your first 'hello' from the client call a function in a controller that calls the associate function.
A couple tips would be don't let the client just tell you who they are, as in don't just take the username from the params but get it from req.session
(This assumes you have user auth setup)
In my case I have
in api/services/Z.js (putting the file here makes it's functions globally accessible)
var socketList = [];
module.exports = {
associateSocket: function(session, socket) { // send in your username(string) socket(object) id(mongoId) and this will push to the socketlist for lookups
sails.log.debug("associate socket called!",socketList.length)
var iHateYou = socketList
//DEBUG
var sList = socketList
var util = require('util')
if (session.authenticated){
var username = session.user.auth.username
var userId = session.user.id
// sails.log.debug("Z: associating new user!",username,userId,socket)
if (username && socket && userId) {
sList[sList.length]= {
username: session.user.auth.username,
socket: socket,
userId: session.user.id,
};
sails.log.debug('push run!!! currentsocketList length',socketList.length)
} else sails.log("Z.associateSocket called with invalid data", username, userId, authId, socket)
}else{sails.log.warn("Z.associateSocket: a socket attempted to associate itself without being logged in")}
},
}
in my config/sockets.js
onConnect: function(session, socket) {
Z.associateSocket(session,socket)
if (session.user && session.user.auth){
sails.log("config/sockets.js: "+session.user.auth.username+" CONNECT! session:",session)
}else sails.log.warn('connect called on socket without an auth, the client thinks it already has a session, so we need to fix this')
// By default, do nothing.
},
Then you can make add some functions to your services file to do lookups based on username and passwords, remove sockets that are disconnecting and the like (I'm using waterlock for my auth at the moment, although debating the switch back to sails-generate-auth)
Remove your onConnect and dicconnect function from config/sockets.js.

What is the correct way to call patch from an OData client in Web Api 2

Following the OData samples created by the web api team, my controller has the following for supporting Patch:
public HttpResponseMessage Patch([FromODataUri] int key, Delta<Foo> item)
{
var dbVersion = myDb.GetById(key);
if(dbVersion == null)
throw Request.EntityNotFound();
item.Patch(dbVersion);
myDb.Update(dbVersion);
return Request.CreateResponse(HttpStatusCode.NoContent);
}
and using the auto-generated client (derived from DataServiceContext), I submit a patch request like this:
var foo = svcContainer.Foos.Where (f => f.Id == 1).SingleOrDefault();
foo.Description = "Updated Description";
svcContainer.UpdateObject(foo);
svcContainer.SaveChanges(SaveChangesOptions.PatchOnUpdate);
However, tracing the call in fiddler, I see that all other properties of Foo are serialized and sent to the service. Is that the correct behavior? I expected only the Id and Description to be sent over the wire. Also, if I debug the service method and call
GetChangedPropertyNames on item, all its property names are returned.
Should I be creating some sort of Delta instance on the client?
I understand the disconnected nature of the service and thus the service side does not have a context for tracking changes, but it seems to me the api team added support for patch for a reason, so I'd like to know if the client ought to be invoking the update in a different manner.
Update
The link YiDing provided explains how to create a true PATCH request from the client (using the Microsoft.OData.Client.DataServiceContext created by the Microsoft.OData.Client 6.2.0 and above.
For convenience, here is the code snippet:
var svcContainer = new Default.Container(<svcUri>);
var changeTracker = new DataServiceCollection<Foo>(svcContainer.Foos.Where(f => f.Id == 1));
changeTracker[0].Description = "Patched Description";
svcContainer.SaveChanges();
The DataServiceCollection implements property tracking, and using this pattern, only the updated properties are sent to the service.
Without using DataServiceCollection and simply using
svcContainer.UpdateObject(foo);
svcContainer.SaveChanges();
all properties are still sent over the wire despite documentation to the contrary, at least as of Microsoft.OData.Client 6.7.0
The client side property tracking is now supported from Microsoft.OData.Client version 6.2.0. It will detect only the modified properties of an entity and send the update request as PATCH instead of PUT to meet the requirement of your scenario. Please refer to this blog post for more details:
https://devblogs.microsoft.com/odata/tutorial-sample-client-property-tracking-for-patch/

Wp7:Push notification channel URI is null

We are trying to test push notifications, using the latest code from the documentation How to: Set Up a Notification Channel for Windows Phone
public HttpNotificationChannel myChannel;
public void CreatingANotificationChannel()
{
myChannel = HttpNotificationChannel.Find("MyChannel");
if (myChannel == null)
{
myChannel = new HttpNotificationChannel("MyChannel","www.contoso.com");
// An application is expected to send its notification channel URI to its corresponding web service each time it launches.
// The notification channel URI is not guaranteed to be the same as the last time the application ran.
myChannel.ChannelUriUpdated += new EventHandler<NotificationChannelUriEventArgs>(myChannel_ChannelUriUpdated);
myChannel.Open();
}
else // Found an existing notification channel.
{
// The URI that the application sends to its web service.
Debug.WriteLine("Notification channel URI:" + myChannel.ChannelUri.ToString());
}
myChannel.HttpNotificationReceived += new EventHandler<HttpNotificationEventArgs>(myChannel_HttpNotificationReceived);
myChannel.ShellToastNotificationReceived += new EventHandler<NotificationEventArgs>(myChannel_ShellToastNotificationReceived);
myChannel.ErrorOccurred += new EventHandler<NotificationChannelErrorEventArgs>(myChannel_ErrorOccurred);
}
If HttpNotificationChannel.Find() returns null, it opens a new channel, but the ChannelUriUpdated event is never triggered.
If HttpNotificationChannel.Find() returns a channel, the ChannelUri property is null. The sample code crashes here because it assumes the ChannelUri property to be not null.
In neither case is the ErrorOccurred event triggered.
How can i solve this problem? This problem is because of microsoft server or any thing else?
Thnks in advance
EDIT
Waiting for replay,after ten days i am suffering of null uri problem
Can any one tell me how can i solve this problem some time MSPN server give chanalk uri ans some time not i mean some time it give null reference Exception.
What Microsoft doing?
If I don't go wrong, www.contoso.com it's a example URI to demonstrate that you need to put your own server URL address, but in my experience, I never use in that way. I prefer just to put
myChannel = new HttpNotificationChannel("MyChannel");
Look this example (it's in Spanish) but the codes are very clear of what you need to do to set the push notification client and service.
I hope I helped you.
You are testing in what mobile are Emulator,
Do you have developer account subscription for windows phone development,
Had you Developer unlocked your mobile,
Noorul.
I think the problem is that you are using the HttpNotificationChannel constructor of the authenticated web service, according to the documentation.
Instead, you should use the constructor that takes only one parameter, as you can check in this example
/// Holds the push channel that is created or found.
HttpNotificationChannel pushChannel;
// The name of our push channel.
string channelName = "ToastSampleChannel";
// Try to find the push channel.
pushChannel = HttpNotificationChannel.Find(channelName);
// If the channel was not found, then create a new connection to the push service.
if (pushChannel == null)
{
pushChannel = new HttpNotificationChannel(channelName);
...
}
Hope it helps

Resources