How Can the `id` Query String Parameter in a Blazor WebSocket Connection Be Accessed? - signalr

When debugging with my Blazor server-side application, I see the following message:
[2022-02-25T10:40:19.177Z] Information: WebSocket connected to wss://<host>/_blazor?id=<_identifier_>.
I am interested in the id query string parameter specifically. Is this value available in any way within a Blazor application? I looked in the ComponentHub.Context.ConnectionId but it does not appear to match this value.
I do realize that I can use the IHttpContextAccesssor, but want to stay away from this as this is considered poor practice with Blazor applications.
(If I am mistaken about this particular scenario that would be great to know as well.)

This is an internal implementation detail of the SignalR handshake, and it is absolutely not meant for the developer to do anything with it.
For instance, if a websocket connection can't be established, because of networking issues, SignalR falls back to long polling, and each long polling request will get a new ID query parameter, which internally all map to the same SignalR connection id.
See also this great article why this is a bad idea: https://consultwithgriff.com/signalr-connection-ids/

Related

Need to validate approach: Spring Integration + AMQP + Async

I've been recently investigating about Spring Integration and AMQP (RabbitMQ), as I need to communicate two applications (middleware and backend) with async approach, so that the middleware doesn't block when receiving client calls.
I first followed the simpler approach of implementing this in a synchronous, this meaning that I have a gateway interface and an outbound gateway (with requiresReply=true) on the middleware, and then an inbound gateway and a service activator on the backend. This initial approach works well (I've used Spring Integration XML config).
Now I need clarification on the approach to follow to make this work in an async way.
By looking at the RabbitMQ Tutorial 6, it's better to work with a callback queue and a correlationId, and per what I understood, this would be similar to calling Spring RabbitTemplate's convertAndSend() and then receive(), instead of convertSendAndReceive() (which would block until response is received).
I've checked the Spring Integration docs, where I need to replace the gateway interface on the middleware for it to return Future or ListenableFuture.
Async Gateway
Once that's done, I also looked at the documentation for the outbound gateway, where it says that it can work together with the RabbitTemplate to manage the correlationID and replyTo message attributes.
My questions are:
In order to make this work with an async approach, should I keep working with outbound/inbound gateways, instead of outbound/inbound message converters?
In case of following the outbound/inbound message converters approach (which sounds to me similar to what the RabbitMQ tutorial shows), how do I associate the Future on the gateway interface with the result coming back from with inbound channel adapter?
To be honest you don't provide an original business requirement. It might be a fact that there is really no reason to get deal with this async handsoff, because you have a #Gateway as an entry point which is thread-free and even if it is blocked to wait for the reply it doesn't impact other threads which may perform similar sendAndReceive operation. In most cases it is really just enough to do everything within the same requestor thread and don't loose performance with shifting to the shared ThreadPoolExecutor.
Right, the Future allows you to free a caller a bit to be ready to accept new requests within the same thread.
Since it is a MessagingGateway and you want to have a reply anyway, there is a hook associated with the request - TemporaryReplyChannel header. That's why that <outbound-gateway> works properly: it place its blocking reply to that channel for the gateway's return (or for FutureTask#set()).
I'd say that we can achieve the same TemporaryReplyChannel gain with that your async reply requirement.
You should use inbound/outbound channel adapter pair.
Before send the message to the <int-amqp:outbound-channel-adapter> you should do this <header-channels-to-string> for the <header-enricher>.
The server side maybe the same - <int-amqp:inbound-gateway>
You should use fixed replyQueue as a header for those message to send through the <int-amqp:outbound-channel-adapter>
the <int-amqp:inbound-channel-adapter> should be configured for that fixed replyQueue.
Both <int-amqp:outbound-channel-adapter> on client side and <int-amqp:inbound-gateway> must be configured for the mapped-request-headers="*" to allow to propagate that reply-channel header to the server and vise versa.
The <int-amqp:inbound-channel-adapter> on the client side will just send the reply to the reply-channel as it is for the <int-amqp:outbound-gateway>
You may need to take care about the correlationId manually, since <int-amqp:inbound-gateway> may require that to produce a reply properly.
Well, something like that...
HTH
Feel free to ask more questions. Or correct me if I misunderstood your question.

How SignalR broadcast the messages?

Have started using SignalR. Would like to clear few queries regarding how SignalR have implemented broadcasting basically how server is able to initiate the Communication ?
1> In normal scenario whenever we request for a let say .aspx page, the server renders the page and returns the reponse back to the client and the things is done
But How SignalR is able to continously able to execute in Background/Async in case of Ticker demo available on the ASP.net site.
I googled little bit and found IRegisteredObject is one of the way where the the object which need to be excuted continously need to register with HostingEnvironment but for that the class have to implement the IRegisteredObject interface but in case of ticker demo none of the class implements the IRegisteredObject interface.
Am I mssing something over here or SignalR uses totally different technique ?
SignalR utilizes 4 transports through which it handles data from the server. Only one transport is used at a time but SignalR has 4 to ensure server/client communication on a wide variety of devices/browsers. Here's the transports and a short technical description:
Long Polling, to receive data it uses an ajax request whose response is not released until there is data available on the server, once the server returns data on the held onto response the client then creates another request and waits for the next batch of data. To send data it creates a second ajax request.
Forever Frame, uses iframes through which the server pushes down javascript text which is then executed in the iframe, the iframe then propagates the execution up to the parent page which then handles the data. To send data SignalR uses ajax requests.
Server Sent Events, uses the EventSource object. Supported in nearly everything but IE. The EventSource object opens up a one way pipe through which the server can pump data through, allowing the client to receive data in real time. To send data SignalR uses ajax requests.
Web Sockets, uses the built-in browser WebSocket object which opens up a single, bi-directional channel through which data can be received and sent.
That's the essence of each of SignalR's transports, you can see an hour presentation in which David Fowler and Damian Edwards create a Lite version of SignalR here. It essentially highlights how SignalR works under the covers.

SignalR1.0.1 - Maintain connectionId

I'm using SignalR 1.0.1 and I want to maintain connection id even on page refresh.
Yes, I know, this is a common question of signalr so I got good answered post also but in all of them they mentioned "IConnectionIdFactory" interface which is missing in my app.
1) https://stackoverflow.com/questions/9518394/signalr-maintaining-user-connection-ids
2) http://www.kevgriffin.com/maintaining-signalr-connectionids-across-page-instances/
Before this I was using SignalR alpha version and in that I have manage this issue using "IConnectionIdPrefixGenerator". But in new version this interface is also missing.
Can anyone guide me How to fix this issue proper way?
There is no longer any recommended pattern for setting or maintaining the connection id of a SignalR client in 1.0. I would suggest making single user groups in lieu of ConnectionIds.
SignalR 1.0 beta connection factory
If you don't need to use a custom string to address messages sent to a client and you can trust your clients, you can include metadata inside the query string of each SignalR request.
How to parameterize a SignalR route?

