viernes, 29 de octubre de 2010

Pasos en la publicación de un software

Pues es cierto que hay una entrada maravillosa en wikipedia al respecto http://en.wikipedia.org/wiki/Development_stage, pero la verdad es que yo siempre me hago un lio y si lo tengo aquí y por escrito, pues a lo mejor deshago el entuerto y además de a mi le sirve a alguien más.

Vaya por delante que no soy un gran experto en inglés, así que las traducciones que haga de los términos aquí expuestos serán muy libres y quizás tengan algún fallo, pero la intención es lo que cuenta.

Y antes de empezar, sólo una promesa (que seguro no cumpliré) que es la de seguir un producto desde sus primeros pasos a ver si así en vez de teoría me baso en una experiencia completa y real.

Desde su nacimiento a su distribución y comercialización:

CTP, Community Technology Preview, “Preestreno de la tecnología para la comunidad”, aquí lo que se pretende es recoger el feedback (retroalimentación) de la comunidad de un producto para su evaluación, la norma es que estos productos son públicos y gratis para su descarga, después de todo la intención del creador del software o tecnología propuesta es que la comunidad de usuarios opine, critique y ayude a mejor el producto. En una CTP parte de la funcionalidad que tendrá el producto final podría no estar disponible.

Beta, Versión que recoge cambios y también el feedback obtenido desde la CTP.

RC, Release Candidate, “Lanzamiento candidato”, esto es que ya casi está finalizado el producto (y este tiene ya todas sus características disponibles) y está es la última oportunidad para echarle un vistazo antes de su inminente lanzamiento definitivo.

RTM, Released to Manufacturing, “Lanzamiento para la industria”, ahora el software ya se ha “quemado” en CD/DVD para que los distribuidores hagan caja.

RTW, Released to Web, “Lanzamiento para la web”, esto es que cada vez hay menos soporte físico para la distribución del software (RTM) y cada vez se distribuye más a través de la compra y descarga desde internet.

SP, Service Pack, “Paquete de servicios”, casi me da vergüenza explicarlos, pero es un conjunto de soluciones a problemas (fixes) y/o posibles mejoras (improvements) que se hacen sobre un software después de su primera publicación definitiva. La verdad es que más habitual la corrección de errores que la de incluir nuevas mejoras. Por otro lado, la norma es que los SP son acumulativos, esto es que un SP siempre incluye a todos sus SP precedentes.

La verdad es que hay algún otro término que o es sinónimo o no se donde encaja, como por ejemplo: Preview, Techonoloy Preview, etc.

Un saludo!.

miércoles, 27 de octubre de 2010

Páginas ASP.NET asíncronas

La verdad es que antes de comenzar a explicar como programar una página ASP.NET asíncrona, la pregunta sería ¿Realmente que supone o que valor añadido me da una página asíncrona? y ¿Cuándo utilizar una página asíncrona?. Digo esto porque yo mismo he tenido que experimentar un proceso de entendimiento para encontrar las respuestas a estas preguntas. Al comienzo quería a toda costa hacer “millones” de páginas asíncronas, pero ahora y después de entender cómo funcionan, ya sólo quiero hacer unas “cientas”… ;-)

Desde el punto de vista del rendimiento, una página asíncrona supone liberar hilos del pool de ASP.NET mientras se completa la operación solicitada, y así poder garantizar la escalabilidad de nuestro sitio web porque siguientes peticiones que se produzcan no serán encoladas y podrán ser atendidas de inmediato por los threads libres del pool, que como podrás imaginar es finito y si se acaba… pues se acaba nuestra aplicación (al menos hasta que alguna página libere algún thread y pueda procesar la petición encolada) y tendremos un bonito Error 503.

Si quieres profundizar más en la configuración de los hilos disponibles en el pool de IIS, visita el siguiente enlace http://blogs.msdn.com/b/tmarq/archive/2007/07/21/asp-net-thread-usage-on-iis-7-0-and-6-0.aspx

De este modo, la ventajas de las página asíncronas están claras, pero ¿Cuándo utilizarlas? pues cuando tengamos operaciones que puedan ser lentas y sobretodo se presten a ser ejecutadas de forma asíncrona. Esto significa que, en principio, operaciones como consultas a bases de datos, lectura y escritura de ficheros, invocación de servicios web, envío de correos, etc. se prestan a ser asíncronas pero sobretodo “pueden” ser asíncronas, es decir, tienen métodos Begin<Operación> (que comienzan la operación de forma asíncrona y devuelven de inmediato el control a la aplicación) y tienen métodos End<Operacion> (que se invocan mediante un delegado al finalizar la operación asíncrona e informan sobre el resultado de la operación).

Esto quiere decir que si no hacemos nosotros mismos la implementación de un modelo asíncrono para nuestras clases (que poder se puede y no es tan complica, ver IAsyncResult en http://msdn.microsoft.com/en-us/library/ms228963.aspx), ”sólo” las clases que nos brinden esta característica serán susceptibles de ser utilizadas de forma asíncrona.

De momento y que yo tenga constancia o que haya querido utilizar en algún momento:

  • System.IO
  • System.Net
  • Proxies de servicios web
  • SqlClient

Otra cosa a tener en cuenta es como “percibe” el usuario una página asíncrona:

  • Comienza a cargar la página
  • La página se queda “en cargando” un buen rato mientras se completa la operación asíncrona
  • Finalmente se renderiza la página y el usuario obtiene un resultado visible

Con esto quiero decir que una página .aspx no es un formulario de Windows Forms con un botón cancelar, con una UI que sigue respondiendo, etc, sino que la página se queda “congelada” y “esperando”…

Vale que también podemos hacer una petición AJAX y así no vemos una bonita página en blanco, pero si vamos por la vía de la página .aspx con una petición síncrona (quiero decir un PostBack síncrono, perdón por liar las cosas) el comportamiento descrito será el obtenido.

Realmente y desde el punto de vista del ciclo de vida de una página .aspx, lo que ocurre es que la página se ejecuta normalmente hasta el evento PreRender, momento en el que se lanza la operación asíncrona y queda la página a la espera de la finalización de la operación lanzada. Una vez finalizada la operación se retoma el restante ciclo de vida de la página y la misma finaliza ya con normalidad.

Otro factor a tener en cuenta y que a mi personalmente me ha costado “asimilar” es ¿Puedo lanzar un super-proceso del que no tengo un tiempo estimado claro de finalización en una página .aspx (por ejemplo un job de sql server que puede tardar 2 horas)? Pues yo diría que lo vamos a intentar, pero que a priori una página .aspx no parece el mejor lugar para ello, así que yo te recomendaría que mejor no lo intentes (avisado quedas). Por favor, que tu petición asíncrona sea lenta no significa que pueda ser infinita. Yo personalmente, si una página se carga y en un tiempo razonable no me ha dado una respuesta, me empiezo a poner nervioso… y acabaré dando F5, cerrando el navegador o cualquier otro perrería por la que el programador se acordará de mí ;-)

