2012-10-29

Forcing a Culture in the business logic

Not exactly a new topic, but a reminder. In my opinion, it's a good practise for your application business logic not to assume that it will be run in a particular Windows configuration, namely a specific culture. An "innocent" ToString() or Parse() method call in a double or DateTime struct is all that takes to break your code. Last week that happened at the office, some of our unit tests were only failing on some development machines. It turned out that some of team members have Windows configured to use GB English regional settings, while others have been using PT Portuguese settings. One approach to fix this is to force a culture in all calls of these methods (US English, for instance), but I think that is boring and easy to overlook. I prefer to force the culture for all calls, something like:

Thread.CurrentThread.CurrentCulture = 
   new CultureInfo("en-US");

 Here's how I have been doing it, depending on the component type.

WCF Service

Usually, I would put the code line in the Application_Start() method of the Global.asax class, since it would apply to every service in the project. However, the last time I've did it, we were using Castle Windsor for dependency injection, and this doesn't seem to work, as the container instantiates the service object in another thread. Solution: put the line in the service constructor.

Since we are also using ThreadPool for some of the tasks, I also had to add the line to the callback method.

Yes, I could also have used the <globalization> tag in the web.config, but that would imply activating ASP.NET compatibility in WCF, which I didn't want to (no problem on doing so, but I just wanted to avoid unnecessary entropy).

Console Application / Windows Service

Usually, I would just put the line in the Program class Main method, but since we are using TopShelf to abstract some of the Windows service boilerplate code, I had to put it elsewhere. Basically, in the WhenStarted() callback.

NUnit Test

Unit tests are basically class libraries, so there is no central point method. The best I came up with was putting the code in the StartUp method, for every unit test class. Since I'm being lazy, in reality I've only added it in every test class that was failing because of culture settings.

EF POCO objects and WCF

We have recently started to use Entity Framework using a Code First approach, including POCO classes. However, when we tried to use POCO object classes as parameters of web service calls, we got the following exception:

System.ServiceModel.CommunicationException: There was an error while trying to serialize parameter http://tempuri.org/:foo. The InnerException message was 'Type 'System.Data.Entity.DynamicProxies.FooClass_F952F109218D94AD325682E75C75F0EFF0D59311269F52F267E249FB9D8F7196' with data contract name 'FooClass_F952F109218D94AD325682E75C75F0EFF0D59311269F52F267E249FB9D8F7196:http://schemas.datacontract.org/2004/07/System.Data.Entity.DynamicProxies' is not expected. Consider using a DataContractResolver or add any types not known statically to the list of known types - for example, by using the KnownTypeAttribute attribute or by adding them to the list of known types passed to DataContractSerializer.'.  Please see InnerException for more details.

What's happening? Well, it happens that a runtime, POCO objects are not really POCO, but proxies that wrap the original POCO objects. WCF knows the POCO type, but not the subtype of the proxy class. How to fix it? There are several approaches, we just opted by a simple workaround: all our classes that need to be passed as parameters for a web service calls now implement ICloneable interface and are cloned just before the call.

Perhaps a more elegant approach would be using a specific class for the parameter of the WCF service and implement a mapper between the two types, but if you need a quick workaround the clone approach does the trick.

2012-10-15

Using Fiddler for local requests

Although not documented here, an alternative way to use Fiddler to proxy local requests is to replace "localhost" in URLs by "127.0.0.1." (notice the extra dot!).

2012-10-10

Don't forget to GO after ALTER TRIGGER

Today I found peculiar issue while doing SQL scripts...

A couple of months ago, I did an SQL script that, among other things had an ALTER TRIGGER statement followed by an UPDATE statement. This particular trigger was supposed to add data to a history table. For some strange reason though, I was having trouble doing a particular update statement, because it was being undone. After a couple of hours, I found the cultrip: there was an update statement inside the trigger. What happened? I didn't do a GO statement between the trigger and the update statement.
(Yeah, maybe this is obvious for all the SQL gurus out there, but it was not for me. Lesson learnt. :))


2012-10-09

svn:ignore for Visual Studio

Similar to other source control systems, you can add an ignore list of files that should not be under source control. In subversion, this is the svn:ignore property. If you are using Visual Studio and the VisualSVN plugin, this can be achieved in the following way:

  • Right-click the solution > VisualSVN > Properties...
  • Click on New... > Advanced
    • In the Property name drop-down select svn:ignore
    • In the Property value text box put the list of expressions you want to ignore, separated by the space character.
Here is an example (work in progress, probably this will have the same content as my .gitignore):

*.suo
*.user
*.dbmdl
*.resharper
aspnet_client
thumbs.db
bin
Bin
obj
Obj
TestResults
debug
Debug
release
Release


You'll end up with something like this (TortoiseSVN):


Edit (2014-02-20)

Fixed an error in my example, each entry must be in a single line.

Update (2014-05-21)

Updated list.