Can an HTTP connection be passed from IIS/ASP.NET to another application or service?

I'm looking into building an ASP.NET MVC application that exposes (other than the usual HTML pages) JSON and XML REST services, as well as Web Sockets.
In a perfect world, I would be able to use the same URLs for the Web Sockets interface as I do for the other services (and determine which data to return by what the user agent requests) but, knowing that IIS wasn't built for persistent connections, I need to know if there's a way that I can accept (and possibly even handshake) the Web Sockets connection and then pass the connection off to another service running on the server.
I do have a workaround in mind if this isn't possible that basically involves using ASP.NET to check for the Web Sockets connection upgrade headers, and responding with a HTTP/1.1 302 Found that points to a different host that has my Web Sockets service configured to directly listen to the appopriate endpoint(s).
If I completely understand your goal, I believe you can use the IIS7/7.5 Application Request Routing module to accomplish this.
Here's a quick reference: http://learn.iis.net/page.aspx/489/using-the-application-request-routing-module/
Rather than 302 responses you could use ISAPI_rewrite to direct to an appropriate endpoint (and manipulate the HTTP header to get it there)
http://www.isapirewrite.com/docs/
Otherwise no, IIS cannot natively pass off an HTTP connection. The current MSFT method is to use a 302 or something else that is intercepting the raw socket and performing header manipulation prior to sending to IIS (or whatever other application)
It strikes me that this would be a better question to ask Microsoft than to ask us. Web Sockets is new technology, and rather than looking for a hack, you might want to ask Microsoft how they plan to support it. IIS is their software. Poke around on http://iis.net (maybe in http://forums.iis.net) and see what you learn.
The way to do this is to use a unique Session ID that is associated with the Http Session. From the description, it seems like you might want to scope this to a single HttpApplication instance, but this is not necessary (you may also persist a session across many application instances). Anyway, this session ID needs to be attached somehow to each Http Request (either with a cookie, querystring, static variable with the HttpApplication instance, form data). Then you persist the identifying information about the Http session somewhere with the ID.
This identifying information may vary depending on your needs but could entail the entire http request or just some stripped down representation that serves your particular purpose.
Using this SessionID somewhere in the Http request allows you to restore whatever information you need to call and interact with the appropriate services. The instances of the services may also need to be scoped to the session as well.
Basically, what I am suggesting is that you NOT directly pass the Http connection to an external process, but instead pass the necessary data to the external process, and allow create a mechanism for sending callback data. I think looking into the mediator pattern may be helpful for you in understanding what I mean here. http://en.wikipedia.org/wiki/Mediator_pattern . I hope this helps.