Pasos para hacer una página asíncrona

  • Incluir el atributo Asyn=”true” en la directiva Page.
    • Esto hace que la página implemente IHttpAsyncHanlder en vez de HttpHandler.
  • Utilizar uno de los siguientes modelos de programación asíncrona disponibles: 
    • AddOnPreRenderCompleteAsync
    • RegisterAsyncTask

Con cualquiera de los métodos expuestos el concepto a lograr es el mismo: Registrar una operación asíncrona que se ejecutará antes de renderizar la página, es decir, antes del evento Page_PreRenderComplete.

Con el primer método (AddOnPreRenderCompleteAsync) sólo registramos 1 operación asíncrona, mientras que con el segundo (RegisterAsyncTask) podemos registrar varias operaciones asíncronas. Aunque con AddOnPreRenderCompleteAsync podríamos encadenar manualmente varias operaciones asíncronas, yo personalmente prefiero el modelo propuesto por RegisterAsyncTask.

Como ya hemos dicho antes, necesitamos algo que se preste a ser asíncrono, es decir, alguna operación que haya implementado el patrón de programación asíncrona propuesto por .NET (IAsyncResult y los métodos Begin<Operation> y End<Operation>) así que para nuestro ejemplo vamos a utilizar el método BeginExecuteNonQuery de SqlCommand.

Para ello tendremos inicialmente el siguiente código en nuestra página:

    Dim _connection As SqlClient.SqlConnection

    Dim _command As SqlClient.SqlCommand

 

    Function BeginAsyncOperation( _

        ByVal sender As Object, _

        ByVal e As EventArgs, _

        ByVal cb As AsyncCallback, _

        ByVal state As Object) As IAsyncResult

 

        Dim connectionString As String = _

            ConfigurationManager.ConnectionStrings.Item("AdventureWorksLT2008ConnectionString").ConnectionString

        Dim sqlConnectionStrinbBuilder As New SqlClient.SqlConnectionStringBuilder(connectionString)

        ' AsynchronousProcessing es obligado si queremos lanzar comandos asíncronos contra Sql Server

        sqlConnectionStrinbBuilder.AsynchronousProcessing = True

        _connection = New SqlClient.SqlConnection(sqlConnectionStrinbBuilder.ToString)

        _connection.Open()

        _command = New SqlClient.SqlCommand("GetCustomers", _connection)

        _command.CommandType = CommandType.StoredProcedure

        ' La siguiente sentencia devuelve inmediatamente el control al código

        Dim result As IAsyncResult = _command.BeginExecuteNonQuery(cb, state)

        Return result

    End Function

 

    Sub EndAsyncOperation(ByVal ar As IAsyncResult)

        Try

            ' Recuperar el comando que lanzó BeginExecuteNonQuery

            Dim command As SqlClient.SqlCommand = CType(ar.AsyncState, SqlClient.SqlCommand)

            ' Finalizar llamada asíncrona

            command.EndExecuteNonQuery(ar)

            command.Dispose()

            command.Connection.Dispose()

        Catch ex As Exception

            'Si hubo errores en BeginExecuteNonQuery, lo sabremos aquí y siempre después de haber llamado a EndExecuteNonQuery, sino y al haber sido ejecutada la llamada asíncrona en otro Thread, la excepción se habrá producido pero en “ESTE THREAD ACTUAL” jamás lo sabremos

        End Try

    End Sub

 

De este código podemos comentar lo siguiente:

  • Las variables de conexión y comando son miembros privados a nivel de clase porque en la función de finalización de la operación asíncrona tenemos que seguir teniendo una referencia a las mismas para llamar al método Dispose.
  • Es necesario incluir el atributo AsynchronousProcessing en la cadena de conexión contra nuestro Sql Server si queremos lanzar operaciones asíncronas.

 

Ahora implementemos la opción 1, esto es AddOnPreRenderCompleteAsync

 

Para ello y en nuestro Page_Load o en cualquier evento de usuario de un control (por ejemplo btnBoton_Click) pondremos el siguiente código:

 

Dim metodoInicial As New BeginEventHandler(AddressOf BeginAsyncOperation)

 

Dim metodoFinal As New EndEventHandler(AddressOf EndAsyncOperation)

 

AddOnPreRenderCompleteAsync(metodoInicial, metodoFinal)

 

Lo que hacemos aquí es:

  • Declarar una variable del tipo BeginEventHandler y otra del tipo EndEventHandler (ambos tipos son delegados)
  • Registrar la operación asíncrona que será llamada automáticamente antes del evento PreRender_Complete.

Si vamos por el camino de RegisterAsyncTask, entonces tenemos que añadir otra función más y es para controlar un posible timeout de la llamada asíncrona (tranquilo que después hablaremos más sobre el timeout) :

 

    Sub TimeoutAsyncOperation(ByVal ar As IAsyncResult)

        ' Finalizar llamada asíncrona

        _command.EndExecuteNonQuery(ar)

        _command.Dispose()

        _connection.Dispose()

    End Sub

 

Y ahora ya podemos registrar las operaciones asíncronas (las que queramos puesto que pueden ser más de una):

 

        Dim metodoInicial As New BeginEventHandler(AddressOf BeginAsyncOperation)

 

        Dim metodoFinal As New EndEventHandler(AddressOf EndAsyncOperation)

 

        Dim metodoTimeout As New EndEventHandler(AddressOf TimeoutAsyncOperation)

 

        Dim tarea As New PageAsyncTask(metodoInicial, metodoFinal, metodoTimeout, Nothing)

 

        RegisterAsyncTask(tarea)

 

Lo que hacemos aquí es:

  • Declarar una variable del tipo BeginEventHandler, y otras dos del tipo EndEventHandler.
  • Registrar las operaciones asíncronas.

Entonces ¿Cuales son las diferencias entre AddOnPreRenderCompleteAsync y RegisterAsyncTask?

Lo cierto es que RegisterAsyncTask gana por goleada:

  • Se puede controlar un timeout de la operación asíncrona porque, bien a través del atributo AsyncTimeout de la directiva page o bien durante el registro de la operación asíncrona, se puede especificar un valor de timeout en segundos. Todo esto en contraste con AddOnPreRenderCompleteAsync que no tiene en cuenta este valor de timeout.
  • Se pueden llamar a varias operaciones asíncronas sin necesidad de ir encadenándolas (imagínate con AddOnPreRenderCompleteAsync esperando a que acabe una con el método EndAsyncOperation para comenzar otra… uff, mejor múltiples RegisterAsyncTask)
  • RegisterAsyncTask permite pasar un parámetro de estado a los métodos Begin (esto puede ser útil para compartir información entre operaciones)
  • Con RegisterAsyncTask en los métodos End y Timeout está disponible el contexto (HttpContext.Current), la cultura de la página, la impersonalización, etc. mientras que en AddOnPreRenderCompleteAsync no está disponible.
  • Posibilidad de controlar cuando comenzar la operación asíncrona con el método ExecuteRegisteredAsyncTasks (Por defecto recordar que las operaciones asíncronas se ejecutaran después del evento PreRender y antes del evento PreRenderComplete)

