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 < 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.

Getting MIME type in .NET from file extension

After some research, I posted a question at stackoverflow.com without much success, but the problem was that the answer was already there.
I you are working on any application that needs to serve files on it’s own, for example for encrypted storage or a rich ACL that needs to be enforced, you will need to provide the most correct Content-Type possible or MIME type from a given file extension to the reponse in order to achieve the best user experience.
For example, if you serve a PDF and use a generic MIME like application/octet-stream, the user may not se a PDF reader to open it, depending on the browser and platform.
Then, in .NET there are 4 alternatives to do this, with their pros and their cons:

  1. Use the Windows registry – This may be a good solution for desktop applications but depends on the software installed on the machine and typically web servers don’t have Acrobat or Office.
  2. Use urlmon.dll’s FindMimeFromData – I don’t know exactly the efectiveness of this method, but it’s used internally by Windows. It should give good and reliable information but you have to read the file and give the method up to 256 bytes of the file header.
  3. Use IIS information – Maybe the most obscure mechanism, based on Directory Services and COM stuff. It’s based on the same mechanism IIS uses, so it should be quite reliable, but complex and may not be the fastest.
  4. Use your own dictionary – Maybe not the most elegant but even .NET uses this internally (see System.Web.MimeMapping… you know how). You get a bunch of types from somewhere and add them to a dictionary with the associated extension. Easy.

So, the optiones are clear. Finally in my case, I used a simple dictionary to ensure compatibility between platforms and homogeneity. Using other mechanisms could lead to strange errors on some platforms that I wanted to avoid over other benefits. But there are much more elaborate mechanisms that can be done.