HttpSession Session ID different to FlexSession ID

I have a Flex application which is served via a JSP page. In this page I output the session ID using HttpSession when the page is loaded:
System.out.println("Session ID: " + session.getId());
In a very simple remote object hosted in BlazeDS (called from the flex application using an AMF Channel and standard RemoteObject functionality) I also output the session ID but this time using FlexSession (which as I understand is supposed to wrap around HttpSession).
System.out.println("FlexSession ID: " + FlexContext.getFlexSession().getId());
I would expect both IDs to be the same but this is not the case. The session IDs differ which is causing problems as there is data stored in the HttpSession which I need to be able to access from my remote objects within BlazeDS.
I've exhausted the reading material on BlazeDS and FlexClient/FlexSession/FlexContext but can't see why the FlexSession is not being linked to the HttpSession. Any pointers greatly appreciated.
I feel I must be missing something fundemental here, am I accessing the
I do not think that it is related to the FlashPlayer..is more related to the concept of FlexSession and how BlazeDS/LCDS works. For example you can have an active session even when not using the http channels - when using NIO/RTMP you are bypassing the application server and the http protocol. So it make sense to have an abstract class FlexSession with various implementations.
However when using BlazeDS FlexSession will wrap an HttpSession object internally, and removeAttribute/getAttribute/setAttribute are in fact calling the the same methods from the HttpSession object..so you can access all the data from the HttpSession. If not please provide more details.
However, it will not work when using RTMP channels(which exists only in LCDS by the way), you need to change your design in this case.
Thanks to both answers above I finally found the root cause and thought I'd share it on here.
The reason for differing session IDs was to do with the use of SSL for authentication and the use of AMF Channel rather than Secure AMF. Using the channel for the first time caused a new session to be created (hence the different ID) as the existing session related to the secure version of the site.
Silly configuration mistake but worth passing on - make sure that if using SSL that you're also using Secure AMF connecting to the secure endpoint rather than standard AMF or you'll run into the same session ID problems I faced.
Unfortunately this is just how the Flash player works. I have seen this same behavior many times.
The best solution I found was to establish the HTTP session and pass back the session ID. On the client side, you can then pass the session ID to the Flex application. You then send that ID from Flash to the server and use it to look up the existing session or establish a second session.
You will need to do something like this though, I have not been able to find a way to reliably get Flash to use the same session.

Resources