SignalR: Reply to Web Forms client on same machine as web application originating request - asp.net

I'm looking for a way to support the following process:
Button is clicked in web application running on machine named PC1234.
Call is made to server (either the web server or an API on another server, it doesn't matter) to Do Something.
The server sends a notification to a Windows Forms client installed on PC1234 that the action is complete.
I've got the easy part working using SignalR. I can call a method on the web server and then send a notification with SignalR to ALL clients that the method has completed. The problem is notifying ONLY the client on the originating machine.
My initial plan was to include some unique identifying attribute of the machine with the call to the server which could then be used to direct the SignalR notification back to just that machine, but that doesn't seem to be possible.
An alternative idea was to have the call to the server include a unique reference and also update a file locally (i.e. a Cookie) with that reference, then have the client app poll the Cookie for new references and filter all SignalR messages received for that unique reference. This would be a bit clunky even if it worked, which it doesn't really, not least because I want this to work cross-browser, and different browsers store cookies in different places.
Ultimately this is to support printing locally and silently from a web application. The user selects a document in the web application, hits a print button, the request is sent to the server which retrieves the document from the database, saves it to a network share and sends a notification to a client app on the machine from which the print request was generated. The client app then prints the document from the network share and deletes it.

I never found a way to do exactly what I described in my question, but I came up with an alternative which worked well enough.
In both my web application and my Windows Forms client, the user was logged in with the same Windows credentials. I was therefore able to have the server respond to the button click in the web application by broadcasting a SignalR message to all SignalR clients where the same user was logged in, using
Clients.User(userId).send(message)
See this article for more detailed examples and instructions.
In my Windows Forms client, I included code to track how many instances of the client were connected to the SignalR Hub with the same user credentials and code to handle the receipt of a SignalR message from the server when multiple client instances were connected with the same user details (in my case, this meant displaying a message saying something like "You've requested a print from the web application but you're logged in at multiple workstations. Do you want the document to print here?").

Related

SignalR disallow connection

We are investigating using SignalR in our app for messaging. We want setup this messaging system as an app on its own. So our all our applications will connect to this messaging app to send messages. All this works fine but I am not sure as to how we can secure the SignalR messaging app. We only want our app to connect to it (basically our app users). If there are any other connections trying to connect, we want to reject this connection. Currently we set a query string parameter which can be validated on the server side but I am not sure how we can do our validation before the connection is made. I know in the hub we can override the OnConnected but this is too late. I want to refuse the connection before it starts.
Can someone point me in the correct directions.
We do that in our ASP.NET application. We have implemented an authentication module. We validate the cookie and the user in there.

Access all ongoing ASP.NET Session States

What we have is an ASP.NET web app that also does some signalR notifications. Since SignalR cannot access ASP.NET session states we need some other way to validate they are a client logged in on the web app.
In most situations you would think a static dictionary would help. As long as one of the ASP.NET Controllers made sure to keep a cache of key client info (via IP/browser info, or some generated token the client send up to signalR later) -- as long as this was done, then SignalR could validate the client connection before adding it to its pool.
However we are working in a server-farm situation, with SessionState backed by SQL. What this means is that a given server instance, even if it had a static cache of all its clients, may not know about Client C. Of course if Client C made a normal web request, it would find out about Client C when it fetched the SessionState. So the question is, IF work is handed over to a second server instance (Machine B) at just the right/wrong time, where Machine B does not know about client C (except via a context-dependent SessionState fetch, inaccessible from SignalR), HOW could we validate the client on the SignalR side?
All it would require is for some static means of getting ALL clients, OR, simply a "static" context for SessionState (i.e. a server-Session State). Because either way, we could sift through the individual client SessionStates and validate "yes, this client had a session state on a previous machine".
Is there any other way than for the client to reload the page, so that ASP.NEt can "cache up" its info locally? That is the only way I see so far.
I think it's a perfect scenario for "SignalR Backplane", it's designed for a webfarm situation to Scaleout SignalR. Lots of articles available, please search.

Web Authentication with client certification

I'm trying to authenticate login of a web app with three elements:
Userid of web app
Password of web app
Client Certificates installed on user's PC. I see a client or machine certificate as a long string or key which is stored in Windows registry.
I'm planning to put those three elements together in a table, so when user intent to login, it will send those three elements to server side and they will be checked.
For example, if user loads web app in a PC which has not be assigned to him, then server will validate that userid and password are correct, but client certificate does not belong to user, and will reject login.
I haven't yet installed a client or machine certificate in every client PC nor installed a CA in IIS. But according to Microsoft, an asp.net web app will send automatically a client or machine certificate to server and asp.net can get it. Also I have found another program example for doing that.
How is that possible? I allways thought that an asp.net web app can't read client resources and if you want to read client resources, then you should use something like ActiveX with all its complications.
Your are right, ASP.NET can't read any client resources. ASP.NET has nothing to do with getting a client certificate from the the user's PC.
What you do is to tell your Web Server (IIS) to request or require a client certificate. The server is adding a special http header to tell the browser to send a client certificate. The Browser asks Windows for one, or uses its own store (Firefox). The browser then sends the public part of the client certificate to the server.
Your ASP.NET can ask IIS whether the browser has sent a certificate and access that information for authentication purposes.

SignalR in WCF service to update web site clients

Using SignalR, is it possible to update website clients from my WCF service if the service is not used by these clients directly?
I have a desktop application in .NET which has WCF service used internally using net.TCP protocol. This application changes one of the status fields in database table depending on certain user actions. I want to notify this change to end users who are accessing a different website hosted on the same web server.
I have tried one SignalR sample where notification works fine if it is sent from same website's host to its own client (stock ticker sample). But in my case, the message should go from WCF service to a website client.
IMO you should do an intermediate hop, for example having your website exposing an endpoint (you pick the technology) where you can post whenever you have a change to notify. Your WCF service would post there whenever there's a change, and the web app would process the post by broadcasting info to the target clients (can be all, or can be just some you filter with some logic behind the post). I use this pattern quite frequently, implementing it with HTTP POST. You would have no issues to implement the SignalR infrastructure in the web app, which is where your clients already connect to.

How to communicate between ASPX and WinForms

How can I send commands to a WinForms application from an ASPX web page? We have already explored executing the WinForms application with different command line parameters but wanted something more smart.
Thanks.
Create a web server within your application that listens for HTTP GET and/or POST commands and acts appropriately. Then use AJAX to send request, i.e., http://localhost/myapp/?command=print&file=teletubies.jpg
Your web server, which is just a program that listens on port 80 and sends responses according to the very simple HTTP protocol, within your application then parses the requested URL and decides that it should print the file teletubies.jpg based on the query string in the URL.
Web pages (whether running asp.net or a competing platform) are always reactive. They receive commands (requests) and respond. They are not proactive, and don't send commands. This is how the core technology on which the internet is built works.
This means is you want an asp.net page to send a message to a client app, the only way to do it is for the client app to frequently poll the page, possibly using System.Net.WebClient.
I don't know of any way this can be done due to security. I know I wouldn't want people to be able to access the running applications on MY machine from their web app.

Resources