Error: Failed to compile both on .NET 4.5 and on .NET 4.0. 4.5 Exception: System.IO.IOException: The file exists.

Today I had a weird issue with a Microsoft IIS web-server. The latest .NET Framework was correctly installed and registered on the server, but when I put my .NET code in the web directory and browsed to it from a remote browser I got the standard .NET error page. I would get the error regardless of whether I was trying to access a page served by .NET or a basic HTML page hosted on the server. I confirmed that IIS was working correctly by removing all files (including the web.config file) from the web-directory and putting in a basic test HTML page on its own. The test page rendered correctly from a remote browser.

Having put the .NET code back in, I browsed to a .NET URL locally on the web-server in order to get a full view of the error message. The rather strange error was as follows:

File Exists Error

In order to help people find this page in search engines, the full text was as follows:

Server Error in '/' Application.

Failed to compile both on .NET 4.5 and on .NET 4.0. 4.5 Exception: System.IO.IOException: The file exists.

   at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)
   at System.IO.Path.InternalGetTempFileName(Boolean checkHost)
   at HibernatingRhinos.Profiler.Appender.Util.GenerateAssembly.CompileInternally(String fileName, List`1 sources, HashSet`1 assemblies, HashSet`1 defineSymbols, String outputFolder, String compilerVersion, Int32 tryCount)
   at HibernatingRhinos.Profiler.Appender.Util.GenerateAssembly.CompileAssembly(List`1 sources, HashSet`1 assemblies, HashSet`1 defineSymbols, String assemblyFileName, String outputFolder). 4.0 Exception: System.IO.IOException: The file exists.

   at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)
   at System.IO.Path.InternalGetTempFileName(Boolean checkHost)
   at HibernatingRhinos.Profiler.Appender.Util.GenerateAssembly.CompileInternally(String fileName, List`1 sources, HashSet`1 assemblies, HashSet`1 defineSymbols, String outputFolder, String compilerVersion, Int32 tryCount)
   at HibernatingRhinos.Profiler.Appender.Util.GenerateAssembly.CompileAssembly(List`1 sources, HashSet`1 assemblies, HashSet`1 defineSymbols, String assemblyFileName, String outputFolder) 
  Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code. 

 Exception Details: System.InvalidOperationException: Failed to compile both on .NET 4.5 and on .NET 4.0. 4.5 Exception: System.IO.IOException: The file exists.

   at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)
   at System.IO.Path.InternalGetTempFileName(Boolean checkHost)
   at HibernatingRhinos.Profiler.Appender.Util.GenerateAssembly.CompileInternally(String fileName, List`1 sources, HashSet`1 assemblies, HashSet`1 defineSymbols, String outputFolder, String compilerVersion, Int32 tryCount)
   at HibernatingRhinos.Profiler.Appender.Util.GenerateAssembly.CompileAssembly(List`1 sources, HashSet`1 assemblies, HashSet`1 defineSymbols, String assemblyFileName, String outputFolder). 4.0 Exception: System.IO.IOException: The file exists.

   at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)
   at System.IO.Path.InternalGetTempFileName(Boolean checkHost)
   at HibernatingRhinos.Profiler.Appender.Util.GenerateAssembly.CompileInternally(String fileName, List`1 sources, HashSet`1 assemblies, HashSet`1 defineSymbols, String outputFolder, String compilerVersion, Int32 tryCount)
   at HibernatingRhinos.Profiler.Appender.Util.GenerateAssembly.CompileAssembly(List`1 sources, HashSet`1 assemblies, HashSet`1 defineSymbols, String assemblyFileName, String outputFolder)

Source Error: 


 An unhandled exception was generated during the execution of the current web request. Information regarding the origin and location of the exception can be identified using the exception stack trace below.  

Stack Trace: 



