Archive for May 2007
ASP.NET AJAX is a P.O.S. designed by naive Microsoft-universe programmers.
(Update 3: Ok, so the outlandish headline probably roped you in … Make sure you read all the way to the bottom, and watch for the follow post on its way soon)
ASP.NET rocks.
ASP.NET AJAX disappoints me.
Well, that’s my personal opinion right now. Let me demonstrate. Feel free to follow along at home and tell me how you go. I’m using v1.0.61025:
First, start by creating a brand new “ASP.NET AJAX-Enabled Web Application” in Visual Studio:
Keep the default, template supplied code. Do not change anything from the defaults.
Change the project to use IIS so it can be accessed from the Mac (the built in server – Casini – is useless if you actually want to test your work in even a semi-adequate collection of browsers because it only accepts connections from localhost):
Run the project in IE7 to check it all works.
No server errors, no JS errors. Schweet:
Open Safari 2.0 (a browser listed as being supported by MS):
Open the debug console:
Load the page. Boom! Crash! Bang!
Yeah awesome – thanks guys. Champion effort.
Are we the only company who actually test our work properly? And no, this isn’t a blind case of “must support everybody for the sake of web standards”, this is a business need driven by the fact that almost 15% of the traffic that hits our servers comes from Safari. Some of our sites peak with a majority of their userbase on Safari – it’s the nature of their industry.
Update: Just to make sure I’m not being a total idiot I downloaded Scottgu’s “ToDo List” sample app from the ASP.NET AJAX site. It doesn’t crash in Safari, but it doesn’t actually do any AJAX either. There are no partial postbacks, and I can’t see any other evidence of the library actually adding value to the application when run in Safari. Now to start diff’ing and work out what magical setting Scott switched from the defaults to make it work.
Update 2: So, here’s the real compatibility guideline from my testing using a blank site, Scott’s sample and my big mumma’ of a commercial project… I’m hosting them on IIS7 with Vista RTM. All the Safari 2.0 tests are performed on Mac OS X, but as per the various Safari version compatibilities, the OS version ranges between 10.4.1 and 10.4.9.
- Safari 2.0 – Serve the uncompressed debug scripts (set ScriptMode=Debug on your Script Manager). The release mode scripts cause the parse error. You’ll get some bits working, but core things like the UpdatePanel will silently die – you just get full postbacks instead.
- Safari 2.0.1 – You’re dreaming. I couldn’t get anything to work.
- Safari 2.0.2 and 2.0.3 – Same as 2.0 for me.
- Safari 2.0.4 – Praise the lord – it works! It would even seem that you can run your scripts in release mode.
As per their documentation, Safari 1.x doesn’t work at all. (I tested Safari 1.3.2.) That’s fine – they said it didn’t work, so that’s the understanding I had when I chose to use the framework. Any Safair 1.3 issues are totally my responsibility.
In our normal development, we test both Safari 1.3 and Safari 2.0. There are major differences between the 1.x line and the 2.x line, so we found we needed to test in both. The Mac-based designers run the bleeding edge updates, but we keep the testing machines in their original un-updated state to replicate the large chunk of users out there who ignore Software Update.
Well, what are the outcomes from all this:
- The documentation is wrong and obviously untested. C’mon guys, I bought a couple of G4 towers off eBay for $80 each that I use via VNC to test this stuff. This information is listed in your technical documentation, not a wishy-washy marketing blurb, so be accurate and test it.
- I’m disappointed that Safari 2.0 through Safari 2.0.3 don’t work – there are lots of users still scatted across these different builds.
Unfortunately we’ve been having a really bad run with ASP.NET AJAX on our projects – issues in all the browsers, not just Safari – and I’m not keen to use it again any time soon. For now, we’re going to have to stick to one of the many other client side frameworks out there.
Over the last few days I’ve been talking to a number of the local guys about my opinions on MS in the client space at the moment. As per Neil’s suggestion, I’m going to write a post along the lines of “What I think needs to happen before I’m confident deploying ASP.NET AJAX or Silverlight”. I’m still a 100% Microsoft zealot when it comes to the server side components, but I’m temporarily losing confidence with their client-side abilities. I hope to have that confidence restored soon.
Update 4: Followed up at http://blog.tatham.oddie.com.au/2007/06/07/aspnet-ajax-continued/
Debugging SSL/TLS problems in .NET
In my previous post I discussed some issues I discovered with SSL client certificates.
For this application, I’m dealing with PayPal. Rather annoylingly, if your client certificate doesn’t check out, they don’t even bother sending an error – they just drop the TCP connection mid-SSL-handshake. Depending on how fast the connection loss is realised, .NET can return a few different errors; none of which are actually much use when it comes to debugging.
Luckily, System.Net (as with most other areas of the framework) has wonderful tracing capabilities. Particularly with a complex process like an SSL handshake, these capabilities become critical to debugging.
Better yet – they’re incredibly easy to use. Just add a block like this to the end of your app.config!
<system.diagnostics>
<trace autoflush="true"/>
<sources>
<source name="System.Net" maxdatasize="1024">
<listeners>
<add name="TraceFile"/>
</listeners>
</source>
<source name="System.Net.Sockets" maxdatasize="1024">
<listeners>
<add name="TraceFile"/>
</listeners>
</source>
</sources>
<sharedListeners>
<add name="TraceFile" type="System.Diagnostics.TextWriterTraceListener"
initializeData="trace.log"/>
</sharedListeners>
<switches>
<add name="System.Net" value="Verbose" />
<add name="System.Net.Sockets" value="Verbose" />
</switches>
</system.diagnostics>
Now, run your app again and take a look at the wonderful lines being added to your bin\Debug\trace.log file.
Getting your PayPal API certificate into a format usable from C#/VB.NET
(Disclaimer: I’m not a security expert – I’m just a dude who bashes his head against the wall until I can find a way to make it work.)
The certificate file that PayPal issues (cert_key_pem.txt) is pretty useless if you’re calling their API from .NET. (I don’t know about other platforms).
Fortunately, it’s a simple one step process to generate a cert_key.der file that you can then use from C# like this:
X509Certificate certificate = X509Certificate.CreateFromCertFile(certificatePath);
httpWebRequest.ClientCertificates.Add(certificate);
What scares me (and thus became the motivation behind the blog post) is that while there is lots of documentation around this process, it’s all painfully over-complicated! Unfortunately this hack method has been distributed so far now that even O’Reilly, a respected publisher, is touting it in print as the best process. Their method is to use OpenSSL to convert it from PEM to P12 format, then import it into your local certificate store using MMC, and finally export it back to CER format.
You can actually achieve an equivalent process using a single call to OpenSSL:
openssl x509 -outform der -in cert_key_pem.txt -out cert_key.der
(Note: OpenSSL is an awesome, and free, open-soure tool you can download from here.)
It puzzles me why this harder, more error prone method is getting all the airtime? I came up with two answers:
- It’ could be a new feature in OpenSSL and hence wasn’t possible before.
- This process is normally being executed by people who’ve never touched X509 certificates before, and thus never realised that DER (what OpenSSL produces) is the same thing as CER (what .NET expects).
I hope people find this simpler method before they start littering their certificates throughout their development machine registries.
Update: The rest of the story …
After playing with this a bit more, I can now see where this idea has come from, however I still don’t like it.
A .cer file only contains your public key, which isn’t very useful for signing something; .NET needs to have access to the private key too. If you only used the code above, then moved you app to a different machine, you’d be getting an SSL-related exception when you called httpWebRequest.GetResponse(). Taking a look at the tracing output from System.Net would reveal something like this:
System.Net Information: 0 : [5988] SecureChannel#23264094 – Locating the private key for the certificate: [Subject]
C=AU, S=New South Wales, L=Neutral Bay, CN=tatham_api1.oddie.com.au[Issuer]
E=re@paypal.com, CN=live_camerchapi, OU=live_certs, O=”PayPal, Inc.”, L=San Jose, S=California, C=US[Serial Number]
00D53D[Not Before]
23/05/2007 11:08:48 AM[Not After]
20/05/2017 11:08:48 AM[Thumbprint]
0461121436D3CE11C042BF3F67884B4220072853
.
System.Net Information: 0 : [5988] SecureChannel#23264094 – Cannot find the certificate in either the LocalMachine store or the CurrentUser store.
Notice that last line saying it couldn’t find the certificate in the store - even though we’d loaded it directly from file? That’s .NET trying to find the full certificate to get the private key.
This is where the first approach comes in handy – in the process using their local certificate store to import/export, most users wouldn’t have deleted the certificate afterwards. The private key remains in the certificate store, and .NET can resolve it from there. There is in fact a benefit to this approach – your private key can be stored somewhere outside you file system and thus be more secure. Well, that’s the theory anyway. In reality – it still needs to be somewhere that your process can access, be it an ACLed file or the certificate store it probably doesn’t make that much of a difference.
The problem to this approach is the deployment impact – you need to be able to install the certificate in the servers store. In some environments this just isn’t possible, and in other environments it just sounds painfully fiddly. So – how can we load the entire certificate, including the public and private key tokens – from a file?
As before, we’re going to use OpenSSL to convert the supplied certificate into something useful. This time though, we’re going to convert it to a P12 file (otherwise known as a “PKCS#12 container file”). These files contain not only certificates, but also private keys in encrypted form.
openssl pkcs12 -export -in cert_key_pem.txt -out cert_key.p12
When you execute this command, OpenSSL will ask you to choose a password. It will use this password to encrypt your private key, so make the password complex and unique.
You can now load and attach the certificate like so:
string certificatePath = Path.GetFullPath(Path.Combine(Assembly.GetExecutingAssembly().Location, @”..\..\..\..\cert_key.p12″));
string certificatePassword = “p12passwordhere”;
X509Certificate clientCertificate = new X509Certificate2(certificatePath, certificatePassword);
httpWebRequest.ClientCertificates.Add(clientCertificate);
Voila! It works.
Now, you just need a way to securely store your API username, API password, P12 file and P12 password. That’s something I’ll cover in another blog post.






