domingo, 27 de noviembre de 2016

Offline Sync + Azure Mobile App + Internal Server Error

Hace poco tiempo decidí aprender Xamarin Forms. Tuve suerte ya que Microsoft lanzó el curso en línea "Xamarin Diplomado Latinoamérica",

Si están pensando en aprender dicha tecnología, no se lo pierdan: Xamarin Diplomado Latinoamerica.

La cuestión con todo esto es que en dicho curso se debe hacer una app conectada a Azure Mobile Services.

La app que hice muestra en pantalla las cotizaciones de las principales monedas con las que se opera en Uruguay (mi país de origen).

Para ello se fija en la base local (IMobileServiceSyncTable<Cotizaciones>) si no existen registros para la fecha actual, si no existen: baja de la página del Banco República Oriental del Uruguay las cotizaciones del día, las guarda en la base local y luego de ello sincroniza con Azure. La idea es, más adelante, completar esta app agregando la funcionalidad de que el usuario pueda consultar por fecha las cotizaciones y además un gráfico con la evolución de las monedas entre dos fechas. 

(No, no vale reírse ... es una app con objetivo didáctico! 😃 )



Al intentar sincronizar la app, en el método PullAsync,  tiraba un error 500: "Internal Server Error".

El código del lado del cliente (Xamarin Forms):




Ésta es la clase “Cotizaciones” definida en el cliente:



El código correspondiente al Push funcionó, ya que si abría la tabla en el SQL Management Studio se mostraban los datos!: 



Ésta es la clase “CotizacionesController” definida en el Backend. Noten el decorado de la clase: "   [MobileAppController]" ... sin él las cosas no funcionan del todo bien.


Ésta es la clase “Cotizaciones” definida en el  Backend: 


El motivo de este post, es explicarles (mas allá del error puntual que yo tenia (Tenía desactivado el   AutomaticMigrationsEnabled  de Entity Framework Code First automatic migrations), cómo hice para solucionar el problema:

Una opción puede ser: En la parte del servicio en Azure… entré a una parte que se llama “Service Editor” y luego Output. Esta ventana nos muestra un traceo con todos los posibles errores que hayan ocurrido en el servicio:



Otra opción que también me fue de utilidad, es "attachearnos" (adjuntarnos) al backend (lo puedes hacer desde la pestaña Cloud Explorer)  y depurar cuando el servicio recibe una llamada. Quedé asombrado de las buenas herramientas que posee Visual Studio (con el SDK de Azure instalado) para realizar cualquier operación en la nube:




Bueno, eso ha sido todo por ahora espero les sea de utilidad... hasta la próxima!














sábado, 28 de marzo de 2015

Como solucionar el bug del control ReportViewer que muestra todos los campos con #Error

Hace tiempo venimos trabajando con ReportViewer y nunca habíamos tenido mayores problemas con el mismo, hasta el día de ayer que sucedió lo que paso a contarles a continuación.

Teníamos unos reportes hechos en una aplicación web que corría con la versión vieja del ReportViewer (la que venía con VS2010 ... no recuerdo el número de versión exacta) corriendo sobre .NET 2.0 y generando reportes localmente; teníamos la necesidad de migrarlo a un sitio nuevo hecho con VS2013 corriendo .NET 4.5.2. La migración se realizó de manera transparente, es decir, no hubo que meterle mano a los archivos rldc ni nada por el estilo. Al momento de probarlos tampoco hubo problemas,  los reportes se generaron correctamente. 

Hasta ahí íbamos bien, llegó el momento de ponerlo en producción y al momento de generar el reporte... ésto es lo que sucedió:


Nos generó el reporte con todos sus campos marcados con el tag "#Error" !. 

Antes de seguir cabe aclarar que algunos campos son expresiones (ej: =IIf(Fields!Cost.Value > Fields!Revenue.Value, "Red", "Black") pero la mayoría no lo son e igual se mostraban con el infame mensaje de "#Error", lo que descartaba algún bug que pudiera tener la expresión.

Pero, ¿que pasó? 

Bien, al parecer es un tema relacionado con el cambio en las políticas de seguridad de .NET 4 y el ReportViewer corriendo en un AppDomain con permisos mas restrictivos, por lo que tenemos dos opciones posibles para solucionarlo:

1) Agregar al web.config la siguiente linea:"<trust legacyCasModel="true" level="Full" />


2) Al momento de generar el reporte agregar las dos líneas que se marcan a continuación: 

protected void GenerarArchivoPdf(string fileName, ReportViewer rpv)
{
Warning[] warnings = null;
string[] streamids = null;
string mimeType = null;
string encoding = null;
string extension = null;
const string deviceInfo = "";
System.Security.PermissionSet sec = new System.Security.PermissionSet(System.Security.Permissions.PermissionState.Unrestricted);
rpv.LocalReport.SetBasePermissionsForSandboxAppDomain(sec);
//Generar el archivo
byte[] archivo = rpv.LocalReport.Render("PDF", deviceInfo, mimeType, encoding, extension, streamids, warnings);
//Guardar el archivo en la carpeta temporal para referenciarlo como adjunto del mensaje
My.Computer.FileSystem.WriteAllBytes(fileName, archivo, true);
}

