Screenshot y Share con Net MAUI

Estamos a full con el nuevo framework de Microsoft, y en esta oportunidad te enseñamos a capturar la pantalla y activar el menú de compartir.

La ventaja de Net MAUI ( al igual que con Xamarin) es que es multiplaforma y nativo.

¿Esto que significa? Que desde unas pocas líneas podremos acceder a las funciones nativas de la plataforma en donde se esté ejecutando, y para nosotros será indiferente.

En este caso vamos a dividir esta situación en dos partes:

  1. Screenshot ( captura de pantalla)

Gracias a la interface IScreenShot podremos capturar la pantalla actual en la que nos encontremos. Esto funcionará para cualquiera de las plataformas disponibles por Net MAUI

Screenshot – .NET MAUI | Microsoft Learn

El resultado de la misma será en un conjunto de bytes (Stream), disponibles para nuestro siguiente paso

2. Guardar el archivo

Para ello haremos uso de la clase histórica de .NET llamada System.IO

System.IO Namespace | Microsoft Learn

  • 3. Activar el menú compartir

Ya teniendo nuestra captura convertida a un archivo procedemos a pasarselo a la clase encargarda de las funciones de “compartir”

Share – .NET MAUI | Microsoft Learn

Como siempre, te dejo un video con todos los pasos bien explicado y acceso al código. Recuerda dejar tu like y tu comentario. Nos vemos…

Agrega publicidad a tu aplicación

Con la nueva versión de Microsoft para el desarrollo de aplicaciones nativas móviles ya en producción, ha nacido un nuevo boom. Anteriormente te contamos sobre Net MAUI: el Framework de .NET para el crear aplicaciones para diferentes plataformas, entre ellas iOs y Android.

Parecía que Xamarin era la única opción disponible, pero un poco olvidada en el tiempo, sin embargo con la llegada de Net 5, trajo consigo esta ansiada evolución: Net MAUI.

El día de hoy con muchos de sus bugs púlidos, y con muchos de los plugins originarios de Xamarin, ya migrados a este nuevo framework, empezamos a hilar finos para empezar a crear aplicaciones aptas para producción y de indole comercial.

Una de esas características es poder monetizar tu aplicación a través de una cuenta de Google Adsense.

Hoy te contaré los pasos necesarios para poder lograrlo y no morir en el intento.

  • 1- Publica tu aplicación en tu tienda oficial

Es necesario que la aplicación esta subida a PlayStore (Android) o AppStore (iOs)

  • 2- Crear tu cuenta en google AdMob

https://admob.google.com/

Está plataforma integrará tu cuenta de Google Adsense y Google Analitycs en una sola. Te permitirá crear tus banners y los diferentes tipos de productos disponibles para monetizar a través de la publicidad

Te permitirá buscar tu aplicación desde las tiendas oficiales

  • 3- Instala en tu proyecto el nuget
dotnet add package Plugin.MauiMTAdmob

Los siguientes pasos consiste en crear directamente sobre tu vista, el yaml correspondiente al control equivalente a tu banner. A continuación te dejo el video del proceso completo.

No te olvides de comentar y dejar tu like!!!

Agrega Google Adsense en Net MAUI

NET MAUI – 2022 Enero

Este versión está disponible para NET 6, y es el framework para desarrollar aplicaciones multiplataforma. Es parte de dotnet, está disponible en NET 6,0 o NET 7.0 en adelante.

Con el podemos desarrollar aplicaciones nativas para MacOS, iOs, Android y Windows. Si te suena esto, es porque anteriormente teníamos a Xamarín con Xamarín Forms. Con el lanzamiento de Net 6.0, y bajo los nuevos lineamientos que apunta .NET a convertir en el framework multiplataforma mas usado por tener aplicaciones completas y veloces, es que decide evolucionar su herramienta (Xamarin) hacía un nuevo producto: NET MAUI. En el incluirá todo lo aprendido hasta el momento con su framework de NET (microservicios, serverless, opensource, multiplataforma, etc).