Una aclaración al respecto de registrar varias tareas asíncronas con RegisterAsyncTask es que es conveniente saber que no se pisan unas a otras, esto es que primero se espera a completar la primera operación asíncrona registrada para inmediatamente comenzar con la segunda y así sucesivamente. Bueno en realidad este comportamiento lo podemos configurar a la hora de registrar la tarea con el parámetro executeInParallel que por defecto es False.

Otra aclaración es que si intentamos registrar una operación asíncrona con cualquier de los 2 métodos válidos y lo hacemos después del evento PreRenderComplete no se tendrá en cuenta y no se ejecutará.

Timeouts

Lo último que quiero decir sobre este modelo de programación asíncrona de páginas .aspx es que tienes que tener en cuenta los timeouts “varios” que intervienen en el proceso y su forma de comportarse:

Para establecer el tiempo que una página .aspx puede estar procesando antes de fallar por un timeout, tenemos disponible:

  • httpRuntime.executionTimeout en el web.config
  • Server.ScriptTimeout (que en la representación del anterior valor pero a nivel de página)

Al respecto de Server.ScriptTimeout te diré que si lo cambias en el código de una página “sólo” afectará a esa página, da igual lo que diga la documentación, te lo digo yo y tú te lo crees ;-)

Cualquier de los anteriores valores no se tienen en cuenta si debug=”true” en el web.config, bueno en realidad se tienen en cuenta pero es que ASP.NET los pone automáticamente con el valor 30000000, casi 1 año!

Por defecto el valor de httpRuntime.executionTimeout es de 110 (pero tampoco te fíes mucho porque me parece a mi que según versión de ASP.NET puede variar ligeramente).

¿Y me importan estos valores cuando hablo de operaciones asíncronas? Pues yo creo que NO.

De hecho el valor que te importa es AsyncTimeout (por defecto 45 y que es independiente de si está o no activa la depuración).

También decirte que AsyncTimeout no es por llamada asíncrona, sino para “todas” las llamadas asíncronas que haya en la página y que realmente lanza el método TimeoutAsyncOperation, pero es más, aunque falle por ejemplo por timeout la segunda tarea registrada de tres, ASP.NET seguirá lanzado la tercera tarea para dar automáticamente otro TimeoutAsyncOperation (elemental!), pero que no por ello ha dejado de lanzarse el comando y tampoco pensemos que porque llamemos a EndExecuteNonQuery en el manejador de Timeout estamos cancelando el comando… VAMOS, UN POCO CUTRE, luego la pregunta ¿Habiéndome dado un primer timeout como paro la sangría de operaciones asíncronas que irremediablemente darán otro timeout automático?

Pues te comento que la única solución es que las clases que utilizamos para la llamada asíncrona tengan un método Cancel() o algo parecido, por ejemplo para SqlCommand.Cancel() pero me da a mi que no es muy definitivo. Pues ver más información al respecto en http://www.pluralsight-training.net/community/blogs/mike/archive/2005/11/04/16213.aspx

Ya para terminar y porque llevo 2 días con este post, hay un tercer método un poco más “salvaje” pero igualmente efectivo que básicamente consiste en pasar de cualquiera de los métodos propuestos y hacerlo un poco a la bravas. De hecho con este método no se lanza la operación asíncrona antes de PreRenderComplete sino que la página se devuelve al cliente por completo (incluso se lanza Page_Unload) y después y al rato (cuando haya finalizado la tarea asíncrona) se procesa la vuelta (incluso si el cliente cerro el navegador por ejemplo).

De hecho, no quiero decir ninguna tontería pero, de este modo, si se podría lanzar una tarea de la que no sabemos cuanto tiempo tardará, de hecho este método no tiene cuenta AsyncTimeout así que le da un poco igual…

Para empezar no es necesario especificar Async = True, y además se ve como simplemente se llama a la operación asíncrona como si fuera casi un formulario de Windows. A mi esto me parece un poco descontrol y lo desaconsejo, pero…

        Dim connectionString As String = ConfigurationManager.ConnectionStrings.Item("AdventureWorksLT2008ConnectionString").ConnectionString

        Dim sqlConnectionStrinbBuilder As New SqlClient.SqlConnectionStringBuilder(connectionString)

        sqlConnectionStrinbBuilder.AsynchronousProcessing = True

        Dim connection As New SqlClient.SqlConnection(sqlConnectionStrinbBuilder.ToString)

        connection.Open()

        Dim command As New SqlClient.SqlCommand("COMANDO", connection)

        command.BeginExecuteNonQuery(AddressOf EndAsyncOperation, Nothing)

Por último comentarte que la programación asíncrona en Web Forms no sólo se limita a formularios web (.aspx) sino que también es muy sencillo implementar la asincronía en controladores genéricos (.ashx).

Un saludo!.

Biblografía

http://msdn.microsoft.com/en-us/magazine/cc163725.aspx

http://www.pluralsight-training.net/community/blogs/mike/archive/2005/11/04/16213.aspx

GAC en Windows7

Hola, estos días he tenido que trastear con el GAC en un Windows7 y he visto que ya no hay ninguna herramienta para gestionar el GAC en herramientas administrativas (como la había en Windows XP), de este modo, en Windows7 las operaciones disponibles para operar con el GAC son:

  • Ver el GAC
    • Tan sencillo como navegar a C:\Windows\assembly
  • Instalar un ensamblado en el GAC
    • Pues arrastrar y soltar el ensamblado en la carpeta C:\Windows\assembly
  • Desinstalar un ensamblado del GAC
    • Click derecho > Eliminar en un ensamblado desde la carpeta C:\Windows\assembly

Un saludo!.

domingo, 24 de octubre de 2010

Emuladores de dispositivos móviles

Hola, ahora que he visto que jQuery ha sacado jQuery Mobile, me he puesto a pensar y he dicho: vale, tengo un iPhone 3G y un Samsung Galaxy S, pero anda que no hay montones de dispositivos más que probar y testear si quieres hacer una aplicación móvil y ver como funcionan en todos los distintos dispositivos que hay en el mercado, solución… emuladores, que la verdad es que ni sabía que existían pero aquí están.

jQuery Mobile promete ser una librería device-cross-browser (este término me lo acabo de inventar pero seguro que se entiende) en el que han participado numerosos fabricante.
http://jquerymobile.com/

iPhone
http://www.testiphone.com/

Nokia
http://www.forum.nokia.com/info/sw.nokia.com/id/db2c69a2-4066-46ff-81c4-caac8872a7c5/NMB40_install.zip.html

BlackBerry
http://www.blackberry.com/developers/downloads/simulators/index.shtml

Android
http://developer.android.com/guide/developing/tools/emulator.html

Opera mini
http://www.opera.com/mobile/demo/

Mobilizer
http://www.springbox.com/mobilizer/

Hay más dispositivos (por ejemplo Windows7 que está al caer, Palm, etc.) pero yo creo que con iPhone, Android, Windows 7 – del que aún no he encontrado ningún emulador definitivo - y BlackBerry es suficiente.

Un saludo!.

miércoles, 20 de octubre de 2010

Test de navegadores (II) – Android