En nuestro caso lo resolvimos utilizando la opción 2

Si quieren leer mas acerca de este tema les recomiendo:



Espero les sea de utilidad y me despido hasta la próxima!






jueves, 9 de octubre de 2014

Obtener el id de usuario desde un token generado por la pagina PasswordReset de ASP.NET Identity 2.1

Antes de comenzar: ¿Que es ASP.NET Identity?

ASP.NET Identity es una de las grandes novedades de la nueva versión de ese gran paraguas de soluciones llamado ASP.NET, sustituyendo al viejo y querido sistema de Membership que venimos usando desde que salio allá por el año 2005. Esta diseñado para dar solución a muchos de los problemas y limitaciones que el sistema anterior tenia. Si quieren tener un análisis detallado del nuevo sistema, les recomiendo leer este post http://brockallen.com/2013/10/20/the-good-the-bad-and-the-ugly-of-asp-net-identity/ (Nota: no esta actualizado por lo que algún item mencionado como desventaja ya no aplica porque fue implementado en la ultima versión)

Presentado el tema, pasemos al problema.

La plantilla de Visual Studio 2013, viene con una pagina de OlvidoSuContraseña y otra RestablecerContraseña que te permiten realizar dichas tareas. 

El mecanismo para restablecer la contraseña que utilizamos en nuestro caso, es el envío de un link vía mail para restablecer la contraseña (hay que tener en cuenta que hay otras posibilidades)

Al entrar a la página de restablecimiento de contraseña, le vuelve a solicitar al usuario la dirección de mail! Evidentemente el que hizo esta plantilla, no tuvo en cuenta que ésto no es muy práctico desde el punto de vista usabilidad.

La idea para solucionar esto, es obtener del token el id de usuario que forma parte del mismo y a partir del mismo, obtener su dirección de mail y no tener que pedírselo de nuevo al usuario.


Manos a la obra!

1) Ubicar el archivo Startup.auth.cs ubicado en la carpeta App_Start y agregar las lineas de código que se muestran a continuación:



2) Ubicar el archivo ResetPassword.aspx ubicado en la carpeta Account y agregar las lineas de código que se muestran a continuación:






La magia la hace el método GetUserFromToken que utiliza el provider que definimos en el primer paso (ResetPasswordProtectionProvider).

Si querés saber mas acerca de Asp.Net Identityhttp://www.asp.net/identity

Espero que les sea de utilidad, hasta la próxima!


martes, 4 de marzo de 2014

Timeouts de Web Service en carga de archivos grandes

En esta semana hemos tenido la oportunidad de agregar funcionalidad a un web service existente. Dicha funcionalidad consta de subir una lista de fotos desde un celular al servicio web anteriormente mencionado. A continuación, la firma del método en cuestión:


Eventualmente, cada foto subida desde el celular, puede superar el tamaño establecido como límite en un servicio web asp.net (4096KB - 4Mb), por lo que debemos meter mano en la configuración por defecto para aumentar estos límites.

Abrimos el archivo web.config y dentro de la sección  System.Web tenemos el tag HttpRuntime y dentro del mismo, encontramos maxRequestLenght y executionTimeout que son los valores que debemos aumentar dependiendo de nuestras necesidades:
 

Adicionalmente, si vamos a implementar este web service en un servidor con IIS 7 o superior, debemos cambiar el límite mencionado anteriormente en OTRO lugar. El tag en cuestión es maxAllowedContentLength el cual se encuentra dentro del tag requestLimits, que a su vez está dentro de system.webServer


Luego de haber modificado éstos valores, queda todo funcionando OK, verdad?
En nuestro caso no fue así. Debimos aumentar un valor adicional dentro de la configuración de IIS, el cual les paso a detallar:

Primero, vamos a la configuración avanzada del sitio como se muestra en la imagen a continuación:

 
Luego, expandimos la sección límites y cambiamos el valor de "Tiempo de espera de la conexión" y That's it!
 
 
No puedo dejar de darle crédito del último tip, al colega Roberto Broggi encargado de IT en la empresa para la cual implementamos la solución.
 
Espero les sea de utilidad, hasta la próxima!

jueves, 20 de febrero de 2014

AOP & PostSharp

Mi filosofía, es siempre aprender cosas nuevas y divertirme haciéndolo.

Hace poco tiempo, los amigos Fabián Fernandez y Bruno Bologna, organizadores de la .NetMeetupUy, dieron una charla muy interesante de AOP y PostSharp.

Por las vueltas de la profesión, hoy me toca trabajar con esa tecnología, la cual gracias a esa charla, no me resulta una desconocida.

Por lo tanto, me voy a tomar el atrevimiento de darles un consejo a mis colegas y amigos:

Asistan a las charlas técnicas...siempre se adquiere conocimiento que en una de esas van necesitar mas pronto de lo que creen...

Mas informacion de AOP y PostSharp en:

http://www.meetup.com/NET-UY/events/145986872/

http://www.postsharp.net/

http://www.youtube.com/watch?v=mKszBAlTOkg