[InvalidOperationException: Failed to compile both on .NET 4.5 and on .NET 4.0. 4.5 Exception: System.IO.IOException: The file exists.

   at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)
   at System.IO.Path.InternalGetTempFileName(Boolean checkHost)
   at HibernatingRhinos.Profiler.Appender.Util.GenerateAssembly.CompileInternally(String fileName, List`1 sources, HashSet`1 assemblies, HashSet`1 defineSymbols, String outputFolder, String compilerVersion, Int32 tryCount)
   at HibernatingRhinos.Profiler.Appender.Util.GenerateAssembly.CompileAssembly(List`1 sources, HashSet`1 assemblies, HashSet`1 defineSymbols, String assemblyFileName, String outputFolder). 4.0 Exception: System.IO.IOException: The file exists.

   at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)
   at System.IO.Path.InternalGetTempFileName(Boolean checkHost)
   at HibernatingRhinos.Profiler.Appender.Util.GenerateAssembly.CompileInternally(String fileName, List`1 sources, HashSet`1 assemblies, HashSet`1 defineSymbols, String outputFolder, String compilerVersion, Int32 tryCount)
   at HibernatingRhinos.Profiler.Appender.Util.GenerateAssembly.CompileAssembly(List`1 sources, HashSet`1 assemblies, HashSet`1 defineSymbols, String assemblyFileName, String outputFolder)]
   HibernatingRhinos.Profiler.Appender.Util.GenerateAssembly.CompileAssembly(List`1 sources, HashSet`1 assemblies, HashSet`1 defineSymbols, String assemblyFileName, String outputFolder) +712

[InvalidOperationException: System.InvalidOperationException: Failed to compile both on .NET 4.5 and on .NET 4.0. 4.5 Exception: System.IO.IOException: The file exists.

   at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)
   at System.IO.Path.InternalGetTempFileName(Boolean checkHost)
   at HibernatingRhinos.Profiler.Appender.Util.GenerateAssembly.CompileInternally(String fileName, List`1 sources, HashSet`1 assemblies, HashSet`1 defineSymbols, String outputFolder, String compilerVersion, Int32 tryCount)
   at HibernatingRhinos.Profiler.Appender.Util.GenerateAssembly.CompileAssembly(List`1 sources, HashSet`1 assemblies, HashSet`1 defineSymbols, String assemblyFileName, String outputFolder). 4.0 Exception: System.IO.IOException: The file exists.

   at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)
   at System.IO.Path.InternalGetTempFileName(Boolean checkHost)
   at HibernatingRhinos.Profiler.Appender.Util.GenerateAssembly.CompileInternally(String fileName, List`1 sources, HashSet`1 assemblies, HashSet`1 defineSymbols, String outputFolder, String compilerVersion, Int32 tryCount)
   at HibernatingRhinos.Profiler.Appender.Util.GenerateAssembly.CompileAssembly(List`1 sources, HashSet`1 assemblies, HashSet`1 defineSymbols, String assemblyFileName, String outputFolder)
   at HibernatingRhinos.Profiler.Appender.Util.GenerateAssembly.CompileAssembly(List`1 sources, HashSet`1 assemblies, HashSet`1 defineSymbols, String assemblyFileName, String outputFolder)
ImageRuntimeVersion: v4.0.30319]
   HibernatingRhinos.Profiler.Appender.Util.GenerateAssembly.CompileAssembly(List`1 sources, HashSet`1 assemblies, HashSet`1 defineSymbols, String assemblyFileName, String outputFolder) +1042
   HibernatingRhinos.Profiler.Appender.NHibernate.NHibernateProfiler.RegisterAppenderUsingNHibernateLogger() +314
   HibernatingRhinos.Profiler.Appender.NHibernate.NHibernateProfiler.Initialize(NHibernateAppenderConfiguration configuration) +53
   XXXXX.App_Start.NHibernateProfilerBootstrapper.PreStart() in c:\TeamCity\buildAgent\work\XXXXX\App_Start\NHibernateProfilerBootstrapper.cs:18

[TargetInvocationException: Exception has been thrown by the target of an invocation.]
   System.RuntimeMethodHandle.InvokeMethod(Object target, Object[] arguments, Signature sig, Boolean constructor) +0
   System.Reflection.RuntimeMethodInfo.UnsafeInvokeInternal(Object obj, Object[] parameters, Object[] arguments) +260
   System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture) +146
   System.Reflection.MethodBase.Invoke(Object obj, Object[] parameters) +34
   WebActivator.BaseActivationMethodAttribute.InvokeMethod() +288
   WebActivator.ActivationManager.RunActivationMethods() +698
   WebActivator.ActivationManager.RunPreStartMethods() +46
   WebActivator.ActivationManager.Run() +68

[InvalidOperationException: The pre-application start initialization method Run on type WebActivator.ActivationManager threw an exception with the following error message: Exception has been thrown by the target of an invocation..]
   System.Web.Compilation.BuildManager.InvokePreStartInitMethodsCore(ICollection`1 methods, Func`1 setHostingEnvironmentCultures) +874
   System.Web.Compilation.BuildManager.InvokePreStartInitMethods(ICollection`1 methods) +169
   System.Web.Compilation.BuildManager.CallPreStartInitMethods(String preStartInitListPath, Boolean& isRefAssemblyLoaded) +166
   System.Web.Compilation.BuildManager.ExecutePreAppStart() +176
   System.Web.Hosting.HostingEnvironment.Initialize(ApplicationManager appManager, IApplicationHost appHost, IConfigMapPathFactory configMapPathFactory, HostingEnvironmentParameters hostingParameters, PolicyLevel policyLevel, Exception appDomainCreationException) +882