Pues me ha dado por ver como pasaría los test Acid y CSS el navegador de mi teléfono con Android 2.1 (así cuando quiera que se actualice a 2.2 puedo volver a testearlo de nuevo). Ahí van los resultados tanto para 2.1 como para 2.2 (que ya he actualizado y los resultados son los mismos):

El test de CSS3 http://tools.css3.info/selectors-test/test.html todo OK, 100%.

El test de Acid3 http://acid3.acidtests.org/ arroja un resultado de 93/100, casi completo pero en cualquier caso me parece suficiente para un dispositivo móvil.

Y por último el test de Acid2 http://www.webstandards.org/files/acid2/test.html lo pasa de “aquella manera”…

image

Un saludo!.

Intellisense en ficheros .skin en Visual Studio

Mini-post, sólo decirte que vayas a este otro donde post donde se explica perfectamente como habilitar el intellisense en los ficheros .skin de Visual Studio http://geeks.ms/blogs/gtorres/archive/2010/02/08/intellisense-para-archivos-skin.aspx

Un saludo!

martes, 19 de octubre de 2010

Depuración activa en ASP.NET?

Hoy quería saber cómo condicionar cierto código en un sitio web o aplicación web, según si está o no la depuración activa.

Para ello, he empezado leyendo este post
http://www.west-wind.com/Weblog/posts/10228.aspx  del que he sacado algunas ideas.

Básicamente tenemos disponibles los siguientes métodos y propiedades para detectar en tiempo de ejecución si nuestra aplicación está o no en modo depuración… que por cierto nunca en producción debería estar en depuración y si no te lo crees, léete esto y me dirás http://weblogs.asp.net/scottgu/archive/2006/04/11/442448.aspx

IsDebuggingEnabled
http://msdn.microsoft.com/en-us/library/system.web.httpcontext.isdebuggingenabled.aspx

Debugger.IsAttached
http://msdn.microsoft.com/en-us/library/system.diagnostics.debugger.isattached.aspx

IsDebuggingEnabled es simplemente un wrapper para no tener que leer directamente el valor desde el web.config con algo parecido a esto (que también nos valdría pero ya son ganas…)

Configuration.ConfigurationManager.GetSection('system.web/compilation').Debug

Debugger.IsAttached tampoco es definitivo porque no queremos saber si hay un depurador asociado al proceso (esto es que estamos depurando por ejemplo desde el IDE), sino si estamos en modo depuración.

Tanto en un sitio web como en una aplicación web y sin importar la configuración activa (esto es bien Debug para sitio web, bien Debug o Release para una aplicación web).

  • ·        F5 + con debug=”true” en web.config
  • IsDebuggingEnabled = True
  • Debugger.IsAttached = True
  • ·        Ctrl + F5 + con debug=”true” en web.config
  • IsDebuggingEnabled = True
  • Debugger.IsAttached = False
  • ·        Ctrl + F5 + con debug=”false” en web.config
  • IsDebuggingEnabled = False
  • Debugger.IsAttached = False

De lo anterior se deduce que la propiedad que nos interesa es IsDebuggingEnabled, así que:

        If Context.IsDebuggingEnabled Then

            '  modo de depuración activo

        Else

            '  modo de depuración no activo

        End If

Sólo nos queda hablar de #If DEBUG, pero la verdad es que no hay mucho que hablar puesto que en VB no funciona, pero si en C#... y sólo mencionar que en C# no importa cuál sea el valor de debug en el web.config, puesto que se guía exclusivamente por la versión de configuración activa (Debug o Release).

Y un último apunte es que si te fijas, aún cuando compilas en modo Release, se generan ficheros .pdb y entonces ¿los puedo quitar? ¿Está bien que los quite? Yo personalmente los voy a quitar, pero literatura al respecto y mil discusiones hay por internet:

http://forums.asp.net/p/1539298/3745787.aspx

http://gchandra.wordpress.com/2008/02/22/disable-pdp-file-generation-in-release-mode/

http://geekswithblogs.net/SudheersBlog/archive/2006/09/22/92054.aspx

clip_image002

Un saludo!

sábado, 16 de octubre de 2010

Test navegadores

Hoy me ha dado por pasar todos los test que he encontrado disponibles para los navegadores actuales. De las pruebas y resultados obtenidos se puede sentenciar que IE8 y Firefox son los peor parados (ahora ya con las nuevas versiones, IE9 y Firefox4 ya no), mientras que Chrome, Opera y Safari parecen que hacen bien sus deberes y cumplen al 100% con los estándares.

El último apunte es para IE9 que parece que por fin (y aunque esto ya parece el cuento de la lechera) se ha puesto las pilas y está casi a nivel, ya veremos, hasta que no lo veo no lo creo.

CSS3

http://tools.css3.info/selectors-test/test.html

  • IE9 - OK
  • IE8
    • “From the 41 selectors 20 have passed, 1 are buggy and 20 are unsupported (Passed 345 out of 574 tests)”
  • Firefox 4 - OK
  • Firefox 3.6.10
    • “From the 41 selectors 20 have passed, 1 are buggy and 20 are unsupported (Passed 345 out of 574 tests)”
  • Google Chrome - OK
  • Opera - OK
  • Safari (tanto el de escritorio como el iPad 1) - OK

ACID3

http://acid3.acidtests.org/

  • IE9 95/100 100/100
  • IE8 – 20/100
  • Firefox 7 – 100/100
  • Firefox 4– 97/100
  • Firefox 3.6.10– 94/100
  • Google Chrome – 100/100
  • Opera – 100/100
  • Safari (tanto el de escritorio como el iPad 1) - 100/100

ACID2

http://www.webstandards.org/files/acid2/test.html

  • IE9 - OK
  • IE8
  • image
  • Firefox– OK
  • Google Chrome – OK
  • Opera – OK
  • Safari – OK
  • iPad1

ACID1

http://www.w3.org/Style/CSS/Test/CSS1/current/test5526c.htm

Un saludo!

lunes, 11 de octubre de 2010

Mis extensiones favoritas

Ya sea a modo de recordatorio o bien por si algún perdido llega navegando a este blog, voy a enumerar las extensiones de Visual Studio que yo utilizo y que me dan algún valor añadido a mi gran y querido IDE.

JSEnhancements
http://visualstudiogallery.msdn.microsoft.com/en-us/0696ad60-1c68-4b2a-9646-4b5f4f8f2e06?SRC=VSIDE

“Añade esquematización a los ficheros .js y .css, además de soportar #region”

Javascript Parser
http://visualstudiogallery.msdn.microsoft.com/en-us/288a2b0f-1357-47b4-8215-1134c36bdf30

“Añade una ventana con una lista de las funciones javascript del documento para facilitar la navegación entre las mismas”

devColor
http://visualstudiogallery.msdn.microsoft.com/en-us/7dbae8b3-5812-490e-913e-7bfe17f47f1d

Pequeña utilidad para ver los colores en los ficheros .css, muy útil!”

StructureAdornment
http://visualstudiogallery.msdn.microsoft.com/en-us/203f22f4-3e9f-4dbb-befc-f2606835834e

