Testing ConfigurationSection

Creating ConfigurationSections can be tricky but it’s quite straightforward to test them, provided you take care and don’t try to do too much like this subtle bug in MvcContrib.IncludeHandling that lead me crazy for a couple of hours.

The thing is that the code does like this:

public IncludeHandlingSectionHandler()
{
    _types = new Dictionary<IncludeType, IIncludeTypeSettings>
    {
        { IncludeType.Css, Css },
        { IncludeType.Js, Js }
    };
}

Where this is the constructor and .Css and .Js properties are marked with [ConfigurationProperty], so in theory seems correct.

In the tests, there’s an XML file with the section and it’s loaded using the DeserializeSection method of the ConfigurationSection base class. And this seems correct, everything goes ok and the dictionary is populated correctly with the data from the XML file.

But it’s wrong. If you add the section to the app.config (or web.config) file and instead of using DeserializeSection you use ConfigurationManager.GetSection(sectionName), the constructor is called before populating the Css and Js properties so the dictionary is not created properly but as those properties return a default implementation in case there’s no configuration, it seems to work, but the configured values are never loaded.

This way, tests pass but it’s impossible to configure the library via web.config. Anyway, in my opinion the problem is in .NET Framework because internally, GetSection should use DeserializeSection to be consistent.

Get MAC from IP address in .NET

After dealing with several options, most of them involving a call to a command line tool and parsing the output, which is not really elegant. Other solutions were based on obsolete VBScript client code and ActiveX, even worse.

Finally I found in the excellent pinvoke.net site a very nice and simple example using a simple call to iphlpapi.dll’s SendARP method. The trick was to use ARP to get the MAC from the IP.

Note that this has it’s limitations, as I will only work if the remote machine is in the same network and the packet does not need to go through a router. I was enough for our needs.

Here’s the code I adapted from the example:

public static string GetMAC(IPAddress ipAddr)
{
var mac = new byte[6];
var len = (uint)mac.Length;

var result = SendARP((int)ipAddr.Address, 0, mac, ref len);

if (result != 0)
{
return "MAC not found!";
}

var str = new string[(int)len];

for (var i = 0; i &lt; len; i++)
{
str[i] = mac[i].ToString("x2");
}

return string.Join(":", str);
}

[DllImport("iphlpapi.dll", ExactSpelling = true)]
private static extern int SendARP(int destIP, int srcIP, byte[] pMacAddr, ref uint phyAddrLen);

Enjoy!

NHibernate: Custom type is not serializable

Since I acquired a NHibernateProfiler license, an initialization warning message draw my attention, the text seemed quite easy to solve:

WARN: custom type is not Serializable: MyLibrary.MyCustomDataType

My first solution was adding [Serializable] attribute to the custom type, but that didn’t make the trick. As it was only a warning, I did not investigate further at that moment.
But the other day, debugging data access code I saw the warning again and the easiest solution was going to the source NHibernate code to find this:
TypeFactory.InjectParameters(userType, parameters);
if (!userType.ReturnedClass.IsSerializable)
{
LogManager.GetLogger(typeof(CustomType)).Warn("custom type is not Serializable: " + userTypeClass);
}
As seen in this code, the message is unclear, because the class that must be serializable is the ReturnedClass, not the custom UserType itself.
So, to solve the warning I just needed to add [Serializable] to the class returned by my custom UserType instead than the type itself.