[HttpException (0x80004005): The pre-application start initialization method Run on type WebActivator.ActivationManager threw an exception with the following error message: Exception has been thrown by the target of an invocation..]
   System.Web.HttpRuntime.FirstRequestInit(HttpContext context) +579
   System.Web.HttpRuntime.EnsureFirstRequestInit(HttpContext context) +112
   System.Web.HttpRuntime.ProcessRequestNotificationPrivate(IIS7WorkerRequest wr, HttpContext context) +716

  


Version Information: Microsoft .NET Framework Version:4.0.30319; ASP.NET Version:4.6.1055.0  

I found this article on stack overflow which helped me to solve the problem. The answer was simply to clear down the %TEMP% folder, which for me was C:\windows\temp. Apparently, if there are more than 65,535 files in there .NET is not able to serve web-pages through IIS. There were hundreds of thousands of files in the folder so I couldn’t even browse to it using Windows Explorer. It ended up being a command prompt job:

File Exists Error Command

Microsoft Windows [Version 6.1.7601]
Copyright (c) 2009 Microsoft Corporation.  All rights reserved.

C:\Windows\system32>cd c:\Windows\Temp

c:\Windows\Temp>del c:\Windows\Temp\*.*
c:\Windows\Temp\*.*, Are you sure (Y/N)? y

That fixed the problem.

Beware! ASP.NET MVC ActionFilterAttributes are cached between requests!

My colleagues and I recently encountered a very strange bug in an ASP.NET MVC web-site which seemed to be to do with NHibernate. The error suggested that we were trying to use a session that had already been closed. We could not find any sign of a closed session anywhere within the controllers in our project. Eventually we pinned the error down to a repository (containing an NHibernate session) referenced in an ActionFilterAttribute. The guy that wrote the code assumed that the repository would be referenced freshly by the attribute each time it was used, but of course it wasn’t; the .NET engine was helpfully caching the attribute between calls so that some users were getting sessions intended for other users.

The moral of the story is to make sure your ActionFilterAttributes are always stateless.

The following simple demonstration highlights this. Here is an ActionFilterAttribute which stores the date and time in a field on construction:

using System;
using System.Web.Mvc;

namespace WebTest.Attributes
{
    public class TestActionFilterAttribute : ActionFilterAttribute
    {
        private readonly DateTime _now;

        public TestActionFilterAttribute()
        {
            _now = DateTime.Now;
        }
        public override void OnActionExecuting(ActionExecutingContext filterContext)
        {
            // Put the date into a ViewBag property:
            filterContext.Controller.ViewBag.DateTime = _now;
        }
    }
}

This is then used in a controller as follows:

using System;
using System.Text;
using System.Web.Mvc;
using WebTest.Attributes;

namespace WebTest.Controllers
{
    public class HomeController : Controller
    {
        [TestActionFilter]
        public ActionResult Index()
        {
            const string dateTimeFormat = "yyyy-MM-dd HH:mm:ss.fffffff";

            var text = new StringBuilder();

            text.AppendFormat("DateTime called directly: {0}<br/>", DateTime.Now.ToString(dateTimeFormat));
            text.AppendFormat("DateTime taken from ActionFilterAttribute: {0}<br/>", ViewBag.DateTime.ToString(dateTimeFormat));

            return Content(text.ToString());
        }
    }
}

If you refresh the page a few times you’ll notice that the time coming from the ViewBag (which originates from the attribute) remains the same while the current time continues to increase, proving that the attribute isn’t being instantiated for each web call. You have been warned!

Using Visual Studio to run web-sites locally using real domains

Visual Studio is great for developing and testing web-sites, but by default it runs them under a localhost address using a randomly generated port number, as given in the property page for the web-site:

Visual Studio Real Domains 01

This is fine, but sometimes it’s useful to have sites run at a location that looks more like a real internet URL, especially if you plan on including functionality that manipulates the URL for redirects etc… I’ve also encountered issues creating cookies using the default http://localhost:xxxx address.

Fortunately, there’s a hosts file trick you can use to make Visual Studio run sites under more realistic URLs. First point 127.0.0.1 at the URL you want to use in your hosts file, for example:

127.0.0.1 www.testing.com

Note though that if the URL you are using points to a real web-site on the internet, you won’t be able to access that site again until you remove the entry from your host file.

Then edit the property pages so that you’re using the Visual Studio Development Server, a specific port (rather than an auto-assigned port) and a custom start URL containing your chosen port number and test URL, for example:

http://www.testing.com:1455

Your property pages should look like this:

Visual Studio Real Domains 02

Then, when you run your web-site using Visual Studio, it will use http://www.testing.com:1455 as the base URL. All paths relative to that should work as expected:

Visual Studio Real Domains 03

Exotic .NET XML configuration file sections

The .NET framework makes application configuration really simple by supplying an out-of-the-box XML configuration file structure and associated classes to access the information contained within it.

By default, it allows configuration key-value pairs to be set and retrieved easily at run time. For example, the following configuration settings:

  <appSettings>
    <add key="ServerName" value="WinDB1"/>
    <add key="DatabaseName" value="MyData"/>
    <add key="EnableFeature" value="true"/>
  </appSettings>

…can be retrieved using:

var appSettingsReader = new AppSettingsReader();

var serverName = (string)appSettingsReader.GetValue("ServerName", typeof(string));
var databaseName = (string)appSettingsReader.GetValue("DatabaseName", typeof(string));
var enableFeature = (bool)appSettingsReader.GetValue("EnableFeature", typeof(bool));

…or (if you add a reference to System.Configuration):

var serverName = ConfigurationManager.AppSettings["ServerName"];
var databaseName = ConfigurationManager.AppSettings["DatabaseName"];
var enableFeature = bool.Parse(ConfigurationManager.AppSettings["EnableFeature"]);

…although as per a past post of mine, Encapsulated and strongly-typed access to .NET configuration files I don’t recommend that you litter your code with references to AppSettingsReader (or ConfigurationManager), but instead that you wrap all configuration up in a class so that settings are encapsulated away.

It is often necessary to hold more complex configurations though. Many developers I’ve worked with have tried to use the key-value model to store such settings, using a single string with various delimiters to hold separate different values. For instance, given a person construct with an ID, title, first name, last name and birth date attributes, some developers would be tempted to do something like this:

  <appSettings>
    <add key="Person1" value="I:1|T:Mr|F:Joe|L:Bloggs|D:1980-01-01"/>
  </appSettings>

…and then use string split functions to populate a Person class when reading information from the configuration file. While this approach works, it results in brittle, hard to read configuration files and complex string logic to take strings apart.

Instead, it is better to use the exotic configuration capabilities included in the framework. Here is an example demonstrating how you might store configuration information to populate the following Person class:

using System;

namespace ConfigurationExample
{
    public class Person
    {
        public int Id { get; set; }
        public string Title { get; set; }
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public DateTime BirthDate { get; set; }
    }
}

The configuration file to store such settings might look like this:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  
  <configSections>
    <section name="people" type="ConfigurationExample.PeopleConfigurationSectionHandler, ConfigurationExample" />
  </configSections>
  
  <people>
    
    <person id="1">
      <title>Mr</title>
      <firstName>Joe</firstName>
      <lastName>Bloggs</lastName>
      <birthDate>
        <year>1980</year>
        <month>1</month>
        <day>1</day>
      </birthDate>
    </person>

    <person id="2">
      <title>Miss</title>
      <firstName>Jane</firstName>
      <lastName>Black</lastName>
      <birthDate>
        <year>1984</year>
        <month>2</month>
        <day>3</day>
      </birthDate>
    </person>
    
  </people>
  
</configuration>

A class implementing IConfigurationSectionHandler must be written to read this exotic configuration file structure; you will need a reference to System.Configuration in order to use this interface. The location of your class is given in the ‘configSections’ declaration at the top of the file. In this case the framework is being instructed to look for a class with name and namespace ‘ConfigurationExample.PeopleConfigurationSectionHandler’ in the ‘ConfigurationExample’ DLL/project in order to read the configuration section named ‘people’.

