Cambio del directorio de compilación temporal de ASP.NET

He leído esto en algún sitio recientemente y me ha llamado mucho la atención porque no lo sabía. Resulta que es posible cambiar la carpeta en la que ASP.NET 2.0 compila las aplicaciones y genera todos sus ensamblados. Para ello basta con indicarlo en web.config dentro del nodo ‘compilation’ usando el atributo ‘tempDirectory’, así:



<compilation tempDirectory=»C:Temporales»/>


Muy sencillo. Igual te puede resultar útil en alguna ocasión.

Cómo usar la administración Web integrada en ASP.NET en aplicaciones de producción

Una cuestión muy celebrada de ASP.NET 2.0 es que no es necesario «currarse» desde cero toda la funcionalidad de autenticación, autorización, etc… ya que gracias a las nuevas API basadas en proveedores para Membership y Roles junto con los controles de Login (que incluyen interfaces de usuario para casi todo lo que necesitemos desde autentiación hasta creación de usuarios, etc..) incorporados a la versión 2.0 apenas será necesario escribir código nunca.


El caso es que desde Visual Studio todo es muy fácil: basta con ir al menú «Sitio web·Administración de sitio Web» y nos aparece el flamante diálogo que vemos en la figura:



(pulsa para ver en tamaño real)


El caso es que con él configuramos todos los aspectos de nuestra aplicación relacionados con la seguridad: desde los proveedores que usaremos, pasando por los permisos de las carpetas y llegando a la definición de los primeros usuarios. Todo ello se guarda por defecto en una base de datos SQL Server creada para la ocasión y que tiene una estructura predefinida y unos procedimientos almacenados que usan Membership y Roles, y que podemos reproducir gracias a la herramienta de línea de comandos aspnet_regsql.exe.


