Pues eso, que desde que cambié el alojamiento de «mi sitio», elguille.info, de Axarnet/Domitienda a acens (de telefónica) los enlaces que tenía «incrustados» en las páginas (para que mostrase en una página de mi sitio el artículo de mi blog (este) no se mostraban a causa de un error que mostraba este texto: The request was aborted: Could not create SSL/TLS secure channel La solución ha sido fácil (después de haber buscado en la red sobre este error) y que he he econtrado en StackOverflow, concretamente en un comentario a una de las respuestas, no puedo poner el enlace a ese comentario, pero es el que tiene este texto: You don’t need to exclusively set it to a single type, you can simply append as well. System.Net.ServicePointManager.SecurityProtocol |= System.Net.SecurityProtocolType.Tls12; – Nae Mar 20 ’18 at 8:44
Ese código es para C#, en Visual Basic sería este:
System.Net.ServicePointManager.SecurityProtocol =
System.Net.ServicePointManager.SecurityProtocol Or System.Net.SecurityProtocolType.Tls12
Lo que tengo que hacer ahora es ver si ese código simplemente lo puedo poner en la página maestra o tendré que ponerlo en cada página… creo que si se ejecuta una sola vez es suficiente, así que… si ves que da nuevamente ese error, te ruego que me lo digas. Gracias.
Pues eso… aquí tienes un ejemplo que son 2 (o cuatro si tenemos en cuenta que el código que te voy a mostrar es tanto para Visual Basic como para C#/CSharp) y es para obtener las IPs del usuario (o donde se ejecute el código) y de esas IPs (que contendrá las IPv6 y las IPv4) extraer solo las IPv4.
Este código utiliza expresiones regulares (RegEx) y por tanto necesitas añadir una importación del espacio de nombres System.Text.RegularExpressions, también utiliza métodos para acceder al nombre del equipo (host name) y obtener las direcciones IP, por tanto, necesitarás una importación al espacio de nombres System.Net.
Este código sirve tanto para aplicaciones de escritorio (los ejemplos están hechos para aplicaciones de consola para todas las plataformas), aplicaciones móviles y aplicaciones WEB.
Yo lo he probado en las dos primeras, y cuando lo haga en la tercera, te mostraré el código usado (o lo pondré en el repositorio de GitHub que crearé para poner el código de ejemplo) y las cosas que debas tener en cuenta, siempre y cuando tengas algo que tener en cuenta 😉
Nota 01-sep-2021: Ya he publicado una página ASPX (asp-net) para probar el código. Para esa página he creado una DLL con idea de ponerla en el directorio BIN del hosting donde tengo alojado «mi sitio» www.elguille.info. En GitHub también está el código de esa DLL (del proyecto, que en este caso lo he creado con VB). Este es el enlace de la página de prueba: ComoNET: Utils IP (.NET Core) (elguille.info)
Nota: Las dos funciones principales: la que obtiene las IPs y la otra que extrae las IPv4 de esas IPs están en una clase estática (compartida sería en VB, pero en este caso no es necesario indicar Shared) con métodos estáticos (así debe ser en C#), esos métodos en Visual Basic están declarados con Shared, mientras que en C# se utiliza static.
En realidad, en Visual Basic podría haber usado un módulo (Module) en vez de una clase y definir expresamente los métodos de forma compartida, pero la diferencia de declarar los métodos como compartidos en una clase y usar esos métodos desde un módulo es que «tras las bambalinas» hay más código si se define un módulo. Me refiero al código IL generado, aunque en realidad solo hay más código en el constructor del módulo, ya que el código IL de los métodos es el mismo en ambos casos. Después te pongo algo sobre esto (seguramente en otro post).
Otro detalle es que en la medida de lo posible he usado declaraciones de variables explícitas en lugar de usar inferencia de tipos, para que así te resulte más fácil ver (o saber) de qué tipo de datos estoy hablando (o utilizando).
Obtener las direcciones IP del usuario actual
En esta primera parte del ejemplo, echaremos mano de los métodos GetHostName y GetHostAddresses de la clase Dns definida en System.Net.
El nombre del host es necesario para saber las IPs, ya que GetHostAddresses utiliza el nombre del host (¿anfitrión?), pero mejor ve el código y después ya veremos si hay algo que aclarar.
Empiezo con el de C# y después te muestro el de Visual Basic.
PublicSharedFunction ObtenerIPs()
Dim sb AsNewStringBuilder()
Dim ipAddresses AsString
Try
Dim hostName = Dns.GetHostName()
Dim addresses AsIPAddress() = Dns.GetHostAddresses(hostName)
ForEach address AsIPAddressIn addresses
sb.Append($"{address}, ")
Next
ipAddresses = sb.ToString().TrimEnd(", ".ToCharArray())
Catch ex AsException
ipAddresses = "ERROR: " & ex.Message
EndTry
Return ipAddresses
EndFunction
Un par de cosas (tips) a destacar de ese código: 1- La variable addresses es un array del tipo IPAddress, para obtener cada una de las direcciones IP utilizo un bucle foreach (For Each) y las agrego al StringBuilder (por aquello de que consume menos recursos que si las concateno). 2- Como le voy añadiendo a cada IP una coma y un espacio al final (para separarlas), es necesario quitar esa coma del final, para ello utilizo TrimEnd() indicándole qué caracteres quiero quitar del final. Los caracteres indicados al método de la familia Trim deben ser caracteres, no una cadena, por eso utilizo una cadena con los caracteres a quitar del final y la convierto en array de tipo Char con ToCharArray.
Extraer las IPv4 de una cadena con otras cosas usando expresiones regulares
En el método que se encarga de hacer eso, utilizo la clase RegEx para mediante una cadena con «expresiones regulares» (que resultan ser buenas y no regulares 😉 ) y los casos en que ha tenido éxito, los voy agregando a un StringBuilder que después usaré (tras quitar lo que no haya que usar) para devolver como resultado de las direcciones IPv4 de esa cadena entrante.
Aquí tienes el código de ese método para Visual Basic y C#.
PublicSharedFunction LasIPv4(ipAdresses AsString) AsString
Dim sb AsNewStringBuilder()
Dim sRegExIPv4 AsString = "((25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(25[0-5]|2[0-4]\d|[01]?\d\d?)"
Dim r AsRegex = NewRegex(sRegExIPv4)
ForEach m AsMatchIn r.Matches(ipAdresses)
If m.Success Then
sb.Append($"{m.Value}, ")
EndIf
Next
Return sb.ToString().TrimEnd(", ".ToCharArray())
EndFunction
Y esto es todo… ¡Ah! ¡No! que falta el código de cómo usar estos dos métodos.
Cómo usar los métodos anteriores
Eso está en el método Main del «programa» de consola.
Aquí tienes el método Main que los utiliza.
staticvoid Main(string[] args)
{
//Console.WriteLine("Hello World!");
Console.WriteLine("Ejemplo en C# usando .NET 5.0 para obtener las IPs y extraer con RegEx solo las IPv4.");
Console.WriteLine();
string ipAdresses = Utils.ObtenerIPs();
Console.WriteLine("La cadena con todas las IPs:");
Console.WriteLine(ipAdresses);
string ret = Utils.LasIPv4(ipAdresses);
Console.WriteLine();
Console.WriteLine("Direcciones IPv4:");
Console.WriteLine(ret);
Console.WriteLine();
Console.WriteLine("Pulsa INTRO para terminar.");
Console.ReadLine();
}
Sub Main(args AsString())
'Console.WriteLine("Hello World!")
Console.WriteLine("Ejemplo en Visual Basic usando .NET 5.0 para obtener las IPs y extraer con RegEx solo las IPv4.")
Console.WriteLine()
Dim ipAdresses AsString = Utils.ObtenerIPs()
Console.WriteLine("La cadena con todas las IPs:")
Console.WriteLine(ipAdresses)
Dim ret AsString = Utils.LasIPv4(ipAdresses)
Console.WriteLine()
Console.WriteLine("Direcciones IPv4:")
Console.WriteLine(ret)
Console.WriteLine()
Console.WriteLine("Pulsa INTRO para terminar.")
Console.ReadLine()
EndSub
Aquí te dejo una captura del programa en ejecución.
Pues eso… con el título de este post: Cómo refrescar los datos en aplicaciones de Xamarin.Forms o .NET MAUI, aparte de referirme que es para apliciones multiplataforma/multidispositivos creadas con Xamarin.Forms o .NET MAUI, me refiero a esos casos en los que quiero que se muestre un mensaje (por ejemplo en el texto de una etiqueta) mientras la aplicación hace cosas que pueden tardar un poco, como leer los datos de una base de datos o contar hasta cientocuincuentamilmillonesdetrillones, por decirte algo 😉
En .NET Framework / aplicaciones de Windows.Forms, yo suelo usar el fatídico (para algunos) Application.DoEvents(), que sí, que dicen que usando el Thread.Sleep se supone que hace lo mismo, pero yo te digo que no, a mí no me ha funcionado nunca.
Con la aplicación mobile en la que estoy enfrascado desde hace ya unos 3 meses, intenté el Sleep, intenté crear/usar un temporizador (otra de las formas en que hago con .NET Framework esa pequeña pausa para refrescar), pero nada de nada… Probé haciendo los métodos asíncronos para que fuesen «agüeitable» (async y await), pero nada de nada…
Sin embargo ayer, buscando en la red de redes (Inernet por si no sabías que así se le llama algunas veces), me encontré con una consulta en la que respondían eso que tanto estaba buscando saber cómo hacer, y la respuesta la encontré, (casi como de costumbre), en stackoverflow, concretamente aquí.
Y es usando Task.Delay(...) a la que tenemos que indicar los milisegundos de espera. En esa respuesta indican dos formas de hacerlo: de forma asíncrona y de forma síncrona, decirte que la que a mí me ha funcionado es la asíncrona, la otra, como si miraras al cielo esperando ver pasar un elefante rosa… por decir algo… Vamos, que ni de coña esperaba…
Y como he visto que funcionaba, me he creado un método compartido en la clase App para que me sea fácil usarla desde cualquier parte de la aplicación, a ese método lo he llamdo Refrescar y recibe un parámetro con los milisegundos que quieres esperar antes de seguir, yo suelo usar el valor 300, que es el que casi siempre uso en los temporizadores que pongo en las aplicaciones de escritorio creadas con .NET Framework. Este es el código de ese método (en C# ya que por ahora las aplicaciones de Xamarin.Forms / .NET MAUI son (y segurián siendo solo) para el cochambros lenguaje ese de los puntos y comas.
Y si te ha molestado que diga cochambroso lenguaje, de verdad que lo siento, pero… es lo que me parece a mí, al menos en la forma que yo lo uso, es una pequeña caca comparado con Visual Basic. Ya sabes: cochambros es lleno de mugre o cochambre que viene de cocho, puerco… ¡UF! me vas a odiar como seas fanático del C#, pero es lo que hay, es mi opinión, pero con fundamentos.
El código
Bueno, a lo que vamos, este es el código:
///<summary>
/// Hacer una pequeña pausa para refrescar.
///</summary>
///<paramname="intervalo">El tiempo que hay que esperar (en milisegundos).</param>
asyncpublicstaticTask Refrescar(int intervalo = 300)
{
awaitTask.Delay(intervalo);
}
El valor predeterminado es de 300 milisegundos, es decir, menos de un tercio de segundo, incluso con 100 iría bien, pero…
Cómo lo utilizo
En uno de los casos, tengo una etiqueta en la que muestro el total de datos que leo de la base de datos, mientras se hace la búsqueda muestro un mensaje diciendo algo como: Leyendo los datos…, hago la pausa, (se refreca el contenido de la etiqueta) y mientras llamo al método que lee los datos, en el que actualizo esa etiqueta con los datos mostrados, etc.
LabelInfoReservas.Text = $"Leyendo las reservas de '{ElCliente.Nombre}'...";
// refrescar...
//await Task.Delay(300);
awaitApp.Refrescar();
await asignarLasReservas();
En la siguiente captura, puedes verlo (me ha dado tiempo a hacerla a pesar de que había pocos datos que leer porque, esa es la impresión que a mí me da, las aplicaciones para Windows-UWP de Xamari.Forms / .NET MAUI son algo lentas… en ocasiones muuuucho más lentas que las aplicaciones para escritorio hechas con .NET Framework 4.8. Tanto que esta app móvil no podremos usarla al 100% en la playa porque hay poca cobertura móvil (de datos) que ya se hace insufrible utilizarla, y en este caso no creo que sea porque está hecha con C# 😉
Captura de la app con el mensaje mientras lee los datos de la base de datos.
Y ya está… eso es todo, simple, ¿verdad? pues… sí… 😉