That class could look something like this:

using System;
using System.Collections.Generic;
using System.Configuration;
using System.Xml;

namespace ConfigurationExample
{
    public class PeopleConfigurationSectionHandler : IConfigurationSectionHandler
    {
        public object Create(object parent, object configContext, XmlNode section)
        {
            var people = new List<Person>();

            foreach (XmlNode node in section.ChildNodes)
            {
                if (node.NodeType == XmlNodeType.Comment)
                {
                    continue;
                }

                var id = GetAttributeInt(node, "id");
                var title = GetChildNodeString(node, "title");
                var firstName = GetChildNodeString(node, "firstName");
                var lastName = GetChildNodeString(node, "lastName");

                var birthDateNode = GetChildNode(node, "birthDate");

                var birthDateYear = GetChildNodeInt(birthDateNode, "year");
                var birthDateMonth = GetChildNodeInt(birthDateNode, "month");
                var birthDateDay = GetChildNodeInt(birthDateNode, "day");

                people.Add(new Person
                {
                    Id = id,
                    Title = title,
                    FirstName = firstName,
                    LastName = lastName,
                    BirthDate = new DateTime(birthDateYear, birthDateMonth, birthDateDay),
                });
            }

            return people;
        }

        private static string GetAttributeString(XmlNode node, string attributeName)
        {
            try
            {
                return node.Attributes[attributeName].Value;
            }
            catch
            {
                var message = string.Format("Could not read attribute named '{0}' in people section of configuration file", attributeName);
                throw new ConfigurationErrorsException(message);
            }
        }

        private static int GetAttributeInt(XmlNode node, string attributeName)
        {
            try
            {
                var value = GetAttributeString(node, attributeName);
                return int.Parse(value);
            }
            catch
            {
                var message = string.Format("Could not convert value stored in attribute named '{0}' to an integer", attributeName);
                throw new ConfigurationErrorsException(message);
            }
        }

        private static XmlNode GetChildNode(XmlNode parentNode, string nodeName)
        {
            try
            {
                return parentNode[nodeName];
            }
            catch
            {
                var message = string.Format("Could not find node named '{0}' in people section of configuration file", nodeName);
                throw new ConfigurationErrorsException(message);
            }
        }

        private static string GetChildNodeString(XmlNode parentNode, string nodeName)
        {
            try
            {
                return parentNode[nodeName].InnerText;
            }
            catch
            {
                var message = string.Format("Could not read node named '{0}' in people section of configuration file", nodeName);
                throw new ConfigurationErrorsException(message);
            }
        }

        private static int GetChildNodeInt(XmlNode parentNode, string nodeName)
        {
            try
            {
                var value = GetChildNodeString(parentNode, nodeName);
                return int.Parse(value);
            }
            catch
            {
                var message = string.Format("Could not convert value stored in node named '{0}' to an integer", nodeName);
                throw new ConfigurationErrorsException(message);
            }
        }
    }
}

Although there is quite a lot of code there, it’s all pretty simple. More importantly, it’s not too brittle and very simple to extend should you wish to add more attributes to the Person class.

The method required by the IConfigurationSectionHandler interface is Create:

public object Create(object parent, object configContext, XmlNode section)

This is what gets called when the framework asks for the contents of the ‘people’ section. The ‘section’ parameter contains the people node from the XML. In essence, the code creates a list in which Person objects are stored, and loops over the child nodes in order to extract the correct information.

There are two important points to note about the code:

1) The code that detects for the presence of XML comments:

if (node.NodeType == XmlNodeType.Comment)
{
    continue;
}

…ensures that developers don’t break the code by adding comments into the XML.

2) All the helper methods in the class (e.g. GetAttributeString, GetChildNodeString, etc…) must expect there to be issues with the XML and throw meaningful, self-explanatory exceptions when things do go wrong. When there are problems with these types of sections it is not always obvious what the problem is from the default exceptions .NET throws (particularly if you’re using this technique in the start up code of a Windows Service) so you will save yourself a lot of head scratching further down the line by writing good error messages. The chances are that you will have more than one section handler in your project so it’s a good idea to encapsulate such helper methods away in an abstract ConfigurationSectionHandler base class to cut down on duplication and to promote reuse.

Assuming you have registered your section handlers correctly in the ‘configSections’ declaration, you can retrieve the Person objects as follows:

