Este ejemplo consta de una sola página .asmx y, aunque no es lo recomendado, debo admitir que hay veces en las que me gusta que toda la solución pueda ser fácilmente portada copiando un solo archivo.
Con todas estas salvedades, pasemos a la receta.
Ingredientes
- Una base de datos de IP. Recomiendo la de MaxMind - GeoLite Country / Open Source IP Address to Country Database. Para este ejemplo elegimos la versión gratuita.
- Una base de datos de una sola tabla. Para este ejemplo elegimos Microsoft Access para hacer el ejemplo más sencillo y transportable.
- Una Regular Expression para validar IPs.
- Un algoritmo para convertir un string IP en un double.
Preparación
1.- Nos bajamos la base gratuita de IPs desde la página de MaxMind (para una solución comercial deberíamos adquirir la versión full) desde haciendo “clic aquí”.
2.- Creamos una nueva base de datos Access y creamos una tabla que llamaremos “IPSegments”. Esta tabla deberá contener los siguientes campos (si respetamos el orden será luego más fácil importar la base).
- beginIP – Text
- endIp – Text
- beginNro – Numbrer (double)
- endNro – Numbrer (double)
- CountryCode – Text
- ContryName - Text
4.- Creamos nuestro archivo .asmx.
Luego de la declaración de WebService nos aseguramos de incluir las siguientes líneas “using”:
using System.Data;
using System.Data.OleDb;
using System.Text.RegularExpressions;
El único método web será algo así:
[WebMethod]
public string GetCountryCode(string ip) {
return GetCountryByIp(ip);
}
El primer método privado será el validador de IPs. Lo podemos resolver de forma elegante con una Regular Expression.
private bool IsValidIp(string ip) {
string pattern = @"^([1-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])(\.([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])){3}$";
Regex reg = new Regex(pattern, RegexOptions.Singleline | RegexOptions.ExplicitCapture);
return reg.IsMatch(ip);
}
Luego necesitamos el algoritmo para convertir una IP en un double
private double Ip2Double(string ip) {
string[] octetos = ip.Split('.');
int w = int.Parse(octetos[0]);
int x = int.Parse(octetos[1]);
int y = int.Parse(octetos[2]);
int z = int.Parse(octetos[3]);
double result = 16777216 * (double)w + 65536 * (double)x + 256 * (double)y + (double)z;
return result;
}
Finalmente creamos el método que busca el país en la base de datos
private string GetCountryByIp(string ip) {
if (!IsValidIp(ip)) throw new Exception("Invalid IP format");
object result;
double ipNum = Ip2Double(ip);
string connectionString = "Provider=Microsoft.Jet.OLEDB.4.0; Ole DB Services=-4; Data Source=";
connectionString += System.Web.HttpContext.Current.Server.MapPath("GeoIPCountry.mdb");
OleDbConnection oConn = new OleDbConnection(connectionString);
string query = "SELECT CountryCode FROM IPSegments WHERE @IpNum BETWEEN beginNro AND endNro";
OleDbCommand dbCommand = new OleDbCommand(query, oConn);
dbCommand.Parameters.Add("@IpNum", DbType.Double).Value = ipNum;
oConn.Open();
try {
result = dbCommand.ExecuteScalar();
} finally {
oConn.Close();
}
if (result == null) throw new Exception("IP not in Database, maybe is a local IP");
return result.ToString();
}
En este link tienen el “plato terminado”: GeoIP WebService con ASP.NET y C#. Pueden copiarlo en una instancia de IIS configurada para ejecutar ASP.NET (funciona en todas las versiones) y probarlo. Sin embargo les recomiendo hacer sus propias implementaciones tomando este ejemplo solo como una especie de “starter kit”.
2 comentarios:
Muy interesante articulo, pero yo intente ejecutar este proyecto, coloque los archivos que me descargue (la base y el web service) dentro de una carpeta llamada GeoIPCountry en el wwwroot la cree en el IIS abri el proyecto con visual studio 2005 lo ejecute y me sale
"You are not authorized to view this page
You might not have permission to view this directory or page using the credentials you supplied. "
Por favor yo de verad necesito ese servicio de reconocer el país ayudeme a ejecutarlo correctamente. gracias.
Anónimo: el mensaje de error denota un problema de permisos entre Windows y IIS. Aparentemente no tiene nada que ver con el código que te descargaste. Asegurate de que todos los archivos están con los permisos adecuados.
Publicar un comentario