Un must-have, líneas verticales para seguir la estructura de los bloques de código”

ItalicComments

“Pone los comentarios en cursiva…vale, no hace más productivo, pero me aburro menos al leer los comentarios…”

Comments Extender

http://visualstudiogallery.msdn.microsoft.com/17c68951-7743-40bd-ad35-608706f54a92?SRC=VSIDE

Esto es ya es para rizar el rizo en lo relativo a comentarios, casi me da vergüenza esta extensión porque es puro adorno para los comentarios, pero insisto es que sino me aburro y de este modo justifico la presencia de comentarios…

VS10x Code Map

“Similar a Javascript Parser pero con histórico, ordenación etc.. facilita la visualización de métodos de una clase”.

Snippet Designer
http://snippetdesigner.codeplex.com/

“Añade creación y manipulación sencilla de snippets desde el propio IDE”.

OutLineRegionMarge
http://visualstudiogallery.msdn.microsoft.com/96f0b449-3809-49bf-9af1-a89cd8300ded/view/Reviews

“Colapsar y expandir bloques de código en Visual Basic.NET”.

RegEx Tester
http://visualstudiogallery.msdn.microsoft.com/en-us/16b9d664-d88c-460e-84a5-700ab40ba452

“Añade soporte para probar y crear expresiones regulares también desde el propio entorno”.

Aunque no sea una extensión al uso, también utilizo:

Por otro lado y hablando sobre SQL Server Management Studio también nos resulta útil en la oficina las herramientas de redgate:

Intentaré ir actualizando este post para reflejar las extensiones que vaya instalando y que sean útiles y me gusten.

Un saludo!.

jueves, 7 de octubre de 2010

Herramientas on-line

Pues a modo de recordatorio para mi mismo y para quien le interese, aquí dejo algunos enlaces de herramientas web útiles para un programador .NET.

Programación
https://dotnetfiddle.net/
http://csharppad.com/
http://jsperf.com/
http://jsfiddle.net/

Expresiones regulares
http://gskinner.com/RegExr/
http://txt2re.com/
http://www.regexpr.com/
http://regexlib.com
http://www.regexper.com/

Generador de imágenes para el típico “cargando…” de ajax
http://ajaxload.info/

Formateador y optimizador de CSS
http://www.cuervoblanco.com/csstidy/css_optimiser.php

Formateadores de sentencias SQL
http://www.sqlinform.com/online.phtml
http://www.dpriver.com/pp/sqlformat.htm

Traductor de C# a VB y viceversa
http://converter.telerik.com/

Temas para Visual Studio
http://studiostyles.info/

Generador de machineKey
http://aspnetresources.com/tools/machineKey
http://www.eggheadcafe.com/articles/GenerateMachineKey/GenerateMachineKey.aspx

Codificar/Descodificador en Base64
http://www.motobit.com/util/base64-decoder-encoder.asp
http://ostermiller.org/calc/encode.html

Generador de MD5
http://www.adamek.biz/md5-generator.php

Decodificador de ViewState
http://lachlankeown.blogspot.com/2008/05/online-viewstate-viewer-decoder.html
http://ignatu.co.uk/ViewStateDecoder.aspx

Correo rápido y anónimo
http://www.yopmail.com

Traductor de reglas CSS a lenguaje humano
http://gallery.theopalgroup.com/selectoracle/

Lorem ipsum
http://www.lipsum.com/ (texto)
http://www.lorempixum.com/ (imágenes)
http://www.picksumipsum.co.uk/ (textos graciosos)
http://hhhhold.com/ (imágenes)

Screenshots en distintos exploradores
http://browsershots.org/

Traducción de ficheros de recursos (.resx) a través de google y bing
http://resxgen.odelvalle.com

Traductor de texto, binario, hexadecimal, decimal, octal, base64, etc.
http://redir.dasumo.com/hex/

Creador de temas para jQuery UI.
http://jquit.com/

Cálculo de especifidad CSS
http://specificity.keegan.st/
http://css-specificity.webapp-prototypes.appspot.com/
http://josh.github.com/css-explain/

Icon
http://thenounproject.com/
http://www.iconfinder.com/
http://iconlet.com/
http://www.iconwanted.com/
http://iconmonstr.com/
http://dakirby309.deviantart.com/art/Metro-Uinvert-Dock-Icon-Set-678-Icons-294529071
http://speckyboy.com/2012/12/17/top-50-free-icon-sets-from-2012/
http://one-div.com/
http://www.iconsdb.com/
http://www.endlessicons.com/
http://findicons.com/
http://www.flaticon.com/
http://flaticons.net/
http://inspiretrends.com/collection-of-free-flat-icons-pack/

Texturas
http://www.cssblog.es/24-sitios-de-texturas-gratis-para-diseno-web/
http://www.noisetexturegenerator.com/

Key Code Checker (Javascript)
http://www.west-wind.com/weblog/posts/2011/Dec/08/A-Key-Code-Checker-for-DOM-Keyboard-Events

Convertir pixeles a porcentaje
http://responsv.com/flexible-math/

Comprimir CSS
http://www.csscompressor.com/

Validar Javascript
http://jslint.com/
http://www.jshint.com/

Generador JSON
http://www.json-generator.com/

GIF
http://gif-explode.com/

HTML5/CSS3
http://webdirections.org/tools/ (herramientas)
http://css3button.net/ (botones)
http://css3buttongenerator.com/ (botones)
http://www.cssdrive.com/css3button/ (botones)
http://button.csscook.com/ (botones)
http://www.patternify.com/ (imágenes con patrón)
http://csslayoutgenerator.com/ (layouts)
http://www.colorzilla.com/gradient-editor/ (degradados)
http://css3generator.com/ (herramientas)
http://www.css3generator.in/ (herramientas)
http://css3gen.com/ (herramientas)
http://css3please.com/
http://layerstyles.org/ (cajas)
http://border-image.com/ (imágenes)
http://css3pie.com/ (cajas)
http://matthewlein.com/ceaser/ (animaciones)
http://www.fontsquirrel.com/fontface/generator/ (fuentes)
http://www.wordpressthemeshock.com/css-drop-shadow/ (cajas)
http://border-radius.com/ (bordes redondeados)
http://css-tricks.com/examples/ButtonMaker/ (botones)
http://gradients.glrzad.com/ (degradados)
http://www.cssmatic.com/ (herramientas)
http://prefixmycss.com/ (prefijos de vendedores)
http://codepen.io/dcullen/pen/AFtCJ (botones awesómicos para epilépticos)

Tamaños de pantalla y resoluciones
http://screensiz.es/phone
http://i-skool.co.uk/mobile-development/web-design-for-mobiles-and-tablets-viewport-sizes/

Checklist
http://webdevchecklist.com/

Bootstrap
http://www.layoutit.com/

Un saludo!

lunes, 4 de octubre de 2010

Sitio web o aplicación web

Diferencias entre sitio web y aplicación web

Antes de comenzar y para no llevar a engaño a nadie, copio literalmente un texto que me parece bastante determinante:

“No hay ninguna diferencia de rendimiento entre un proyecto de sitio web y un proyecto de aplicación web.”
http://msdn.microsoft.com/es-es/library/dd547590.aspx

A partir de aquí, utilizar un sitio web o una aplicación web ya es decisión nuestra en función de sus ventajas o desventajas.

Archivo > Nuevo > Sitio web…

clip_image002

Archivo > Nuevo > Proyecto…

clip_image004

La primera diferencia es donde guarda los ficheros de forma predeterminada Visual Studio 2010 según el tipo de proyecto.

·        Sitio web.

o   Carpeta para el sitio web dentro de C:\Users\<Usuario>\Documents\Visual Studio 2010\WebSites.

o   1 fichero .sln dentro de C:\Users\<Usuario>\Documents\Visual Studio 2010\Projects.

·        Aplicación web.

o   Sólo 1 carpeta que contiene tanto la aplicación como 1 fichero .sln y 1 fichero .vbproj, dentro de C:\Users\<Usuario>\Documents\Visual Studio 2010\Projects.

 

Sitio web

Aplicación web

Archivo de proyecto

No hay. Todos los ficheros dentro de la carpeta del sitio web se incluyen automáticamente en el sitio.

Existe un fichero vbproj o csproj que almacena la lista de ficheros incluidos.

Excluir archivos del proyecto (menú contextual
Excluir del proyecto”)

Agrega la extensión .exclude

No agrega ninguna extensión al fichero, simplemente actualiza el archivo de proyecto (vbproj) para no incluirlo.

Archivo copiado en la carpeta de proyecto

Lo agrega automáticamente.

No lo agrega automáticamente. Es necesario pulsar la opción “Incluir en proyecto” en el menú contextual.

 

Una ventaja de usar archivos de proyecto en los proyectos de aplicación web es la siguiente:

“Es fácil quitar archivos del sitio temporalmente pero, aun así, asegúrese de no perder el control sobre ellos, dado que permanecen en la estructura de carpetas. Por ejemplo, si una página no está lista para implementarla, puede excluirla temporalmente de la compilación sin eliminarla de la estructura de carpetas. Puede implementar el ensamblado compilado y, a continuación, incluir de nuevo el archivo en el proyecto. “

Una ventaja de usar la estructura de carpetas sin archivos de proyecto en los proyectos de sitio web es la siguiente:

“No tiene que administrar la estructura del proyecto exclusivamente en Visual Studio. Por ejemplo, puede copiar archivos en el proyecto o eliminarlos de este mediante el Explorador de Windows.”

http://msdn.microsoft.com/es-es/library/dd547590.aspx

En cualquier caso, la funcionalidad de “Excluir archivos de proyecto” es igualmente válida con independencia del tipo de proyecto elegido. Esto es, si alguna página falla y queremos excluirla, podremos hacerlo en ambos tipos de proyecto.

 

Nuevo WebForm…

Default.aspx

·        Default.aspx.vb

WebForm1.aspx

·        WebForm1.designer.vb

·        WebForm1.aspx.vb

 

El fichero .designer.vb es un fichero autogenerado que no deberíamos nunca editar puesto que los cambios se perderían en un nuevo proceso de generación del fichero. En este fichero encontramos las declaraciones de los controles utilizados en el web form. Si alguna vez nos ocurre que hemos incluido un control en nuestro formulario pero no aparece en el fichero .designer.vb, la solución más rápida y efectiva parece ser borrar el fichero .designer.vb y en el menú contextual del formulario web pulsar la opción “Convertir en aplicación web” que volverá a crear el fichero .designer.vb con su contenido actualizado.

 

Clase de nuevo WebForm…

Nuevo Servicio Web…

[<Carpeta1>_][<CarpetaN_]_Default

En fichero .asmx se crea en la ubicación seleccionada, pero el fichero .vb se crea en el directorio App_Code.

WebForm1

Ambos ficheros se crean en la ubicación seleccionada.

 

Como vemos en la característica anterior, un sitio web crea un nuevo web form con una clase subyacente cuyo nombre es la lista de directorios concatenados más el nombre del fichero. De este modo, en un sitio web “no debería” haber nunca nombres de clases repetidos.  Por otro lado, esta convención de nombre de clase tiene el problema de que si se cambia de carpeta un web form, entonces el nombre de la clase ya no refleja su ubicación verdadero en el sitio.

Respecto a las aplicaciones web y puesto que no se antepone antes del nombre de clase ninguna información relativa a la carpeta donde está ubicado el elemento, podría pasar que hubiera nombres de clase repetidos. Por ejemplo, un web form Default.aspx en 2 carpetas distintas. Para solucionar esto, Visual Studio agrega un sufijo numérico al nombre de clase, de modo que en el ejemplo anterior tendríamos la clase _Default y _Default1.

 

Modelo de código

CodeFile

CodeFile="Default.aspx.vb" Inherits="Carpeta1_Default"

En un sitio web la clase Carpeta1_Default es parcial (que se une en tiempo de compilación con la clase del marcado), mientras que en una aplicación web la clase EsppacioDeNombres.Raiz._Default no es parcial.

CodeBehind

CodeBehind="Default.aspx.vb" Inherits="EspacioDeNombresRaiz._Default"

 

También es interesante observar que una aplicación web crea un espacio de nombres, mientras que un sitio web no lo crea. Por ello, en la aplicación web, el web form hereda de “<Espacio de nombres raíz>.<Clase>”.

 

App_Code

Es en la única carpeta (también en sus subcarpetas) donde se pueden guardar ficheros .vb.

Se puede guardar un fichero .vb en cualquier sitio del proyecto y compilará sin problemas.

Transportar el proyecto entre máquinas

Se puede abrir desde Visual Studio simplemente abriendo la carpeta principal del sitio web. Es fácil de transportar entre equipos de desarrollo.

Es necesario el archivo de proyecto (.vbproj o .csproj).

En mi opinión es más fácil de transportar este tipo de proyecto porque desde el principio (durante su creación) ya Visual Studio guarda todo lo necesario en una sola carpeta.

Compilación

Genera 1 fichero .dll por cada página, control, etc (si se especifica, sino 1 por carpeta, ver más abajo el punto “Publicación de sitio web”)

Se genera 1 sólo fichero .dll con toda la aplicación (páginas, controles de usuario, código del proyecto de la aplicación web, etc.)

 

Compilación - Rendimiento

Es complicado determinar que es más óptimo en términos de rendimiento, si 1 fichero .dll por página/carpeta (sitio web) o 1 sólo fichero para toda la aplicación (aplicación web). La primera solución es mejor si una navegación típica por nuestro sitio no implica cargar todas las páginas (sólo se carga lo necesario), sin embargo es mejor la segunda si por norma se navegará por todas las páginas (mejor cargar todo y así después no habrá tiempos de demora por cargar cada .ddl por separado).

Además, en memoria ocupa menos 1 .dll para toda la aplicación que lo que ocuparían todas las .ddl por página sumadas al final.

Por otro lado, también es cierto que 1 sólo fichero .dll para toda la aplicación tardará más en cargar la primera vez en memoria, pero a la larga será más rápido que esperar a cargar 1 .dll por página siempre la primera vez que se visita esa página.