var people = (IList<Person>)ConfigurationManager.GetSection("people");

Since the IConfigurationSectionHandler interface uses the ‘object’ type as its return value you need to cast the result to the correct type. It would have been nice if the interface was made generic, but I guess you can’t have everything!

If you’re following the advice in my previous post on configuration encapsulation, you’ll probably want to wrap this call up in your ConfigurationFile class, as follows:

using System.Collections.Generic;
using System.Configuration;

namespace ConfigurationExample
{
    public class ConfigurationFile
    {
        private readonly IList<Person> people;

        public ConfigurationFile()
        {
            people = (IList<Person>)ConfigurationManager.GetSection("people");
        }

        public IList<Person> People
        {
            get
            {
                return people;
            }
        }
    }
}

Note that a reference to the Person list is stored when the class constructs to save the running the cast each time you want to retrieve the contents of the configuration file section.

In summary, it’s a little more work to write exotic configuration file sections, but the advantages over brittle, difficult to extend key-value implementations is certainly worth the extra effort.

NHibernate and log4net

Here’s a quick trick for people using NHibernate and log4net within their .NET applications. (…and if you’re not using NHibernate or log4net, you should seriously think about it!)

Add the following to your log4net configuration to find out what’s going on inside NHibernate:

  <logger name="NHibernate">
    <level value="DEBUG" />
  </logger>
  <logger name="NHibernate.SQL">
    <level value="DEBUG" />
  </logger>

As those kind folks at NHibernate have already set up the loggers behind the scenes, everything just works. The SQL logger is especially useful as it’ll show you explicitly which SQL statements are being generated by NHibernate. You can adjust the levels of NHibernate logging independently of your normal application logging, which is useful as the NHibernate logs tend to be pretty verbose.

The full configuration will look something like this:

<log4net>
  <appender name="TraceAppender" type="log4net.Appender.TraceAppender" >
    <layout type="log4net.Layout.PatternLayout">
      <param name="ConversionPattern" value="%d %-5p- %m%n" />
    </layout>
  </appender>
  <appender name="RollingFileAppender" type="log4net.Appender.RollingFileAppender">
    <file value="Application.log"/>
    <appendToFile value="true"/>
    <rollingStyle value="Date"/>
    <datePattern value="yyyy-MM-dd'.log'"/>
    <layout type="log4net.Layout.PatternLayout">
      <conversionPattern value="%date [%thread] %-5level %logger [%property{NDC}] - %message%newline"/>
    </layout>
  </appender>
  <root>
    <level value="DEBUG"/>
    <appender-ref ref="TraceAppender"/>
    <appender-ref ref="RollingFileAppender"/>
  </root>
  <logger name="NHibernate">
    <level value="ERROR" />
  </logger>
  <logger name="NHibernate.SQL">
    <level value="ERROR" />
  </logger>
</log4net>

Changing the default naming convention for foriegn keys when using Fluent NHibernate

By default, NHibernate will assume that foreign keys should be named using the convention ReferencedTableName_id (e.g. Person_id). I personally don’t like this conversion and would prefer ReferencedTableNameId (e.g. PersonId).

Fortunately, this is pretty easy to achieve by extending the ForeignKeyConvention class in Fluent NHibernate:

using System;
using FluentNHibernate;
using FluentNHibernate.Conventions;

namespace NHibernate.Helpers.Conventions
{
    public class CustomForeignKeyConvention : ForeignKeyConvention
    {
        protected override string GetKeyName(Member property, System.Type type)
        {
            if (property != null)
            {
                return property.Name + "Id";
            }

            if (type != null)
            {
                return type.Name + "Id";
            }

            // If both are null, we throw an exception:
            throw new ArgumentNullException("property", "The property and type parameters cannot both be null");
        }
    }
}

This needs to be wired into your SessionFactory creation code as follows:

sessionFactory = Fluently.Configure()
    .Database(DatabaseConfiguration)
    .Mappings(x => x.FluentMappings.AddFromAssembly(MappingsAssembly))
    .Mappings(x => x.FluentMappings.Conventions.Add(new CustomForeignKeyConvention()))
    .ExposeConfiguration(x => new SchemaUpdate(x).Execute(false, true))
    .BuildSessionFactory();

Note that the example above will also update the database schema.

Once you’ve done that, all foreign keys will use the desired naming convention.

Prevent malicious image uploads

