Since you seem to have a decent amount of control over your end-user's environment and the ability to have them install software on their desktop, I would consider registering a custom HTTP scheme that invokes your .NET executable to do the work. Registering a custom URI scheme is relatively straightforward with a couple of registry keys. If you register as an open/command like in that article's example, the browser will call your registered .EXE with the rest of the URL as your command-line parameter, and then your program can perform the work.
A benefit of this mechanism is that it works on the major browsers without having to write browser-specific code (plug-ins, etc.) From your perspective it's a little convoluted, because you will have the user invoke the external program, have it do the work, and then you need to detect on your page (ajax back to your server?) that the work got done, and allow the user to move on. But because you can pass a good bit of data to your program via the custom URI, the process could "feel" relatively seamless to your end user and not require much extra interaction, assuming they have the custom-scheme-handler installed.
A downside, though, is that (to my knowledge) detecting whether your URI scheme handler is installed on an end-user's system is not exactly simple in a cross-browser way from your web app. You may have to just let the invocation fail and pop up installation instructions if you detect on the server side that the helper app has not started and isn't working.
Even though this is not perfect, my experience is that signed java applets are getting increasingly harder for end-users to run. The browser vendors are blocking Java, or old versions of Java, or creating lots of security warnings, or Sun is changing the rules and requiring you to add things to your .JAR's manifest, or zealous firewalls just block signed .JARs altogether on the network layer because they might be malware, etc. You're going to find it is a hassle keeping up with that if you go the Java route.