This contract is no longer available in v1.
Extensibility has nothing similar.
Client - JavaScript Library, Persistent Connections claims to be able to do so, yet this code doesn't work:
connection.id = 'id_set_by_client_side_code';
Documentation says:
Gets or sets the client id for the current connection.
Is there an issue or am I missing something?
You no longer get control over the connection id in SignalR. People abused it by trying to share the connection id across multiple pages by making it something stable (which leads to buggy behavior). In SignalR 1.0, connection ids are always random. The only thing you can do is add a prefix.
Related
In database some entity is getting updated by some backend process. We want to show this updated value to the user not real-time but as fast as possible on website.
Problems we are facing with these approaches.
Polling :- As we know that there are better techniques then polling like SSE, WebSockets.
SSE :- In SSE the connection open for long time(I search on internet and found that it uses long polling). Which might cause problem when user increases.
WebSockets :- As we need only one way communication(from server to client), SSE is better then this.
Our Solution
We check database on every request of user and update the value.(It is not very good as it will depend upon user next request)
Is it good approach or is there any better way to do this or Am I missing something about SSE(misunderstood something).
Is it fine to use SignalR instead of this all?(is there any long connection issue in it or not?)
Thanks.
It's just up to your requirements what you should use.
Options:
You clients need only the update information, in the case they make a request -> Go your way
If you need a solution with different client types like (Webclient, Winformclient, Androidclient,....) and you have for example different browser types which you should support. Not all browsers support all mechanisme... SignalR was designed to choose automatically the right transport mechanisme according to the mechanisme which a clients supports --> SignalR is an option. (Read more details here: https://www.asp.net/signalr) Has also options that your connection keeps alive.
There are also alternatives like https://pusher.com/ (For short this is only a queue where you can send messages, and also subscribe for messages) But these services are only free until for example some data volume.
You can use event based communication. When ever there is a change(event) in the backend/database, server should send a message to clients.
Your app should register to respective events and refresh the UI when ever there is an update.
We used Socket IO for this usecase, in our apps and it worked well.
Here is the website https://socket.io/
I recently downloaded the latest version of BlazeDS turnkey from Adobe to see if I could get BlazeDS to connect to a mobile app I'd recently made in Flex. After doing one or two tutorials, I made a browser-based flex app which basically did everything I wanted the mobile app to do.
However, when I tried to get it to work in the mobile app, I get a few different errors, specifically with the RemoteObject, Producer objects. Whenever I try to access the remote object's getServers() method (the app monitors the status of a number of servers), I get a HTTP 502 error. The same thing happens whenever I try to send a message using the Producer. The error is:
Channel Fault: error; NetConnection.Call.Failed: HTTP: Status 502: url: 'http://erviceStatusUpdater.swf/samples/messagebroker/amfpolling'
"ServiceStatusUpdater" is the name of the app, which explains the first part, but not the missing letter after the "http://" declaration. Do I need to declare an endpoint for each of the producers and remote objects? And if so, what should they be? I've tried looking it up but it seems to be quite difficult to find documentation on this sort of thing.
I should also mention that "samples" is the current context root, or at least that's what it was in the other project that ran using the same server. The messaging channel as well as the remoting channel have already been setup, as these are the same as when using the browser app.
Thanks
EDIT: I've managed to get the remote object to work by specifying the end point for the remote object. For anyone who's having a similar problem, the end point (in my case) was "http://localhost:8400/{context root}/messagebroker/amf", where "{context root}" is your context root (which in my case was "samples"). The consumer still isn't receiving messages, though.
Finally fixed both issues. The issue with the RemoteObject was that the endpoint was not defined. This fix is detailed in the edit to my question.
The second issue with the consumer was to do with the fact that no channels had been defined for it. In order to do this, one has to define the channel set that the consumer should use (which can be an instance of ChannelSet), and then within that channel set, there should be a channel instance which has its URI set to point to the correct stream (which in my case happened to be the same as the remoting endpoint; amf).
I made the second fix in actionscript, not sure if it's possible to do it all in mxml.
I have a flex/LCDS stack, where I'm finding that after logout, I often (but not always) start receiving Duplicate HTTP Session errors on the client.
Here's the important facts of the stack:
The flex client has a login/logout functionality within the app. The page does not refresh after the logout. (Therefore, the Flex app, and the underlying mx.messaging.FlexClient remains initialised)
A user may have multiple tabs open.
per-client-authentication is set to false - we're trying to achieve SSO (integrating with CAS) so the user principle is bound to the JSession.
The problem is most evident when using long-polling for messaging, and when there are two (or more) tabs open.
The problem is very difficult to reproduce when using RTMP or Streaming channels.
A user is bound to a JSession - ie., if they log in on Tab1, they become logged in on Tab2.
When a user logs out from either tab, the Jsession is invalidated.
Here's my current theory as to what's causing the issue:
Tab1 (T1) Starts client -> Issued ClientId1 (C1) -> JSession1 (J1) created
Tab2 (T2) Starts Client -> Issued ClientId2 (C2) -> Joins J1
T1 logs in -> J1 Unaffected
T2 logs in -> J1 Unaffected
T1 & T2 Both subscribe, start polling over amflongpolling
T1 sends logout -> J1 Invalidated -> J2 created
T2 sends poll (against J1)
T1 logout completes, returns with J2, updates cookie
The last two calls create a conflict, where the LCDS sees the FlexClient appears to be related to 2 JSessions.
As a result, an error along the lines of the following is recieved:
Server.Processing.DuplicateSessionDetected Detected duplicate
HTTP-based FlexSessions, generally due to the remote host disabling
session cookies. Session cookies must be enabled to manage the client
connection correctly.
Note: I've been able to recreate the problem in a stand-alone project. I believe it's not an issue with our application specific code, instead caused by the Stateful / session nature and conflicts between multiple tabs sharing the same session.
In summary, I believe the issue is caused where the session is invalidated on the server as a result of calls from one tab, but before the response is sent to the browser to inform it of the new JSession, calls are issued under the old Jsession.
What are some appropriate strategies to defend against this duplicate session issue?
Update
To clarify, while the scenario is similar to those discussed here, there are subtle differences which make the solutions in that article inappropriate.
Specifically, the article discusses preventing duplicate sessions by controlling the initial creation of JSessions across both browsers, using a JSP, or an orchestrated RemoteObject call.
Flex actually assists in this process by preventing outbound RemoteObject calls until the local FlexClient DSid variable is defined, showing that the initial session has been established.
My scenario differs, because the JSession (& associated LCDS FlexSession / Client-Side FlexClient objects) have already been established once, (using the techniques discussed in that article) and subsequently invalidated via logout - which calls session.invalidate() - destroying the JSession.
The issue arises when Tab2 sends a call with a stale JSession, a duplicate HTTP Session error. The situation then gets compounded, as when LCDS throw the DuplicateHTTPSession error, it also invalidates all known Jsessions attached with the client, meaning that the Tab1 - which had been ok - now has a stale JSession. The next time that Tab1 sends a call, IT causes a DuplicateHTTPSession error, and the cycle repeats.
Unfortunately, the Flex framework hooks for delaying calls while sesssions are established have no easy way (that I've found) of being re-enabled once set. (I've tried the following, to no avail:)
// Reset DSid to get a new FlexSession established on LCDS
use namespace mx_internal
public function resetFlexSession()
{
FlexClient.getInstance().id = null;
// Note - using FlexClient.NULL_ID also doesn't work.
}
I feel for you - I've fought this for a long time and never found a solution, but found a fix that worked for me so hopefully it will at least keep this issue under control until you can find the culprit. (And if you do, please post it here).
Now, I've got a slightly different environment than you (I'm using CF on the backend) so keep that in mind.
I also tried the whole "FlexClient.getInstance().id = null;" thing too and it didn't work by itself, but it was how and where I implemented it that made it work.
So, this is what I did that made the problem go away.
On my main form, before ANY RemoteServer calls are made, I setup a creationComplete handler and placed this code you already know and love:
// Not sure if this is needed anymore, but I'm leaving it in
FlexClient.getInstance().id = null;
Next, in my very first call to the server, I gracefully handle the failure, and clear that stinking ID out again:
public function login(event:Event): void {
Swiz.executeServiceCall(roUsers.login(),
function (event:ResultEvent): void {
// Handle a successful login here...
}
, function (faultevent:FaultEvent): void {
// This code fixes this issue with IE tabs dying and leaving Flex with a Duplicate Session problem.
if (faultevent.fault.faultString.indexOf("duplicate")) {
FlexClient.getInstance().id = null;
Swiz.dispatchEvent(event);
}
});
}
And it worked.
Basically, try the call, and if it fails for the duplicate session thing, then clear out that ID and reissue the call.
The key point being that I don't think clearing out the ID works until you've made at least one call to the server. Once you do, it worked like a CHARM for me, and in all of my apps.
Note that I'm using the SWIZ framework above so just translate it to your own world.
By the way, I've never seen this error in any other browser but IE, and I believe it may have something to do with the infamous Dead Tab Issue that IE suffers from.
If the above doesn't work, I also know of a few changes to some config files on the server that might help.
Good luck my friend!
This article titled, Avoiding duplicate session detected errors in LCDS, gives an in-depth explanation of what's happening in your situation. Here is a relevant quote:
...[LCDS] believes that the FlexClient it received the request from was already
associated with a different session on the server.
For the client application to make sure that FlexClients in the
application don’t get into this bad state, the client application must
make sure that a session is already established on the server before
multiple FlexClients connect to the server at the same time.
There are several approaches recommended to fixing this, including:
calling a jsp page to load the application
"The jsp page could both create a session for the client application and return an html wrapper to the client which would load the swf."
calling a Remoting destination
"which would automatically create a session for the client application on the server"
An additional, unrelated, cause to be aware of;
Some browsers (Internet Explorer, for example) apply domain naming rules to cookies and this means that a code domain like "my_clientX.server.com", although it may return valid BlazeDS responses, will continually trigger duplicate session notifications as access to the cookie will be blocked.
Changing the name to a valid name (without underscore) will resolve the issue.
We have two client apps (a web app and an agent app) accessing methods on the same service, but with slightly different requirements. My team wants to control behaviour on the service side by passing in a ApplicationType parameter to every method - which is essentially an enum containing the name of the calling client application - which is then used as a key for a database lookup to configure the service with client-specific options.
Something about this makes me uneasy as I don't think the service should really have to be aware of which client is calling it. I'm being told that it's easier to do it this way than pass a load of options dynamically through the method call.
Is there anything wrong with the client application telling the service who they are? Or is there really no difference between passing a config key versus a set of parameterized options?
One immediate problem I can see is that if we ever opened the service to another client run by a third party, we'd have to maintain their configuration settings locally for them. At the moment we own both client apps so it's not so much of a problem.
How would you do it?
In a layered solution, you should always consider your layers as onion-like layers, and dependencies should always go inwards, never outwards.
So your GUI/App layer should depend on the businesslogic layer, the businesslogic layer should depend on the data access layer, and similar.
Unless you categorize the clients (web, win, wpf, cli), or generalize it with client profiles (which client applications can configure), I would never pass in the name of the calling application, as this would make the business logic layer aware of and dependent upon the outside layer.
What kind of differences are we talking about that would depend on the type of application? If you elaborate a bit on the differences here, perhaps someone can come up with some helpful advice on other ways to solve this.
But I would definitely look for other ways before going down your described path.
Can't you create two different services, one for each application? The two services will share a lot of code or call a single internal service with different parameterization depending on what outer service was called.
From a design perspective, this is no different than having users with different profiles. From a security perspective, I hope your applications are doing something to identify themselves, lest users of one application figure out a way to invoke the other applications logic as a hack. (Image a HR application being used by the mafia and a bank at the same time, one customer would be interesting in hacking the other customer's application on a shared application host)
In .net the design doesn't feel this way because the credentials live on the thread (i.e. when you set the IIPrincipal, that info rides on the thread-- it is communicated along with each method call, but not as a parameter.)
Maybe what you are looking for in terms of a more elegant design is an ApplicationIdentity attribute. You'd have to write a custom one, I don't know of one in the framework right now.
This is a hard topic to discuss without a solid example.
You are right for feeling that way. Sending in the client type to change behaviour is not correct. It's not a bad idea for logging... but that's about it.
Here is what I would do:
Review each method to see what needs to be different and why.
Create different methods for different usages. The method name should be self explanatory. If you ever need to break compatibility, you have more control (assuming you're not using a versioning system which would be overkill for an in-house-only service).
In some cases request parameters (flags/enum values) are more appropriate.
In some cases knowing the operating environment is more appropriate (especially for data security). The operating environment almost always sent during a login request. Something like "attended"/"secure" (agent client) vs "unattended"/"not secure" (web client). Now you must exchange a session key (HTTP cookie or an application level session id). Sessions obviously doesn't work if you need to be 100% stateless -- especially if you want to scale-out without session replication... if you have that requirement, send a structure in every request.
Think of requests like functions in your code. You wouldn't put a magic parameter that changes the behaviour of the function. You would create multiple functions that each behave differently. Whoever is using the function makes the decision which one to call.
So why is client type so wrong? Client type has no specific meaning on its own. It has many meanings and they may change over time. It's simply informational which is why it is a handy thing to log. An operating environment does have a specific meaning.
Here is a scenario to consider: What if a new client type is developed that is slightly different in a way that would break compatibility with the original request? Now you have two requests. 2 clients use Request A and 1 client uses Request B. If you pass in a client type to each request, the server is expected to work for every possible client type. Much harder to test and maintain!!
Is it possible for ASP.NET to mix up which user is associated with which session variable on the server? Are session variables immutably tied to the original user that created them across time, space & dimension?
To answer your original question: Sessions are keyed to an id that is placed in a cookie. This id is generated using some random number crypto routines. It is not guaranteed to be unique but it is highly unlikely that it will ever be duplicated in the span of the life of a session. Even if your sessions run for full work days. It would probably take years for a really popular site to even generate a duplicate key (No stats or facts to back that up).
Having said all that it doesn't appear that your problem is with session values getting mixed up. The first thing that I would start to look at is connection pooling. ADO pools connections by default but if you request a connection with a username/password that is not in the pool it should give you a new connection. Hint that may be a performance bottleneck in the future if your site is very large. It has been a while since I worked with SQL Server, in Oracle there is a call that can be made to switch the identity of the user. I would be surprised if there was no equivalent in SQL Server. You might try connecting to your DB with a generic username/password and then executing that identity switch call before you hand back the connection to the rest of your code.
It depends on your session provider, if you have overriden the session key generation in a way that is no longer unique, then multiple users may be accessing the same session.
What behavior are you seeing? And are you sure there's no static in play with the variables you are talking about?
while anything is possible. . . .
No, unless you are storing session state in sql server or some other out of process storage and then messing with it. . .
The session is bound to a user cookie, the chances of that messing up in a normal scenario is very unlikely, however there could be issues if using distributed session state.
It's not possible. Sessions are tied to the creator.
Do you want to mix up, or do you have a case when it looks like mixed up?
More information:
I've got an app that takes the userid/password from the login page and stores it in a session variable. I plop it into my connection string for making calls to SQL Server.
When a table gets updated, we're using 'system_user' in the database to identify the 'last updated by' user. We're seeing some odd behavior in which the user we're expecting to be listed is incorrect, and it's showing someone else.
Can you pop in the debugger and see if the correct value is indeed being passed on that connection string? It would quickly help you idenfity which side the problem is on.
Also make sure that none of the connection code has static properties for connection or user, or one user may have their connection replaced with that of the most recent user before the update fires off.
My guess is that you're re-using a static field on a class to hold the connection string. Those static fields are re-used across multiple IIS requests so you're probably only ever seeing the most recently logged in user in the 'last updated by'.
BTW, unless you have a REALLY good reason for doing so then you shouldn't be connecting to the DB like this. You're preventing yourself from using connection pooling which is going to hurt performance under high loads.