Lo primero que debes saber es que está en una versión preview, y solo está disponible por el canal de Visual Studio 2022 preview (en cualquier versión). Pero para el Q1 del 2022 ya tendremos un versión candidad. Y en el Q2 del 2022, ya una versión definitiva.

Lo que no está claro si está en Net 6.0, o será ya parte de Net 7.0 (Nov 2022).

Estas son las últimas novedades, y te muestro como obtener un ejemplo de una arquitectura completa con NET 6.0 (API, Minimal API, FrontEnd y Mobile Apps entre otros):

Net Maui – Enero 2022 – YouTube

Si quieres saber más de NET MAUI, este lo lanzamos apenas ya teníamos las primeras novedades:

NET MAUI – Te cuento todo lo que debes sabes – YouTube

Consultas Linq en Query Syntax y Method Syntax en .net con c#

LINQ : Language Integrated Query – Wikipedia, la enciclopedia libre

Como su nombre lo dice, es lenguaje para realizar consultas integradas, y es provisto y administrado por .NET

Aprende a usarlo, te permitirá recorrer cualquier colección (Enumerables, Dictioraries, Lists, etc)

También cada resultado proveniente de una consulta con el ORM de EF (Entity Framework ) te devolverá un IQueriable (Un tipo de colleción), y su manipulación, sin dudas los harás mediante LINQ.

Para que puedas aprender en el siguiente video vemos varias consultas para que puedas realizar, y sobre todo para que puedas comparar los dos métodos disponibles que tienes:

Method Sintax & Query Sintax

Sin mas nada que decir, aquí está el video:

Consultas Linq en Query Syntax y Method Syntax en .net con c# – YouTube

A connection was successfully established with the server, but then an error occurred during the pre-login handshake

Trabajas con Docker, MSSQL y recibes este error

Para ser mas claro el error que me estuvo volviendo loco fue el siguiente:

A connection was successfully established with the server, but then an error occurred during the pre-login handshake. (provider: TCP Provider, error: 35 – An internal exception was caught

Es difícil de entender y descifrar así te cuento un poco como era mi escenario

Escenario:

Persistencia: MS SQL Server 2018 Express Edition

Aplicación Web: Net 6.0

Contenedor: Docker

Al principio pensé que era una cuestión de conexión al motor, por lo que suele tener las siguientes precauciones:

En mi imagen base suele habilitar algunas herramientas para facilitar las pruebas: Por ejemplo iputils

FROM mcr.microsoft.com/dotnet/aspnet:6.0 AS base

WORKDIR /app
#si el motor es SQL 2018
RUN sed -i 's/TLSv1.2/TLSv1/g' /etc/ssl/openssl.cnf 
EXPOSE 80
EXPOSE 443
USER root
RUN apt-get update
RUN apt-get install -y iputils-ping
RUN apt-get install -y nano
RUN apt-get install -y tzdata
RUN apt-get install -y locales
ENV LANG es_AR.UTF-8  
ENV LANGUAGE es_AR:es  
ENV LC_ALL es_AR.UTF-8  
ENV TZ America/Mendoza

Por otro lado en mi aplicación web bajo NET 6.0 suele habilitar la migración por párametros y habilitarlas al lanzamiento de la misma:

Mi Program.cs quería así

....
bool applymigrations = Configuration.GetValue<bool>("Migrations:ApplyMigrations");
string cone_rw6 = Configuration.GetValue<string>("ConnectionStrings:RW6Connection");
string cone_beje = Configuration.GetValue<string>("ConnectionStrings:BejermanConnection");

Console.WriteLine($"BD: Migraciones {applymigrations}, Conection: {cone_rw6} ");
Console.WriteLine($"BD: Migraciones {applymigrations}, Conection: {cone_beje} ");

var scope = app.Services.CreateScope();
if (applymigrations) await Migrations(scope.ServiceProvider);

Console.WriteLine("******************Finalizado configuración de middlewares *******************");

/* ========  Run  =======*/
app.Run();

Y mi función de Migraciones así



async Task Migrations(IServiceProvider services)
{
    //Cadena de conexión de variable externa



    var context_identity = services.GetRequiredService<AppIdentityContext>();
    var context_appdb = services.GetRequiredService<AppDbContext>();
    var conn_appidentity = context_identity.Database.GetDbConnection();
    var conn_appdb = context_appdb.Database.GetDbConnection();

    Console.WriteLine($"Conexión Actual Identity: {conn_appdb.ToString()}  {Environment.NewLine}  {conn_appdb.ConnectionString}");
    Console.WriteLine($"Conexión Actual AppDB: {conn_appdb.ToString()}  {Environment.NewLine}  {conn_appdb.ConnectionString}");
    Console.WriteLine("****************** Probando acceso  *******************");
    try
    {
        Console.WriteLine("Base Disponible de Identity:" + context_identity.Database.CanConnect());
        Console.WriteLine("Base Disponible de AppDb:" + context_appdb.Database.CanConnect());
    }
    catch (Exception ex)
    {
 Console.WriteLine($"------ !!! ERROR connectando: {ex.Message}");
    }

    Console.WriteLine("****************** Aplica Migraciones:  *******************");
    Console.WriteLine(applymigrations);

    if (applymigrations)

    {
        //Aplico la migracion
        Console.WriteLine("******************Aplicando migración*******************");
        Console.WriteLine("Migrando Identity:");
        context_identity.Database.Migrate();
        Console.WriteLine("Migrando Context:");
        context_appdb.Database.Migrate();

        Console.WriteLine("******************Cargando Usuarios:*******************");
        var userManager = services.GetRequiredService<UserManager<MyAUser_Models>>();
        var roleManager = services.GetRequiredService<RoleManager<IdentityRole>>();

        await AppIdentity_StartUp.CargarUsuarios(userManager, roleManager);
    }
}

Pero a pesar de todo esto no había caso. La aplicación se conectaba, pero luego la misma se caía.

Por lo que me puse a analizar el error completo:

Microsoft.Data.SqlClient.SqlException (0x80131904): 
A connection was successfully established with the server, 
but then an error occurred during the pre-login handshake. 
(provider: TCP Provider, error: 35 - An internal exception was caught)
 ---> System.Security.Authentication.AuthenticationException: Authentication failed, see inner exception.
 ---> Interop+OpenSsl+SslException: SSL Handshake failed with OpenSSL error - SSL_ERROR_SSL.

Y venía de la mano de SSL. Ya sabiendo por donde orientar mi búsqueda, fue mas sencillo llegar al causar y a la solución:

Para OpenSSL, la mínima versión con la que opera la imagen de .NET es TLS v1.2 en adelante, mientras que el MS SQL Server 2018 express edition, solo soporta hasta TLS v1.0

Solo era cuestión de probar, si la teoría era correcta. Para ello ingresé a la imagen y modifique la configuración del openssl para correr en una versión inferior:

#docker exec -it <name> sh

#cat /etc/ssl/openssl.cnf

.......
[system_default_sect] 
MinProtocol = TLSv1.2 
CipherString = DEFAULT@SECLEVEL=2

Por lo que procedí a modificar mi imagen, y no tener que cambiarlo manualmente en la implementación:

Para ello agregué

RUN sed -i 's/TLSv1.2/TLSv1/g' /etc/ssl/openssl.cnf

Mi primer parte del dockerfile quedó así

#################################################################################################
FROM mcr.microsoft.com/dotnet/aspnet:6.0 AS base

WORKDIR /app
#si el motor es SQL 2018
RUN sed -i 's/TLSv1.2/TLSv1/g' /etc/ssl/openssl.cnf 
EXPOSE 80
EXPOSE 443
USER root
RUN apt-get update
RUN apt-get install -y iputils-ping
RUN apt-get install -y nano
RUN apt-get install -y tzdata
RUN apt-get install -y locales
ENV LANG es_AR.UTF-8  
ENV LANGUAGE es_AR:es  
ENV LC_ALL es_AR.UTF-8  
ENV TZ America/Mendoza

API rest con Net 5.0 y MongoDB

Desde que salío Net 5.0 (Nov 2020) empezamos a migrar todos nuestros proyectos a esta nueva versión. Muy similar a Net Core, pero con algunos cambios, sobre todo haciendo foco en Microservicios. Por otro lado con el crecimiento de popularidad de las bases No SQL decide armar esta tutorial con el producto mas conocidos: Mongo DB.

Esta base no relacional presenta ciertas diferencias con respecto a sus antecesoras relacionales como MS SQL Server. Por lo que en los siguientes videos te vamos a mostar

  • Como instalar desde 0 tu motor MongoDB
  • Crear la Base de Datos
  • Crear la colección
  • Realizar las primeras consultas por consola
  • Realizar las primeras consultas por Compass

En esta segunda parte ya nos enfocamos en trabajar con Net 5.0 y crear nuestro servicio web

  • Creamos el proyecto
  • Armamos nuestro modelo
  • Incorporamos Swagger y MongoDB Driver
  • Creamos la estructura para empezar a trabajar

En esta tercer parte ya estamos listo para nuestro servicio

  • Creamos el CRUD (Create, Recovery, Update y Delete)
  • Creamos el controlador
  • Probamos nuestro API Rest

En el siguiente video estaremos viendo los siguientes temas

  • Crear filtros avanzados
  • Usando Docker

Issabel – Error 500 con Smarty

Hacía tiempo que no instalaba una PBX con Issabel desde 0. Ya estando a mediados del 2021, creí que el proceso iba a salir redondo, y no se iba a presentar ningún problema. Que pena enterarme que sigue teniendo algunos bugs.

Esta vez, luego de terminar la instalación, y actualizar paquetes (yum update), al ingresar al portar web tenía un error 500.

Por ello lo primero que debes hacer es ir a ver logs:

tail -f /var/log/httpd/ssl_error_log

Un error se repetía con cada intento de acceso que realizaba:

[Sun Jun 13 11:51:43.298260 2021] [:error] [pid 1312] [client 172.0.4.102:52760] PHP Fatal error: Uncaught –> Smarty: unable to create directory /var/www/html/var/templates_c <– \n thrown in /usr/share/php/Smarty/sysplugins/smarty_internal_runtime_writefile.php on line 51

Lo primero que debes hacer es entender el mismo:

smarty_internal_runtime_writefile.php

Es el encargado de escribir la cache en su directorio destino. Aquí te das la idea es que una cuestión de permisos

unable to create directory /var/www/html/var/templates_c

Aquí confirmamos la teoría de cúal es el directorio que no tiene permisos (o que no existe)

La solución es bastante sencilla:

  • Creamos el directorio
  • Le damos permisos
mkdir /var/www/html/var/templates_c
chmod 777 /var/www/html/var/templates_c

Con esto debería ser mas que suficiente para solucionar el problema.

No graba en las transferencias

El siguiente problema fue detectado en un Elastix 4.0 con Asterisk 11.24. No descartó que persista en Issabel, pero habría que confirmar.

El origen de la cuestión es que las grabaciones no incluía las transferencias. Para ser más claro, una llamada entrante (IN) que era dirigida hacia una cola (queue), es atendida por un coordinador. Luego este la vuelve a transferir, y en ese momento que realiza el corte (hangup), ya que alguien lo atendía del otro lado, la grabación se cortaba.

Esto puntualmente tiene que ver con una propiedad de asterisk (herencia), la cúal no estaba seteada. La forma de correguirlo es agregando la siguiente línea en el archivo: extensions_override_freepbx.conf (o extensions_override_elastix.conf)

Dependiente de tu versión deberías verificar en cúal de esos dos archivos agregar la línea

1-Haz backup de tu archivo

cp /etc/asterisk/extensions_override_freepbx.conf /etc/asterisk/extensions_override_freepbx.conf.bak

2-Busca la siguiente línea

exten => s,n(record),MixMonitor(${MIXMON_DIR}${CALLFILENAME}.${MIXMON_FORMAT},,${MIXMON_POST})

3-Agregá al final de esta (y en una nueva línea) , lo siguiente

exten => s,n,Set(AUDIOHOOK_INHERIT(MixMonitor)=yes)

4-Reinicia el servicio del asterisk

sudo service asterisk restart

o ingresa a la consola del asterisk y haz un reinicio por aplicación

Stopping and Restarting Asterisk From The CLI – Asterisk Project – Asterisk Project Wiki

core restart gracefully

Listo!!!

A partir de ahora, la llamada inicial, contendrá en la grabación todas las transferencias que puede haber sufrido, hasta el último corte (Tanto del cliente o del agente) que haya transcurrido.

Configurar Grandstream 410x en Argentina

En la era de troncales de SIP mediante MPLS por Fibra, quedan algunos rezagados que mantienen sus líneas análogas. Lo importante es estar conectados a la PSTN sin importar él como.

Este es el caso con el que me encontré con la necesidad de digitalizar 4 líneas del proveedor de Telefónica de Argentina, y tras indagar las ofertas de mercado que habían vigente se decidió por la compra de un gateway Grandstream GXW 410x.

Este equipo cuenta dos versiones: de 4 puertos FXO (4104) y 8 puertos (4108). Fuera de ellos son exactamente iguales.

El primer obstaculo que puedes encontrarte es que este en un Firmware desactualizado. Aquí te cuento como llevarlo a su versión mas vigente

Subsanado esta parte restaba configurarlo. Para ello la parte más difícil fue detectar la correcta frecuencia de los tonos. Existen varias configuraciones dando vueltas en la red, pero la solución más cercana fue usar la herramienta de Test (Line Analysis). Sin embargo no es del todo correcto. El tip para esta etapa consiste en subirle el volumen mediante el incremento de la ganancia. Tanto para la llamada entrante, y poder detectar el CID (número) como para detectar el corte (HangUp)

Les comparto las imágenes que hablan por si solo…

En esta configuración en particular, los números ingresan una central Asterisk 13. Para ello es que directamente se dio de alta un troncal para manejar los 4 puertos:

Espero que les sea útil…

Website not available with Sophos XG

Este error, es un dolor de cabezas que suele dar el UTM de Sophos. La implementación del mismo permite filtrar el tráfico, y controlar ataques indeseados, entre otras cosas. Sin embargo en la panacea que promete, presenta a veces errores que son dificiles de detectar, sobre todo porque sus logs no quedan del todo accesible, y toca ingresar siempre por consola para intentar encontrar el meollo del asunto.

En concreto, muchas veces al intentar ingresar a sitios “https”, suelen haber problemas al no cargar correctamente los scripts, certificados, u otros motivos extraños que terminan provocando errores 50x. Sin embargo los mismos al probarlo esquivando al Sophos XG funcionan correctamente. Por ello es que empiezas a dudar del causante del problema.

Ante esto encontré una solución ( no elegante) que funciona para arreglar el error, sin embargo aún no está claro el motivo que se soluciona. Lo que hacemos es reiniciar el servicio de awarrenhttp, que es el proxy web encargado del filtro del tráfico.

No se hable mas!!!. Les dejo la guía:

You enabled debug logging for the web proxy, reviewed the service status and log contents, then disabled debug logging.

OpenPuTTY from the desktop connect to Sophos XG
Open the Advanced Shell4 and run:
service -S
This command shows you the status of all of the services on the XG Firewall.

service–S | grep http


You can filter this output using grep.
Run:
service awarrenhttp:debug–ds nosync
This command will put the service in-it is not synchronized across a HA cluster.
Run:
service–S | grep http
You can see that the service is nowrunning and is in debug mode.
Run:
tail–f /log/awarrenhttp.log
command you can see the debuglogging.
PressCtrl + C
Run:
service awarrenhttp:debug–ds nosync
Running this command again will takethe service out of debug.
Run:
service–S | grep http
Confirm that the service is no longer indebug mode.
You enabled debug logging for the web proxy, reviewed the service status and log contents, then disabled debug logging.