Thursday, March 29, 2007

OTA Bitmap Format

Further to the post about embedding a bitmap into an SMS, I needed to know the format of the picture to send. Wikipedia has an excellent article on the format, so I'll need to use this when I get those 5 minutes to give it a go.

Picture Messages in SMS

Embedding a bitmap picture into an SMS isn't something that Esendex directly supports, but after a customer's request I thought I'd take a few minutes to find out how to do it.

So I sent a picture message from my phone into one of our virtual mobile numbers, and I'm pretty sure I can reverse engineer the bytes that I got.

Then I found this Nokia article on it, which I should have known already as I used to have this document on my desk pretty much all the time... So it looks quite interesting.

I'll give it a go when I get 5 minutes, but the specification doesn't seem that complicated. Watch this space I guess.

Wednesday, March 28, 2007

MailMessage Subject Property Error

Just a small problem this time for the .Net 2.0 Migration. Assigning a string that contains line feed characters to the Subject property on a System.Net.MailMessage object will result in an error being thrown that says:

The specified string is not in the form required for a subject.

Just make sure you strip out any carriage returns (\r) or line feeds (\n) from your string before you assign it and everything will be fine.

So done, onto the next one...

EventType clr20r3 From Windows Service






In the final throws of testing part of our system on the new .Net 2.0 code, we deployed a few of our Windows services to a production server in preparation for going live with it. Luckily for us that we did because we found that one of the services appeared to stop occasionally.

The service is responsible for notifying our customer's applications of events on their accounts as part of our Push SMS API service, which for many customers is a very important part of the services we offer. So we needed to get this problem fixed before going live, but we had a number of problems with finding out why the service was stopping.

We use log4net for logging within all of our applications, but these log files did not show any errors being thrown from the service.

However, the Event Viewer did trap an error. It was in the category of a .Net Runtime 2.0 Error, being logged in the Application section of the Event Viewer. The error message looked like this:

EventType clr20r3, P1 t1f44vcumbpfz21uvtobhdijm4egyfae, P2 1.0.2643.18660, P3 460a41c8, P4 mscorlib, P5 2.0.0.0, P6 4333ab80, P7 4052, P8 27, P9 qvnotafqzyql5inknkn5msslsene3ln1, P10 NIL.

I think you'll agree its not that much help. Most of the errors were the same, but some had different garbled text in the P9 section.

The code that was running hadn't changed since the 1.1 build, and the service never used to stop on any errors previously. We have error handling that will log any error and allow the service to carry on in the event of any failures. Or so we thought anyway.

I was maybe 5 minutes away from raising a support call with Microsoft, when I found this article that explained how I could make the error message more useful: Tech Notes :: DotNet Runtime Error UPDATE: Original link seems to have died. See below.

The error is an example of an unhandled exception being thrown out of the application. You can make some sense of the error by implementing a handler for the UnhandledException event on the current AppDomain that your application is running in. This event will pass in the exception object that has been thrown, so you can log it to the Event Viewer in a more meaningful fashion.

From this we found the error and have now corrected it so the service doesn't keep stopping.

When the service started it would perform each task it was required to do in a method that we had queued in the ThreadPool. If this method managed to throw out an exception, then of course that current Thread would exit. Now, we shouldn't have been throwing exceptions out of this method anyway, but the 1.1 Framework didn't seem to mind about it.

In the 2.0 Framework it seems that if a method that is in the ThreadPool throws, then that Exception takes down the application, in this case the Windows service. Personally I feel that this is a better way of doing it, as the 1.1 Framework was masking an error in our code. The error message could have been a bit more meaningful in the first place though.

UPDATE (3 Apr 2009): The original link that was the inspiration behind solving this no longer exists.  However if you are interested please check out Unhandled Exception Processing In The CLR from the MSDN Magazine for more information.

Tuesday, March 27, 2007

DateTime XML Serialisation in .NET

Got quite a few posts to write about more version 1.1 to 2.0 migration issues. We've recently released the .Net 2 build onto some of our servers for testing, and there were quite a few problems. I'll try to keep 1 post per issue we saw.

We had a problem with our scheduled SMS service (which allows customers to specify a date and time when they want to submit a given SMS), in that the dates being used weren't being respected correctly when posting from a .Net 2 web service, through an XML formatted MSMQ, and being processed by a .Net 1.1 Windows service.

This was due to the differences between how the versions serialise DateTime objects to XML. There is what I would call a bug in the 1.1 framework that means you cannot serialise a DateTime that represents a UTC time (i.e. with zero offset from GMT, and no daylight savings adjustments). Check out this very useful article about DateTimes in general: Coding Best Practices Using DateTime in the .NET Framework.

It seems any time you put in is treated like the local time for the application deserialising it. I'm not entirely sure, but if you indicate that the time is in UTC (by adding a Z to the end of the time section), the 1.1 framework does treat that as UTC (Zulu) time, but then internally corrects it to the local time the server is in. That's certainly the behaviour we observed during tests anyway.

This has been fixed in version 2, so our solution to the problem just involves altering the order in which we deployed the .Net 2 builds to our servers.