Server callbacks in ASP.net - asp.net

What is the correct way to implement server callbacks in ASP.net to update a control? I know all about AJAX and async client calls to server but what about this scenario:
You display a treeview (server control) with a list of items to the user. You have a server process running which checks a queue. When an item gets added to the queue it should update the tree control. How? Sounds easy. But seems ridiculously difficult in ASP.net.

The server cannot (generally) push content out to the client. Web browsers operate in a disconnected environment - in order to simulate "push" behavior you have to have the client periodically poll the server.
The exception to this is if you can use a technology like Silverlight or Flash, which can maintain persistent duplex connections to the server independent of the browser.
As far as I'm aware, most website that appear to dynamically "push" content out to the browser (eg. gmail, facebook chat, etc) are really polling periodically from the client.

Related

SignalR: Reply to Web Forms client on same machine as web application originating request

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?").

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.

What are the possible threats while calling web services by using JQuery and how can avoid them?

I know this question can be too generic but for purposes of narrowing the question, here is a brief description:
I'm planning to forget about ASP.net UpdatePanel and move to use ajax via JQuery. I am afraid that because of the plain, client-side nature of JavaScript (and consequently JQuery code), any one looking to my web page's source can realize what is the URL of the web services I'm calling and also what are being passed to those web services.
When using UpdatePanel for these types of operations, I'm sure that calling web services is done on server-side and I have no concern regarding issues of information on calling sensitive web services being exposed publicly but now that I'm planning to use Ajax via JQuery, It worries me alot.
Are my concerns reasonable and if true, what are the best solutions for avoiding the threats of web-service-calling-info being exposed?
Clarification: when saying UpdatePanel, I mean utilizing a chain of techiques including ASP.net AJAX, code-behind and relying on server-side Dlls for performing async server-side operations instead of jquery Ajax which requires web services for intracting with server.
There is no way on the internet to protect your web services all the time by just hiding the URL. I am not sure when you say your updatepanel does the web service call from the server you are not taking the true power of AJAX.
One way to secure your web service is to use the authentication in the web service side. For example you need to send some authentication key every time you access the source, and this is very common, you have so many public web service who protects it self using auth key like OpenId implementation. In case you do not want to change the web service logic I think jquery way of AJAX is not a secure option.
Here's a thought, you can have two levels of web service, one which will open for all that you can use in the jquery. From the current web service, from the server side call the other secure web service. Even now you can configure your incoming request for some specific machine IP.
In this case other than your own server no body else can access to the web service securely kept behind the firewall. It is something similar we do while connecting to database server from application server.
Let me know if this helps.
I'm going to state the problems my answer is hoping to solve:
Assuming you host your services on a machine other than the web server, the problem is you give potential attackers the name/address of those machines.
Attackers can write scripts/bots to scrape your data.
Attackers can focus on your web services and try to hack them/gain access to your network.
Attackers can try to perform a DoS/DDoS on your web services.
The solution I've used in the past is to create a light weight proxy on the web server such that all AJAX calls simply point back to the current domain. Then when a call comes in, it is simply routed to the appropriate web service, which is hosted somewhere internally on the network.
It creates one additional hop on the network, but it also has these benefits:
It hides the actual IP of the machine hosting your services.
You can easily lock down that one web server and monitor unusual activity. If you see a spike in activity, you can potentially shut down the web services. (If you use a different machine, you'd have to monitor two boxes. Not a huge problem, but easier to monitor just one.)
You can easily put a distributed caching layer in the proxy. This protects you from load/denial of service (DoS) attacks and obviously supports normal web service traffic.
You can hide the authentication at the proxy level. The public calls won't betray your authentication scheme. Otherwise an attacker can see what tokens or keys or secrets or whatever that you use. Making a proxy on the web server hides that information. The data will still flow through, but again you can monitor it.
The real benefit in my opinion is that it reduces the surface area of your application which narrows what an attacker can do.
Since you refer to ASP.Net, know its viewstate can easily be decrypted. There's no failproof ways to protect your code (not to say urls called).
If you're web services are called with some parameters that could allow unrestricted and dangerous actions, then you'd better start using some users/roles/rights management.
If you're worried about "man in the middle" attacks, you best option is to use https.

Key Events in ASP

How can I capture key events in ASP using C# code?
for example, I want to press the left key and a text box will pronounce "Left Pressed".
You misunderstand how web applications and ASP.NET work. Keys are pressed by the user on the client side, in the browser that shows HTML pages. ASP.NET and the C# code that makes up the web application run on the server side. You cannot really capture key events on the server side. Even if you could, you shouldn't - every time the user would press a key, you'd have to send it over to the server side, evaluate it and then render the page again and send it back to the browser. This would generate a lot of traffic and force page reloads very frequently, making the pages very hard to use. Even AJAX calls wouldn't help much with this.
Instead, you should handle key presses on the client side, in JavaScript code that runs inside the browser and when you encounter something that the server needs to handle, you can then perform a server call.
This site (among a bunch of others) has code samples that show how to implement key detection in JavaScript:
http://www.alessandrolacava.com/using-javascript-to-detect-the-key-pressed/
Edit:
Alternatively, you can try using Silverlight, which is a programmable browser plugin similar to Flash. Silverlight hosts the .NET Framework and can be programmed using C#. Even in this case, though, you'll handle keys on the client side, not on the server.

The Effort to Keep Credit Card Information Away from My Shared Server while using ASP.Net Web Forms

Focusing on clients who can not afford PCI compliant servers I intend to limit credit card information to a form entry that posts to the gateway via SSL. I do not store CC info on my clients shared server. My question is about the ASP.NET web form that uses server controls and if form information is in any way run through my clients shared and potentially unsecure server just by using form elements with runat=server. In this form I am using plain html input elements to collect the CC#, CVV# and expiration date but the submit element uses runat=server as I have logic in the code behind that limits the visibility of the button if a condition is not met.
If the form on the shared server accepts card details then that server & network must be PCI compliant, the fact that the details are not stored doesn't matter. Given that its a shared server achieving compliance will be virtually impossible.
The best way to keep card data away from the shared server is to have its page host an IFrame for a page thats hosted on a dedicated, compliant server.
If you never have any postbacks that should work, but if you do have any controls that support postbacks, the cc info will possibly be included (depends upon viewstate).
It sounds like you're going to have access to the cc info, as otherwise it doesn't make sense to make the button visible or not...

Resources