No quiero olvidar decir que si el servidor anda corto de memoria, quizás parezca mejor de nuevo la primera opción puesto que aunque penalicemos el tiempo de carga por carga 1 .dll según la vamos necesitando, por contrapartida consumiremos sólo la memoria necesaria.

Compilación - Mantenimiento

En el caso de un sitio web, si una página cambia se puede sólo actualizar la .dll que la contiene y sin tocar el resto y todo debería funcionar. Sin embargo, en una aplicación web, cualquier cambio y por mínimo que sea, implicará compilar de nuevo todo el proyecto en 1 sólo fichero .dll y volver a subirlo entero.

Otra nota relacionada con la compilación, es que un sitio web utilizado ficheros .refresh para las copias locales de ensamblados en el directorio \bin, mientrás que una aplicación web no utilizar ficheros .refresh.La teoría dice que los ficheros .refresh (que guardan la ubicación en disco desde donde se agregó la referencia al ensamblado) sirve para si se cambia el fichero original que el sitio web actualice automáticamente el fichero (yo nunca he hecho esto y además me parece “demasiado” automático).

Un fichero .refresh se puede eliminar sin problemas, al igual que si lo copiamos de nuevo se “asociará” automáticamente a su fichero padre. De hecho si se quita el fichero .refresh vemos como en la página de propiedades del sitio web y para la referencia oportuna, el texto “Actualización automática” cambia automáticamente al número de versión del fichero.

Con ,refresh

image

Sin .refresh

image

 

Debug
/Release

Al no haber un fichero de proyecto no se manejan estos conceptos.
El único setting reseñable es debug=”true|false” del fichero web.config.

Funciona con normalidad como cualquier proyecto de Windows Forms.
Además también es importante de nuevo el setting debug=”true|false” del fichero web.config.

Publicación

1. xcopy

2. Se puede precompilar en el equipo local y después utilizar xcopy. Si no se precompila la compilación es realizada en tiempo de ejecución y de forma dinámica por ASP.NET la primera vez que se solicita un recurso.

Visual Studio permite publicar en:

·        Sistema de archivos

·        IIS Local

·        Sitio FTP

·        Sitio remoto

1. Copiar el ensamblado en el servidor. El ensamblado se genera al compilar la aplicación.

Visual Studio permite publicar en:

·        WebDeploy

·        FTP

·        Sistema de archivos

·        FPSE (Sitio remoto IIS con extensiones de servidor de FrontPage).

Análisis de código

No soportado.

Funciona.

Diagrama de capas

No soportado.

Funciona.

Atributos del ensamblado (nombre, versión, etc.)

No.

Sí.

Probar páginas sin tener en cuenta el estado de otras páginas (olvidándonos de que podemos “excluir” ficheros)

Sí (siempre y cuando no se precompile y se publique con xcopy).

Se pueden probar páginas específicas sin tener en cuenta el estado de otras páginas. Esto se debe a que la ejecución de una página individual no requiere la compilación correcta del sitio al completo, solo de la página y de los componentes de los que dependa, como el código de la carpeta App_Code o el archivo Global.asax.

No.

Referencias a otros proyectos web

No.

Sí.

Pre-build y post-build.

No.

Sí.

Acceso a páginas o controles de usuario desde clases independientes.

No.

Sí.

Compilar y publicar en sitio web

clip_image006

Permitir que este sitio precompilado se actualice

Especifica que el contenido de las páginas .aspx (importante!, sólo la parte del marcado) no se compila en un ensamblado, sino que el marcado se deja tal cual, lo cual permite realizar cambios en la funcionalidad del cliente y el código HTML después de precompilar el sitio Web.

Por ejemplo, si se deja marcada esta opción (por defecto),  en la carpeta de publicación seleccionada tendremos un fichero Default.aspx con el siguiente código:

<%@ page language="VB" autoeventwireup="false" inherits="_Default, App_Web_3eaft2cx" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">

<head runat="server">

    <title></title>

</head>

<body>

    <form id="form1" runat="server">

    <div>

        <h1>

            Hola Mundo</h1>

    </div>

    </form>

</body>

</html>

Sin embargo, si desmarcamos la opción tendremos esta otra salida para el fichero Default.aspx:

Éste es un archivo marcador generado por la herramienta de precompilación y que no se debería eliminar

En el primer caso podríamos editar en el servidor de producción la página .aspx (el marcado, diseño, etc.) y la aplicación reflejaría automáticamente los cambios. Sin embargo, en el segundo caso no podremos editar el fichero .aspx puesto que no tenemos disponible el marcado. Lo cierto es que nunca he tenido que modificar el marcado en producción y en mi opinión es preferible desmarcar esta opción porque además así tampoco distribuimos “parte” de nuestro código fuente (vale que el marcado no suele ser lo más interesante de nuestro trabajo intelectual, pero yo soy muy “quisquilloso” con esto…)

