After further investigation, I've managed to solve the problem. What is causing the problem is that Proj4js will dynamically load any parts it needs rather than immediately loading all of it's scripts.
Internet Explorer has most trouble with this, but also Firefox and Chrome show the symptom. IE managed to not be able to use any transformations, even after a subsequent ajax call to get data had already finished. Both Firefox and Chrome did not have the transformations available on time for the center of the map being set correctly, but did have them very shortly after, resulting in my ajax-loaded data to be transformed correctly for displaying on the map.
From Visual Studio I could see that after each call to create a new projection, scripts would be dynamically loaded. Firstly, it would load the projection definition:
/Scripts/proj4js/defs/EPSG27700.js
From the definition it would then load the projection type being used (in this case transverse mercator):
/Scripts/proj4js/projCode/tmerc.js
The only problem was that apparantly, the browser was not able to process these files in time before needing to use them, resulting in no transformation actually taking place. The solution to this was to add any needed definitions to my script-includes manually:
<script type="text/javascript" src="/OpenLayers-2.10/OpenLayers.js"></script>
<script type="text/javascript" src="/Scripts/proj4js/proj4js.js"></script>
<script type="text/javascript" src="/Scripts/proj4js/projCode/merc.js"></script>
<script type="text/javascript" src="/Scripts/proj4js/projCode/tmerc.js"></script>
<script type="text/javascript" src="/Scripts/proj4js/defs/EPSG27700.js"></script>
<script type="text/javascript" src="/Scripts/proj4js/defs/EPSG900913.js"></script>
And now all the transformations I needed were avaiable as soon as the page had loaded, so it would perform all transformations correctly.
In order to know what extra files to include, see which (EPSG) definitions you need. Inlcude those definitions. Look inside those files and see which projections they use For example, EPSG 27700 is defined as follows:
Proj4js.defs["EPSG:27700"] = "+proj=tmerc +lat_0=49 +lon_0=-2 +k=0.9996012717 +x_0=400000 +y_0=-100000 +ellps=airy +datum=OSGB36 +units=m +no_defs";
So we can see that it uses tmerc
(transverse mercator), so we include that projection. Do this for any definition you need.
Note that WGS84 (EPSG:4326) is included by default. It doesn't even have a separate defining javascript file.