Bien, el caso es que una vez terminada la aplicaicón la ponemos en un servidor IIS de verdad para que entre en producción y estamos la mar de contentos con nuestros usuarios. Pero, de repente, nos damos cuenta de que necesitamos más usuarios, de que necesitamos editar los que ya hay o cambiar cualquier otro aspecto de nuestra seguridad y la herramienta de configuración que tenemos en Visual Studio no está. ha desparecido y no podemos usarla en producción. :-((( De hecho si miramos por los foros de Internet y de Microsoft vemos que todo el mundo nos dice: «no hay nada que hacer», «constrúyete tu propia gestión de usuarios» o «menuda chapuza han hecho».


Bien, lo cierto es que la cosa no es tan terrible y realmente sí podremos hacer uso de la herramienta sin problemas. Veamos como…


Lo que mucha gente no sabe es que esta herramienta está incluida junto con su código fuente completo ¡¡en la instalación de las bibliotecas de tiempo de ejecución de ASP.NET 2.0!!. Es decir, está incluida en todos los equipos capaces de ejecutar ASP.NET 2.0, no sólo en los que tienen Visual Studio 2005 instalado. Para encontrarla basta con ir a la siguiente ruta:



C:WINDOWSMicrosoft.NETFrameworkv2.0.50727ASP.NETWebAdminFiles


Sabiendo esto sólo hay que hacer un par de cosas y saber trucarla para poder sacarle partido en cualquier aplicación, incluso en las que estén en producción.


Vete a IIS y en el servidor virtual de tu aplicación o en cualquier otro crea un directorio virtual que apunte a la ruta anterior. ¡OJO! es muy importante que esté en un directorio virtual y no directamente en el raíz de un servidor virtual por la forma en la que está construida la aplicación, así que crea uno con el nombre, por ejemplo, de «aspnetwebconfig».


En la pestaña de seguridad del directorio virtual deberás permitir la autenticación de usuarios ya que sólo con la anónima no podras hacerla funcionar. Pues deshabilitar la anónima (no se usa,así que da igual pero mejor quítala) y activa la autenticación integrada de Windows.


Muy importante: no olvides indicar que quieres usar ASP.NET 2.0 para este directorio virtual o recibirás errores puesto que por defecto se emplea ASP.NET 1.1. Usa la pestaña ASP.NET de tu IIS para conseguirlo:



Bien, una vez creado el directorio virtual de administración podrás administrar cualquier aplicación Web de ASP.NET 2.0 que tengas en esa máquina llamando a la página por defecto con dos parámetros especiales, de la siguiente manera (ejemplo):



http://localhost/aspnetwebconfig/default.aspx?applicationPhysicalPath=D:LogistiaCodigoLogistiaWeb&applicationUrl=/LogistiaWeb


Fíjate que los dos parámetros son los siguientes:


1) applicationPhysicalPath: La ruta física en el disco a la aplicación que quieres administrar. La herramienta de administración se encargará de leer su web.config y conectarse a las bases de datos pertinentes y ver los permisos de cada carpeta, etc…


2) applicationUrl: la ruta virtual base de tu aplicación, normalmente el nombre de la carpeta virtual que usas para acceder a ella. Puede estar en blanco.


Una última cosa importante: este sitio web de administración sólo funcionará en local, no permitiendo el acceso desde URLs remotas por cuestiones de seguridad. Pero te permitirá manejar cómodamente los usuarios, roles, parámetros de personalizaicón, seguridad, etc…

Cómo mezclar varios lenguajes de programación en una aplicación ASP.NET 2.0

Una de las cosas más reseñadas de ASP.NET 2.0 es que es capaz de gestionar páginas ASPX creadas en diferentes lenguajes todas al mismo tiempo. Es decir, puedes tener una página o un control escritos en C# y mezclarlos con otros escritos en VB.NET o J# sin problema. Incluso puedes depurarlos todos juntos desde Visual Studio, saltando sin problemas de un lenguaje a otro.


Ahora bien, desde mi punto de vista esto no es demasiado interesante. Es raro que reutilices una página de una aplicación a otra y si escribes una aplicación completa desde cero normalmente lo haces en el mismo lenguaje. Hombre, pensando en equipos de desarrollo donde varios programadores contribuyen al mismo proyecto y trabajan en lenguajes distintos es muy interesante, pero vamos…


Normalmente lo que compartes entre aplicaciones son controles o bibliotecas de funciones, las cuales normalmente deberías compilar en sus propios ensamblados y listo. Ya no tendrías que mezclar lenguajes ahí.


Otra posibilidad es que tengas un módulo o una clase escritas en tu carpeta App_Code de una aplicación y quieras reutilizarlas en otra. Normalmente lo que tendrías que hacer es simplemente copiarlas a la carpeta App_Code de tu proyecto nuevo y ya estaría. El problema es que App_Code no permite mezclar código de varios lenguajes dentro de ella. Así, si copias un archivo .vb a una carpeta App_Code que ya contiene algún archivo .cs verás que al ejecutar la aplicación el compilador se queja y te dice que no puedes mezclar lenguajes en App_Code.


Entonces ¿se pueden o no se pueden mezclar lenguajes?


Pues la respuesta es que sí, pero no directamente.


Cuando el compilador de ASP.NET compila de forma automática el contenido de la carpeta App_Code lo que hace es generar una DLL única para todas las clases que allí estén y para ello usa el compilador del lenguaje en el que estén escritas. Si están en más de un lenguaje no sabe a qué compilador llamar y por eso se queja.


Para resolver este asunto podemos echar mano de un «truco» que consiste en indicar al compilador cómo queremos compilar nuestro código existente en App_Code. En la sección <compilation> de web-config se puede indicar cuántas DLL de código queremos obtener a partir de App_Code y cómo están éstas organizadas. Cada ensamblado generado se corresponderá con una carpeta dentro de App_Code y se llamará al compilador para dicha carpeta.


De este modo podemos guardar en una carpeta todo el código en VB, en otra carpeta el código en J# y dejar en el raíz las clases escritas en nuestro lenguaje principal (en mi caso C#). La estructura podría quedar así:



Está claro: cada lenguaje en su carpeta.


Sin embargo si ahora ejecutamos la aplicación veremos que se vuelve a producir un error. Sigue sin funcionar.


El problema es que todvía nos hace falta ajustar las carpetas de código en web.config, de la siguiente manera:


<compilation>
   <
codeSubDirectories>
      <
add directoryName=«CSharp«/>
      <
add directoryName=«JSharp«/>
   </
codeSubDirectories>
</
compilation>


Fíjate en que no se indica qué lenguaje se usa para compilar cada carpeta (eso lo determina automáticamente el compilador) sino que se va a generar un ensamblado por cada carpeta y por lo tanto se puede usar un compilador diferente para cada una de ellas. De ahí que se pueda mezclar el código.


Ahora si ejecutas la aplicación verás que todo funciona sin problemas y puedes depurar todos a la vez etc…


Un par de observaciones:


1.- Si te fijas en la imagen de arriba, la de las carpetas, verás que éstas tiene un aspecto «normal», es decir, son amarillentas y no tienen distintivo especial alguno. Tras haber añadido las líneas anteriores al web.config si te vuelves a fijar verás que su aspecto es el mismo que el de la carpeta App_Code ya que van a ser compilados:



2.- ¿Por qué funciona a mezcla de lenguajes en las páginas? Porque cada página en el nuevo modelo de compilación de ASP.NET 2.0 (que a mi no me acaba de convencer) se compila en su propio ensamblado de manera individual, de ahí que pueda estar cada una de ellas en su lenguaje. Lo que no se puede hacer es mezclar lenguajes en la misma página, claro.

Una manera mejor de persistir el ViewState

Siguiendo a mi post anterior, vamos a ver una técnica alternativa para conseguir la persistencia del ViewState en sesión.


La anterior técnica, nativa de ASP.NET 2.0 adolecía de varios problemillas, los más importantes son:



1.- No eliminaba del todo el ViewState, sólo una parte del mismo. En formularios Web con muchos controles el tamaño del ViewState sigue siendo considerable, si bien se reduce bastante.


2.- Sólo funciona en ASP.NET 2.0, pero no en versiones anteriores.


Voy a explicar a continuación una técnica alternativa que elimina estos problemas y tiene algunas ventajas a mayores.


Para conseguir manejar a nuestro antojo el ViewState podemos sobrescribir dos métodos importantes de la página: SavePageStateToPersistenceMedium y LoadPageStateFromPersistenceMedium. Como se deduce de su propio nombre estos métodos se llaman automáticamente por la infraestructura de páginas ASP.NET a la hora de almacenar y de recuperar el ViewState de una página respectivamente.


Dado que en nuestro caso lo que vamos a hacer es persistir el ViewState a memoria y de manera individual para cada usuario emplearemos una variable de sesión. Podemos usar una única variable para todas las páginas de modo que se sobrescriba cuando cambiemos de página, o bien podemos usar una variable diferente para cada página y así mantener incluso su estado entre varias visitas (más sobre esto luego). En el ejemplo que he preparado he usado esta segunda opción, por lo que defino el prefijo que llevarán todas estas variables:



private const string PREF_CLAVE = «SP_VWST_»;


Le he llamado así para recordar con estas iniciales la palabra «Session Persisted ViewState».


Bien, ahora sobreescribimos el método protegido SavePageStateToPersistenceMedium, y lo dejaremos definido de la siguiente manera:



protected override void SavePageStateToPersistenceMedium(object state)
{
  //base.SavePageStateToPersistenceMedium(state);
  //Se almacena en Sesión (la base lo hace en un campo oculto)
  Session[PREF_CLAVE + Request.RawUrl] = state;
}


Es decir, evitamos que se llame a la implementación por defecto de la base (la primera línea comentada) ya que si no se comportaría como siempre, y almacenamos el objeto de estado en una variable de sesión que se llamará con nuestro prefijo seguido por la URL de la página (para distinguirla del estado persistido de otras páginas). Así de sencillo.


Ahora sólo queda recuperar este estado cuando sea necesario. Para ello seguimos un procedimiento igual de simple, que consiste en sobrescribir el método LoadPageStateFromPersistenceMedium de la página, del siguiente modo:



protected override object LoadPageStateFromPersistenceMedium()
{
object state = Session[PREF_CLAVE + Request.RawUrl];
//Si no lo hay en memoria lo coge del campo oculto, aunque sólo debería darse en la primera llamada y aún así sería nulo…
return (state != null) ? state : base.LoadPageStateFromPersistenceMedium();
}


En este caso recuperamos el estado desde la variable de sesión anterior. Puede que esté vacío porque es la primeravez que pasamos por la página, en cuyo caso llamamos a la implementación por defecto de la clase base (Page) para que otorgue los valores iniciales correctos. También muy sencillo ¿verdad?


Conclusiones


Con esta técnica podremos persistir el estado de nuestras páginas en memoria desde cualquier versión de ASP.NET, lo cual brinda varias ventajas en ciertas circunstancias:




  1. No se debe trasegar la información de estado entre los diferetes postbacks, lo que ahorra mucho ancho de banda y aumenta la velocidad en formularios con muchos controles. Por ejemplo, esta técnica aplicada a un formulario de una de las últimas aplicaciones que hemos hecho en Krasis aumentó la velocidad del mismo de manera espectacular ya que contenía varias decenas de controles (era una entrada de datos muy compleja con muchos postbacks y efectos AJAX).


  2. Con esta técnica sí se elimina por completo el ViewState, al contrario que en el caso del objeto PageStatePersister de ASP.NET 2.0, que sí deja parte del mismo en el formulario.


  3. Al hacerlo de este modo podemos conservar el estado de una página aunque nos vayamos a otras y más adelante volvamos a la misma. Mientras la sesión esté activa podemos regresar a la página y los controles estarán exactamente como los dejamos porque el estado de los mismos están en la variable de sesión. Imagínate por ejemplo una página de búsqueda compleja, con muchas variables y valores compuestos que cuesta mucho configurar. Puedes hacerlo una vez y tenerlos así fijados siempre que regreses a la página (mientras no se borre la variable de sesión correspondiente).

He colocado aquí un archivo .cs con una clase que implementa esta técnica. Si quieres que una página tuya la soporte sólo tienes que heredar de esta clase en lugar de Page y ya está.


¡Espero que te resulte interesante! 🙂

Cómo persisitir el ViewState en una variable de sesión en ASP.NET 2.0

El ViewState de una página ASP.NET 2.0 es lo que permite la «magia» de los PostBack. Se trata de un campo oculto que se envía con el formulario que introduce ASP.NET en todas las páginas ASPX y contiene información sobre el estado de los controles de la misma. A partir de él se recupera dicho estado y parece que la página funciona como un formulario de escritorio tradicional.


El caso es que si tenemos muchos controles este ViewState puede llegar a ocupar mucho y eso hace que cada PostBack al servidor sea muy lento y se empiece a notar demasiado. En casos un poco extremos podemos tratar de minimizar este trasiego de información entre cliente y servidor persistiendo el ViewState en otro lugar en lugar de en un campo oculto de la página. Para ello ASP.NET 2.0 ofrece «de serie» un objeto especial llamado SessionPageStatePersister que permite conseguir precisamente ese efecto y qeu el ViewState se conserve en la memoria del servidor.


Para ello lo único que hay que hacer es sobreescribir la propiedad PageStatePesister de la página de forma que devuelva una referencia a un objeto de la clase que acabamos de mencionar. Muy sencillo.


Como ejemplo de cómo hacerlo he elaborado un pequeño vídeo que muestra paso a paso y con instrucciones la forma de hacerlo y compara una misma página antes y después de usar esta técnica. El vídeo es del mismo estilo que los que tenemos en campusMVP (aunque allí suelen ser algo más largos y con voz) y lo pongo como muestra del tipo de contenido multimedia que podrás encontrar en nuestros cursos:







Si no ves bien este vídeo pulsa aquí.


Esto es útil para casos en los que el retardo debido al tamaño del ViewState sea grande, pero hay que tener cuidado ya que aunque ganamos mejora en la velocidad de los PostBack perdemos recursos en el servidor puesto que el ViewState se almacena en la RAM de éste y la aplicaión ocupará mucho más.


No se recimienda usar esta técnica para todas las páginas de un sitio o de manera generalizada. Ahora bien, si necestias hacerlo lo tienes muy fácil: creas una página que sobreescriba la propiedad y haces que todas las demás hereden de ésta.


Esta técnica se puede generalizar para crear clases de persistencia propias que en lugar de almacenar el ViewState en sesión lo hagan en una base de datos, archivos, etc… Queda a tu imaginación.


Mañana o pasado pondré una continuación de este post para enseñar cómo podemos conseguir los mismo pero con otra técnica completamente distinta y que además funciona en TODAS las versiones de ASP.NET, desde la 1.0. ¡Hasta pronto!

Problemas al descargar archivos desde IIS 6.0 con Internet Explorer

Este es un tema que me traía de cabeza durante varios días y que no lograba solucionar.


Resulta que hemos colocado una aplicación Web en un servidor Windows 2003 de un cliente. En el directorio raíz de la aplicaicón había un par de archivos .exe que estaban ahí para ser descargados desde un enlace directo. Al intentar descargarlos desde Internet Explorer se quedaba el diálogo «flipado» mientras ponía «Obteniendo información del archivo…», y la descarga no comenzaba jamás.


La configuración del servidor no tenía nada raro. Sólo lo habitual en un IIS, así que no encontraba explicación. Además ocurría en TODOS los IE y en todas sus versiones (incluyendo la última que acaba de salir, la 7), así que no era un problema puntual por un index.dat corrupto o cosas típivcas similares. Un verdadero misterio.


El misterio aumentaba cuando veías que con otros navegadores (por ejemplo Firefox) los archivos bajaban sin problemas y se guardaban. Incluso si veías el tráfico que se generaba con un monitor de tráfico, lo cierto es que el archivo sí se estaba descargando por detrás pero IE parecía no enterarse y se quedaba colgado hasta que unos segundos más tarde daba un error.  !??!!


Probé a sustituirlos por ZIPs e incluso probé con otros tipos de archivos (PDF, DOC y demás) y no había manera. Con IE no bajaba ningún archivo y con Firefox sí :-?. Lo único que se conseguia descargar con Explorer eran páginas HTML, gráficos y páginas ASPX. Un misterio ya que no había motivo alguno. Incluso revisé los tipos MIME y estas cosas, pero nada.


La solución


Sorprendentemente el problema estaba en las cabeceras HTTP que enviaba el servidor. resulta que tenía activada la caducidad inmediata de contenidos para que no se hiciese caché de los elementos de la aplicación:



El caso es que, por lo visto, IE tiene un «bug» que hace que cuando recibe estas cabeceras para no almacenar en caché los archivos tampoco los guarda al disco duro. Por ese motivo no funcionaba. El caso es que, sólo con desmarcar esta opción, automáticamente empezaó a funcionar la descarga de todo tipo de archivos.


Como seguía queriendo que la caché funcionase para el resto de elementos, lo único que hice fue crear una carpeta para las descargas y desactivar la caducidad de contenido en ésta, dejándola activada en el resto del sitio.


En fin, que podía haber estado toda la vida y no encontrar el fallo. Espero que esto le disminuya la angustia al que lo lea si llega aquí haciendo una búsqueda sobre este asunto 🙂

Cómo preservar la batería del portátil si lo usas mucho más en casa que por ahí…

Bueno, esto tiene más bien poco que ver con la programación pero lo comento porque a alguno quizá le resulte interesante.


Yo uso mucho mi portatil, casi a diario. Lo que ocurre es que la mayor parte del tiempo lo hago con él enchufado a la corriente, esté en casa o de viaje (ya que lo enchufas en la oficina del cliente o lo que sea). Eso sí, la mayor parte de las veces lo uso enchufado en mi propia casa.


El problema de esto es que acabas con la batería lentamente. Al cabo de unos meses notas como va perdiendo algo de capacidad y un par de años después la cosa es bastante grave. Las baterías son caras, pero ese no es fundamentalmente el problema. El verdadero problema es que, dependiendo de la marca y modelo del portátil, dos años despues de comprarlo puede resutlar muy dificil o imposible encontrar una batería que le valga, ya que o hay estándar alguno para las mismas y los fabricantes son bastante «cabrones» con estos temas y así se aseguran de que cambias el portátil.


La solución: obviamente trabajar sin ella. Lo malo de esto es que si de repente se va la luz pierdes en lo que estabas trabajando.


La otra solución: quítale la batería pero enchúfalo a un SAI (Sistema de Alimentación Ininterrumpida). Esto que parece una obviedad lo cierto es que hasta hace bien poco no se me había ocurrido (riete tú), y desde hace una temporada lo estoy usando y me va muy bien.


Un SAI normal al que le puedes pinchar sin problemas un portátil o una CPU y un par de monitores cuesta hoy en día unos 40 o 50 euros. Incluso uno de buena calidad como los Riello (foto) que es lo que yo uso, tienen más o menos este precio. Con él tu portátil está protegido contra sobretensiones (que en algunas zonas causan estragos, si no que se lo pregunten a mi hermano que ha fundido dos ordenadores (uno de ellos portatil con batería echufado a la red) y un monitor en 2 meses al cambiarse de residencia a las afueras), te conserva la energía al menos 10 minutos aunque se vaya la luz, y te permite trabajar con las mismas ventajas que con la batería pero sin estropearla si trabajas en un sitio fijo con el portátil (como así es el 90% del tiempo si te paras a pensarlo).


Es una tontería, pero con una mínima inversión proteges tu equipo o equipos y no te cargas la batería que te drará muchos años. Creo que vale la pena usarlo.


Otra cosa: cómprate una regleta que se pueda pinchar a la salida electríca no-convencional del SAI ya que no podrás pinchar el portátil directamente al SAI puesto que la mayoría vienen con el mismo conector que tienen las CPU de sobremesa (así medio rectangular con bordes redondeados) y no te servirá. Súmale 7 u 8 euros a la inversión.

¿Cómo es posible que esto le pase a un banco?

El Banco de Santander (www.gruposantander.es) lleva conla página Web caída desde ayer por la mañana (o sea, ahora casi dos días fuera de servicio) debido a una actualización «pequeña» según ellos. Ello implica que no hay banca electrónica y que tienes que jorobarte y no poder realizar transferencias, consultar la lista de tus cuentas habituales con las que trabajas, etc… Eso incluye a particulares y a empresas.


Es inaceptable que un banco como este pueda permitirse el lujo de estar así y reconocerlo abiertamente. ¿Es que no tienen planes de contingencia? ¿Es que no saben que las pruebas hay que hacerlas en sistemas previos antes de pasarlas a producción? ¿es que…? en fin…


Si a uno de nuestros clientes le hacemos la mitad de esto enaplicaciones que no tienen ni una fracción de la importancia que la que tiene el banco nos crucificarían, y estos señores siguen tan frescos. Es lo mismo que cuando a Iberia se le quemaron los sistemas y paralizó el país hace un par de años: disculpas baratas. No se lo pueden permitir. Y si las autoridades e instituciones del ramo fueran mínimamente competentes deberían multar a este tipo de entidades por estas cosas.


En fin, sólo quería desahogarme un poco porque estas cosas me ponen enfermo :-(((