Por otro lado, fijarse como en el primer caso el atributo Inherits de la directiva Page apunta a la clase _Default y un ensamblado llamado App_Web_3eaft2cx. Pues bien, este ensamblado podremos ver que está disponible en la carpeta bin. De hecho, si abrimos este ensamblado con reflector (http://www.red-gate.com/products/reflector/), podemos ver que este ensamblado contiene tanto a nuestra clase _Default como a Default2 (luego ha compilado en un solo ensamblado todas las páginas .aspx de un mismo directorio).

De hecho y aunque en este documento se ha dicho que un sitio web genera 1 ensamblado por página, en realidad se genera 1 ensamblado por directorio, y concretamente para el directorio App_Code se genera 1 sólo ensamblado (con independencia de los subdirectorios que tenga).

 

clip_image008

Utilizar nomenclatura fija y ensamblados de una sola página

Con la situación anterior de ensamblados generados (y con independencia de si utilizamos “Permitir que este sitio precompilado se actualice”) es aún un poco difícil subir cambios realizados en una página al servidor de producción sin tener que publicar de nuevo. Esto se entiende porque cada vez que precompilamos los nombres de los ensamblados (a excepción del ensamblado App_Code.dll) son autogenerados y distintos para cada compilación. Por ejemplo, si quisiéramos hacer un cambio en Default.aspx.vb y publicar sólo la .ddl generada para su carpeta, tendríamos que saber que la antigua .ddl (la que borraremos del servidor de producción) se llama App_Web_3eaft2cx y la nueva se llama App_Web_<OtroID>, además de también sobreescribir Default.aspx y Default2.aspx (todos los ficheros .aspx de la carpeta)… uff, muy complicado, casi publico de nuevo todo y me quito de líos…

Pues bien, para solucionar este galimatías podemos activar “Utilizar nomenclatura fija y ensamblados de una sola página”, que generará:

Página Default.aspx con

<%@ page language="VB" autoeventwireup="false" inherits="_Default, App_Web_default.aspx.cdcab7d2" %>

Y un ensamblado en la carpeta bin con el nombre:

App_Web_default.aspx.cdcab7d2.ddl

De este modo, ya tenemos 1 ensamblado por página y además el nombre del ensamblado incluye el nombre de clase con lo que será fácilmente localizable.

Cabe mencionar que App_Code sigue generando 1 sólo ensamblado aunque marquemos está opción.

Por último, también decir que si marcamos esta opción estamos hablando de “compilación fija” (1 página – 1 ensamblado) y si no hablamos de “compilación por lotes” (1 carpeta – 1 ensamblado).

Ubicación

Por defecto se sugiere C:\Users\<Usuario>\Documents\Visual Studio 2010\Projects\<CarpetaProyecto>\PrecompiledWeb \<NombreProyecto>

En cualquier caso podemos elegir para la ubicación destino:

1.      Sistema de archivos (que si no es una ruta de red apuntando al servidor de producción, implicará que después de precompilar habría que copiar el resultado obtenido en la carpeta del servidor de producción).

2.      IIS Local (donde además podemos crear una nueva aplicación web o un directorio virtual si procede antes de publicar).

3.      Sitio FTP

4.      Sitio remoto

clip_image010

clip_image012

Compilar y Publicar en aplicación web

En una aplicación web no existe el concepto de precompilar porque tampoco se puede hacer xcopy del proyecto sin más en el servidor de producción y esperar que funcione, porque fallaría!. Esto es debido a que a diferencia del sitio web, una aplicación web es un proyecto (con su fichero vbproj asociado) y si quisiéramos hacer un xcopy, lo más parecido sería generar y copiar después el fichero <NombreAplicación>.dll que se haya generado en la carpeta bin.

Para publicar tenemos disponibles los siguientes métodos:

·        WebDeploy

·        FTP

·        Sistema de archivos

o   Sistema de archivos

o   IIS Local

·        FPSE

clip_image014

WebDeploy escapa al objetivo de este post, pero simplemente decir que es un nuevo método de publicación basado en paquetes que una vez configurado en el servidor de producción de IIS, permite al desarrollador subir las aplicaciones de una forma óptima y controlando números parámetros de la publicación (tanto IIS como de Sql Server), además también facilita a los administradores de IIS, la gestión, administración y migración de aplicaciones. Para saber más sobre WebDeploy, visitar http://javierholguera.com/technoblog/?p=104.

Respecto a la publicación de una aplicación web cabe mencionar que los ficheros aspx no se precompilan y que será en tiempo de ejecución cuando se compilen la primera vez que se soliciten. Esto se puede solucionar utilizando un proyecto de instalación web.

Por ende y a menos que se utilice un proyecto de instalación web, el código fuente de marcado de las páginas .aspx será público y accesible desde el servidor de producción (sólo el marcado).

Además y si fuera necesario, también es posible cambiar la ubicación del fichero .ddl de aplicación para que no esté necesariamente en la carpeta bin.

¿Y si no precompilamos un sitio web o no hacemos un proyecto de instalación web para una aplicación web?

Pues en este caso, IIS compilará en tiempo de ejecución el recurso solicitado la primera vez que un cliente lo solicite.

Cabe mencionar que en este escenario de compilación en tiempo de ejecución, la compilación es “por lotes”, esto es que se compila la carpeta entero donde está el recurso. Además, el primer recurso solicitado también compilará Global.asax (si existe) y también sólo 1 recurso será el encargado de compilar la carpeta App_Code (si la utiliza).

Con esto, se puede deducir que por norma, el primer acceso a la primera página será un poco más lento (Global.asax, normalmente también App_Code) y siguientes accesos a recursos en otros directorios también serán un poco más lentos.

Otras diferencias menores

En un sitio web al agregar un nuevo elemento:

clip_image016

En una aplicación web:

clip_image018

Como vemos la principales diferencias son el nombre de la página .aspx sugerida (Default vs WebForm) y como seleccionamos la página maestra.

Otra diferencia es como aparece la página en la lista de eventos y al nombre que automáticamente escoge Visual Studio al seleccionar un evento de la lista:

En un sitio web:

clip_image020

En una aplicación web:

clip_image022

Por ende si seleccionamos por ejemplo el evento PreRender, tendremos un nombre de evento distinto (aunque ambos finalmente “manejan” el mismo evento).

En un sitio web:

    Protected Sub Page_PreRender(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.PreRender

    End Sub

En una aplicación web:

    Private Sub WebForm1_PreRender(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.PreRender

    End Sub

Además también deberíamos apreciar que por defecto en un sitio web el alcance de visibilidad de los métodos es “Protected”, mientras que en una aplicación web es “Private”. Realmente no parece muy relevante, sólo tener cuidado si enlazamos los eventos de los controles a través del atributo “On<Evento>” desde el marcado, puesto que entonces el alcance del método debería ser mínimo “Protected” (con “Private” no funcionará).

Referencias a ensamblados

Otra diferencia que me he encontrado hoy es que, si trabajamos con .NET Framework 4.0, me queda mucho más claro en una aplicación web, cuales ensamblados estamos referenciando.

Lo que quiero decir es que una aplicación web no hay perdida alguna. Sabemos exactamente que estamos referenciando. Esta información se guarda en el fichero .vbproj y además podemos ver las referencias tanto en el nodo “References” (activando ver ficheros ocultos para el proyecto) como en las propiedades del proyecto, en la pestaña “Referencias”.

Sin embargo, en un sitio web, esta información se guarda en el fichero web.config (porque logicamente no hay ningún fichero de proyecto donde guardarlas), así que las secciones <system.web><assemblies>… y <system.web><pages><namespaces>… son las que guardan tanto la información de los ensamblados referenciados como los espacios de nombres importados.

Para más inri, con el nuevo modelo de fichero web.config de ASP.NET 4.0 http://weblogs.asp.net/scottgu/archive/2009/08/25/clean-web-config-files-vs-2010-and-net-4-0-series.aspx, directamente hay algunas referencias que “mágicamente” tenemos disponibles en un sitio web pero que no podemos saber cuales son, es decir, no aparecen en el cuadro de diálogo propiedades del sitio web.

Editar y continuar

Claramente apuesto con un proyecto de aplicación web pero aún tengo pendiente poder “Editar y Continuar” en el código de mis páginas .aspx.

Juro haber navegado hasta la saciedad en google para encontrar una respuesta, pero todas me han llevado a seguir frustrado con este tema (deshabilitar IntelliTrace, activar Editar y Continuar, etc.). Imagino que quizás un futuro Service Pack ayuda a implementar esta funcionalidad.

Bibliografía

http://msdn.microsoft.com/es-es/library/dd547590.aspx

http://geeks.ms/blogs/jalarcon/archive/2009/01/18/sitios-web-o-aplicaciones-web-en-visual-studio-2005-2008-191-cu-225-l-utilizar.aspx

http://eloyparedes.wordpress.com/2007/07/17/proyectos-de-aplicacion-web-vs-proyectos-de-sitio-web-web-application-projects-vs-web-site-projects/

http://weblogs.asp.net/scottgu/archive/2006/09/22/Tip_2F00_Trick_3A00_-Optimizing-ASP.NET-2.0-Web-Project-Build-Performance-with-VS-2005.aspx