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!

ASP.NET MVC and ReturnUrl

I’ve seen many ASP.NET MVC samples and some of them do not honor de ReturnUrl parameter, rendering this unusable.

Classic ASP.NET has the login form component that puts the same exact URL used to access the login page in the form action URL, preserving the ReturnUrl parameter and then, FormsAuthentication.GetReturnUrl() gets it from the Request.QueryString collection.

Fortunately, the GetReturnUrl() method looks as well in Request.Form in case there’s nothing in the query, this way, we can use a hidden field as well to store the ReturnUrl in the View and pass it through POST when the login form is submitted.

So, in ASP.NET MVC we have two options:

  1. Use simply Html.BeginForm() without parameters, which will put a simple form tag, with the same URL as the current one and use POST by default
  2. If we want to have more control on the Html.BeginForm(), put a hidden field with the value of the ReturnUrl, only if the ReturnUrl is not empty, or it will fail. This can be obtained from the Request.QueryString collection, the ViewData if we put it previously on the Controller action or even better store it in the ViewModel and have a strong typed reference.

And that’s it. Then, FormsAuthentication.GetReturnUrl() will get the proper URL and other methods like FormsAuthentication.RedirectFromLoginPage() will also work seamlessly.

Principios básicos de OOP: SOLID

Últimamente reviso mucho código, tanto mío como de otros y me doy cuenta de que muchas veces se pasan por alto los principios básicos del paradigma de orientación a objetos y en muchos casos porque la formación es deficiente o inexistente.
Así pues, uno de los acrónimos en el mundillo de la programación orientada a objetos (OOP) es SOLID, que sirve de regla mnemotécnica para recordar 5 principios básicos:

SRP: Single Responsibility Principle:
El principio de responsabilidad única nos dice que nunca debe haber más de un motivo para que una clase cambie, o lo que es lo mismo, que una clase solamente debe tener un propósito. Esto parece simple pero en realidad es uno de los principios más fáciles de violar y muchas veces no es fácil distinguir las responsabilidades.

OCP: Open-Closed Principle:
El principio abierto/cerrado implica que las clases de software deben estar abiertas para la extensión pero cerradas para la modificación. Este es el principio por el cual se hacen privadas las variables del miembro o que no se usan variables globales. El truco de este principio está en la abstracción. Las clases abstractas implementan un código inalterable desde fuera pero obligan a extender de ellas para usar este código a parte de que se promueve la reusabilidad.

LSP: Liskov Substitution Principle:
El principio de sustitución de Liskov implica que las clases derivadas deberían poder ser sustituidas por sus clases base. Es decir, es en cierto modo una extensión del principio anterior: mientras que OCP promueve la herencia de clases base, LSP promueve que la herencia se haga de forma transparente, es decir, que heredar es bueno pero no hay que olvidar las raíces. Es decir, no implementemos un método en una clase heredada que no esté en la clase base porque romperemos este principio.

De OCP y LSP se deduce que las clases base (abstractas o no) modelan el aspecto general y las clases heredadas modelan el comportamiento local.

DIP: Dependency Inversion Principle:
Básicamente, el principio de inversión de dependencia promueve que hay que depender de abstracciones, no de concreciones. Dicho de forma más compleja, los módulos de más alto nivel no deben depender de los de más bajo nivel sino que ambos deben depender de abstracciones. Y a su vez, las abstracciones no deben depender de los detalles sino al contrario.

En este caso, el uso de interfaces resulta muy beneficioso y un framework de inversión de control (Castle Windsor, StructureMap, por citar algunos) van a hacer que resulte más obvia la necesidad de abstracciones. Además, el testado unitario resulta mucho más sencillo ya que la independencia entre los distintos módulos es muy elevada.

ISP: Interface Segregation Principle:
Este principio de segregación de interfaces indica que no se debe hacer depender las clases de interfaces que no necesitan y que debe haber granularidad en las interfaces para dotar de aspectos específicos a las distintas implementaciones.

En general, en Java y C# se pueden implementar tantos interfaces como se quiera por lo que es sencillo llevar a cabo este principio. Las interfaces son la forma más práctica de modelar las clases y dotarlas de aspectos particulares así como incluso tratarlas de diferente modo según las interfaces implementadas.

Y estos son básicamente los principios SOLID que aunque llevan ya muchos años siguen siendo vigentes y ayudan a desarrollar un código más reusable, mantenible y claro. Además, con las herramientas actuales de refactorización es muy fácil extraer interfaces y clases abstractas de las ya existentes sin tener que revisar cientos de líneas de código. Y cómo no, tener un buen conjunto de tests unitarios ayudará a que cualquier refactorización se haga sin miedo a romper toda la funcionalidad existente.

Referencias: Principles of OOD