If you allow users to upload images to your site, you may be opening up your site to malicious use. This is because particularly cunning hackers can hide commands to do just about anything in the data that makes up the image.

For a great example of an infected image file, see the following page:

http://www.eicar.org/86-0-Intended-use.html

Note that you’ll need to disable your anti-virus if you want to create this file on your computer.

If you allow users to upload this file, it will produce some interesting results!

To prevent the vulnerability (at least when using C#) you simply need to try and load the image data into an Image object. This will throw an exception if the image contains anything nasty. Here is an example:

var image = Image.FromStream(imageDataStream);
using (var memoryStream = new MemoryStream())
{
    image.Save(memoryStream, ImageFormat.Png);
}

Note that you’ll need to load the uploaded data into a stream (imageDataStream in the example above) to get this to work.

Using the Return key with Back and Next buttons on web-sites

When it boils down to it, most sites on the web are just gloried data crunchers. Users enter information, which the system churns up and splits out again at some point in the future, potentially to a different user.

If a site requires a lot of information, it is common to see multistage wizards, with each stage asking for a small portion of the information. Each stage usually has a Back button and a Next button. Convention and common sense dictate that the Back button should be on the left, and the Next button on the right as in the following example:

Type something here:
… and here:

NB: The onclick events return false to prevent the page from actually submitting.

This all seems to works fantastically, and even uses tabindex to ensure that the user tabs onto the Next button before the Back button… until someone comes along that prefers to use the Return key to submit the form, instead of using the mouse or tabbing to the Next button. In this case, the Return key will call the first submit button it can find, which in this case is the Back button. This is not the expected behaviour! Put the cursor in one of the input fields and click Return to see this in action.

One solution to correct this would be to use floats and/or JavaScript to try and reverse the order the buttons are displayed in while still having the Next button placed highest in the HTML to ensure that it would respond to the Return key. However, if a user disables CSS and/or JavaScript this solution will fail. A simpler option is to create a hidden submit button as the first element within the form, which performs the desired Return key operation. The order of any other (visible) buttons on the form is then irrelevant.

The following form demonstrates this:

Type something here:
… and here:

Again, put the cursor in one of the input fields and click Return to see this in action. The only downside to this is that the user will see another submit button if they disable CSS, but in most cases I think it is still the best solution.

Simple trick to help prevent click-jacking

Click-jacking is a technique used by hackers to get you to interact with websites without your consent or knowledge. An example would be to get you to click a Like button on a Facebook page without you realising it. The trick with click-jacking is misdirection. One way to achieve this is to show you a friendly looking site, preferably a site which you are already familiar with, but where the buttons perform actions other than those you expect. This can be achieved by hosting the friendly site in an iframe, with fake buttons floated over the top of the real buttons. These fake buttons can then perform unintended actions, such as submitting a Like to Facebook.

You can test whether your website is vulnerable using the following HTML snippet:

<html>
<head>
<title>Clickjack test page</title>
</head>
<body>
<p>Website is vulnerable to clickjacking!</p>
<iframe src="http://www.mywebsite.com" width="1000" height="1000"></iframe>
</body>
</html>

If you can see the text Website is vulnerable to clickjacking! when you look at the code in a browser your site could be used as a target for click-jacking.

A simple way to prevent this kind of attack is to include the following JavaScript at the top of your site:

<script type="text/javascript">
// Prevent the page from being vulnerable to click jacking
if (self == top) {
var theBody = document.getElementsByTagName('body')[0];
theBody.style.display = "block";
} else {
top.location = self.location;
}
</script>

The JavaScript checks to see if the containing page is the top-most entity in the HTML served to the user. If not, then the whole browser is re-directed to the address of the containing page, thus removing the iframe.

Obviously this won’t work if users don’t have JavaScript enabled, but for the sake of a few lines of trivial JavaScript it’s worth adding this to your site.

Ignore SSL errors when calling web-services in C#

Often when developing .NET systems that call secure web-services, I find myself running code against development and test servers with invalid SSL certificates. This causes service calls to fail and prevents me from making progress. To get round this potential blocker, I include the following snippet somewhere in the code before the service call is made:

ServicePointManager.ServerCertificateValidationCallback = delegate { return true; };

This code only needs to appear once, and it is not good practice to leave it in production code as it means that data sent over HTTPS isn’t actually secure. Consider making the inclusion of this code configurable, or wrap it up in #DEBUG statements so that it is not compiled into production code.