• Sign In
 
  • MSDN Blogs
  • Microsoft Blog Images
  • More ...
Common Tasks
  • Blog Home
  • About
  • RSS for posts
  • Atom
Blog - News
Search
  • Advanced search options...
Twitter (@dmossberg)
Tags
  • ASP
  • ASP.NET
  • Common Language Runtime (CLR)
  • Debugging
  • Ejemplos de Código
  • Failed Request Tracing
  • Herramientas
  • IIS 6.0
  • IIS 7.0
  • Kerberos
  • Log Parser
  • Pages
  • Seguridad
  • Silverlight
  • SSL/TLS
Recent Posts
  • Porque no se reflejan inmediatamente los cambios en aplicaciones ASP.NET

    Posted over 3 years ago
    by Daniel Mossberg
  • Cómo capturar volcados de hang con Debug Diagnostics Tool

    Posted over 3 years ago
    by Daniel Mossberg
  • Cuándo y cómo capturar volcados de memoria en modo Hang

    Posted over 3 years ago
    by Daniel Mossberg
  • Detalles sobre el error HTTP 413 - Request entity too large

    Posted over 3 years ago
    by Daniel Mossberg
  • Acentos y eñes no se muestran correctamente

    Posted over 3 years ago
    by Daniel Mossberg
Archives
Archives
  • May 2012 (2)
  • November 2010 (1)
  • August 2010 (1)
  • April 2010 (1)
  • March 2010 (2)
  • February 2010 (2)
  • January 2010 (2)
  • December 2009 (5)
  • October 2009 (1)
  • September 2009 (3)
  • August 2009 (1)
  • July 2009 (2)
  • May 2009 (2)
  • April 2009 (4)
  • February 2009 (1)
  • January 2009 (1)
  • December 2008 (1)
Blogs de ASP.NET / IIS
  • If broken it is, fix it you should

  • Notes from a dark corner

  • Never doubt thy debugger

  • Speaking of which...

Otros blogs recomendados
  • Blogs de Soporte en España

MSDN Blogs > The code is out there > December, 2009

December, 2009

  • Subscribe via RSS
Sort by: Most Recent | Most Views | Most Comments
Excerpt View | Full Post View
  • The code is out there

    Porque no se reflejan inmediatamente los cambios en aplicaciones ASP.NET

    Posted over 3 years ago
    by Daniel Mossberg
    • 0 Comments

    Esta es una problemática relativamente común. Por ejemplo, actualizamos un ensamblado (DLL) de nuestra aplicación ASP.NET, y cuando la probamos vemos que todavía no se han reflejado los cambios y que la aplicación se comporta igual que antes del cambio. ¿Por qué no se reflejan los cambios inmediatamente?

     

    ASP.NET trabaja con application domains para proporcionar aislamiento entre aplicaciones alojadas en un mismo proceso. El application domain contiene todos los datos relacionados con una aplicación en particular, que son (simplificando): todos los ensamblados específicos de la aplicación, un objeto HttpRuntime y un objeto Cache. Un application domain se puede descargar del proceso que lo aloja, pero un ensamblado no se puede descargar del application domain que lo ha cargado.

     

    Por lo tanto, cuando el runtime de .NET (CLR) detecta, por ejemplo, que algún ensamblado de la carpeta ~/bin de la aplicación ha sido modificado, carga un nuevo application domain con la última versión del ensamblado, y el application domain antiguo se descarga del proceso en cuanto haya terminado de servir todas las peticiones en curso.

     

    Cada vez que se reinicia el application domain, todos los ensamblados tienen que volver a cargarse (previamente haciendo el shadow copy), el código vuelve a compilarse por el JIT-compiler, y la cache y las variables de sesión se reinician. El proceso de reinicio del application domain es bastante costoso, por lo que conviene evitar que se produzca cuando la aplicación web tiene mucha carga de usuarios.

     

    ASP.NET utiliza la API Win32 ReadDirectoryChangesW para monitorizar cambios en carpetas y ficheros. Cuando detecta alguno de los siguientes cambios, se reinicia el application domain (esta lista la he sacado directamente del siguiente post de mi compañera Tess):

     

    ·         Modificaciones en Web.Config, Machine.Config o Glabal.asax

    ·         Modificaciones en la carpeta ~/bin o en su contenido

    ·         La ruta física del directorio virtual es modificada

    ·         Alguna subcarpeta de la aplicación web es eliminada (sólo en ASP.NET 2.0)

     

    Adicionalmente, los siguientes eventos también provocan un reinicio del application domain:

     

    ·         La política CAS (Code Access Security) es modificada.

    ·         El número de recompilaciones dinámicas1 de ficheros *.aspx, *.ascx o *.asax excede el límite especificado en la propiedad <compilation numRecompilesBeforeAppRestart="15"/> en el machine.config o web.config  (por defecto este valor es de 15)

     

    1) Es importante puntualizar que modificar un fichero *.aspx, *.ascx o *.asax también implica una recompilación, dado que en ASP.NET absolutamente todo el código termina siendo compilado, incluso el código “HTML” de la capa de presentación. Las recompilaciones dinámicas, se gestionan de una forma distinta ya que en lugar de reiniciar el application domain directamente, se invalida el ensamblado con la versión antigua del fichero .aspx, y se carga un nuevo ensamblado con la nueva versión.

     

    A la larga, dado que no se pueden descargar ensamblados de un application domain, este comportamiento de ASP.NET supondría que el consumo de memoria aumentaría progresivamente debido a la acumulación de ensamblados invalidados. Por este motivo, ASP.NET reinicia el application domain llegado un número determinado de recompilaciones, para de esta forma poder descargar los ensamblados invalidados.

     

    Por lo tanto, para evitar los problemas asociados a los reinicios de los application domains y a las recompilaciones dinámicas, debemos seguir las siguientes medidas:

    a)      Realizar despliegues a producción cuando el servidor tenga la menor carga posible, o mejor incluso sacándolo del balanceo de forma que no atienda peticiones.

    b)      Cuando el punto a) no sea posible, podemos añadir / modificar los parámetros waitChangeNotification y maxWaitChangeNotification para minimizar el número de reinicios del application domain. Estos parámetros se pueden configurar en el web.config de la aplicación web en cuestión. Por ejemplo:

    <system.web>

      <httpRuntime waitChangeNotification="10" maxWaitChangeNotification="60" />

    </system.web>

     

    Este mecanismo funciona de la siguiente manera: en el momento que sobrescribimos un fichero existente dentro de la estructura de carpetas de nuestra aplicación web, un objeto de File Change Notification detecta el cambio y transcurrido el tiempo que hayamos configurado en el campo waitChangeNotification reiniciará el application domain. Si durante este periodo de espera detecta otro cambio adicional, volverá a esperar otra vez el número de segundos que hayamos configurado en waitChangeNotification, y así sucesivamente hasta que se alcance el tiempo de espera que hayamos configurado en maxWaitChangeNotification. Cuando se alcanza el tiempo de espera configurado en maxWaitChangeNotification, el application domain se reinicia al margen de que se sigan detectando cambios.

    De esta forma, el application domain no se reinicia hasta que se hayan “terminado de copiar” todos los nuevos ficheros a la carpeta de contenido, evitando así múltiples reinicios con su consiguiente coste. Esta problemática también está descrita en detalle en el post al que hacía referencia antes de mi compañera Tess Ferrandez.

     

    c)      En ocasiones es interesante probar si deshabilitando la “compilación por lotes” mejora el comportamiento. Este cambio ocasiona que no se compile la aplicación entera cuando se carga el application domain sino únicamente las partes relevantes de la aplicación requeridas para atender la primera petición. Por un lado se reduce el retraso inicial para responder a la primera petición, aunque por otro lado, cuando llegue una petición posterior que requiera una parte de la aplicación que no haya sido compilada, esa petición también experimentará un retraso.

    Este cambio aplica sobre todo para aplicaciones compuestas por gran cantidad de ensamblados y páginas.

    <system.web>

      <compilation batch="false" />

    </system.web>

     

    Espero que esta información os sea de utilidad.

    - Daniel Mossberg

  • The code is out there

    Cómo capturar volcados de hang con Debug Diagnostics Tool

    Posted over 3 years ago
    by Daniel Mossberg
    • 0 Comments

    Este post es la continuación de Cuándo y cómo capturar volcados de memoria en modo Hang

    La herramienta Debug Diagnostics Tool se puede descargar desde aquí, tanto la versión de 32-bit como la de 64-bit. En el momento de escribir este post, la herramienta está en la versión 1.1 y está soportada para los siguientes sistemas operativos:

     

    ·         Windows 2000 Server

    ·         Windows Server 2003

    ·         Windows XP

     

    Es decir, si pretendemos analizar un problema en Windows Server 2008, Windows Server 2008 R2, Windows Vista o Windows 7 es recomendable utilizar otras herramientas, aunque algunas funcionalidades de Debug Diagnostics pueden funcionar en estos sistemas operativos.

     

    Nota

    En el caso de los sistemas operativos de 64-bit, es conveniente instalar la versión de DebugDiag en función del proceso que se va a monitorizar. Es decir, si el proceso es de 32-bit, es mejor utilizar la versión de 32-bit de DebugDiag al margen de que Windows sea de 64-bit (de esta forma nos quitamos del medio la capa WOW64 que a veces dificulta la depuración).

     

    DebugDiag nos permite capturar volcados de hang básicamente de tres formas distintas:

     

    Volcado manual de todos los procesos de IIS

    Volcado manual de un proceso específico

    Regla de hang

     

     

     

    VOLCADO MANUAL DE TODOS LOS PROCESOS DE IIS

    Podemos generar los volcados manualmente cuando se esté reproduciendo el problema desde el menú [Tools] à [Create IIS/COM+ Hang Dump].

      image

    Por defecto, los volcados se generarán en la ruta: C:\Program Files\DebugDiag\Logs\Misc

     

    VOLCADO MANUAL DE UN PROCESOS ESPECÍFICO

    Podemos generar volcados manualmente de un proceso específico desde la pestaña [Processes] à [Botón derecho sobre el proceso] à [Create Full Userdump]

     

     image

     

    Al igual que en el anterior caso, los volcados se generan en la ruta: C:\Program Files\DebugDiag\Logs\Misc.

     

    REGLA DE HANG

    Las reglas de hang de Debug Diagnostic permiten monitorizar la salud de una aplicación web de forma automatizada, y generar volcados en el momento que la herramienta detecta que la aplicación no respohnde en los tiempos establecidos.

     

    Para configurar una regla de hang debemos posicionarnos en la pestaña [Rules] y posteriormente pulsar sobre el botón  [Add Rule…]. Posteriormente seguiremos estos pasos:

     

    1)      Seleccionar la opción [IIS Hang]

    2)      En la siguiente pantalla, seleccionar las URLs que queremos monitorizar con la herramienta. Debemos configurar al menos una URL, pero en algunos escenario puede tener sentido monitorizar varias. El funcionamiento del mecanismo de monitorización es muy sencillo. Se basa en realizar peticiones HTTP a las URLs configuradas, y esperar hasta que una de esas peticiones no sea atendida en el tiempo establecido para alertar al depurador que se está produciendo un hang.

    Para cada URL, configuraremos independientemente la propiedad ping interval, que es el intervalo de tiempo entre cada ping a la URL, y la propiedad timeout que es el intervalo de tiempo que vamos a esperar a recibir una respuesta. En el momento que la respuesta al ping exceda el tiempo que hemos especificado en timeout, se generará un volcado automáticamente.

    Los valores predeterminados de la herramienta establecen el valor de la propiedad timeout a 120 segundos. Personalmente opino que es un valor muy excesivo, y que en la mayoría de los casos, si una petición HTTP no ha respondido en 30 segundos, se puede confirmar que se está produciendo una contención. Es difícil hacer una recomendación genérica sobre estos parámetros, porque depende mucho de cada aplicación y cada escenario individual. Yo suelo recomendar poner ambos valores a 30, pero al final eso lo tiene que decidir quien conoce la aplicación.

    image

    3)      En el siguiente paso, debemos configurar que hará la herramienta cuando detecte que se está produciendo una situación de hang. Para ello debemos pulsar sobre el botón [Add Dump Target] y seleccionar alguna de las siguiente opciones:

     

    a)      All active IIS/COM+ related processes: Generará volcados de todos los procesos INETINFO.EXE, W3WP.EXE y DLLHOST.EXE. Esta opción es interesante cuando no sabemos a priori cual es el proceso que provoca la contención.

    b)      Executable: Generará volcados de todos los procesos con el mismo nombre que el proceso que indiquemos, por ejemplo W3WP.EXE.

    c)      COM+ application: Generará un volcado del proceso DLLHOST.EXE que aloje la aplicación COM+ que indiquemos.

    d)      Web application pool: Generará un volcado de memoria del proceso W3WP.EXE que aloja el application pool que indiquemos.

    e)      NT Service: Generará un volcado del proceso que aloje al servicio de Windows que indiquemos, por ejemplo SVCHOST.EXE.

    4)      Por último debemos indicar el nombre de la regla y la ubicación donde volcará los datos generados. En función de la circunstancias, estos datos pueden ser de gran tamaño por lo que conviene elegir una unidad que no tenga problemas de espacio.

     

    - Daniel Mossberg

  • The code is out there

    Cuándo y cómo capturar volcados de memoria en modo Hang

    Posted over 3 years ago
    by Daniel Mossberg
    • 0 Comments

    En el contexto de este post, se entiende por hang (yo lo traduciría al castellano como contención) una situación en la que una aplicación responde mucho más despacio de lo normal o deja de responder por completo. Una contención puede ser temporal (pasado un rato la aplicación vuelve a funcionar correctamente) o permanente (lo que se conoce como deadlock), y puede ir asociada a un consumo de CPU elevado o un consumo bajo (o incluso nulo).

     

    Los volcados de memoria en modo hang muestran el estado de la memoria de un proceso en un momento determinado en el tiempo. Por lo tanto, para que la información contenida en el volcado tenga algún valor es imprescindible capturar el volcado en el momento adecuado. Revisemos los distintos escenarios en los que necesitaremos capturar volcados de memoria en modo hang:

     

    Contención y consumo de CPU bajo

    Habitualmente, cuando la aplicación no responde ni consume CPU es que está esperando a algo que se ejecuta en un proceso distinto o incluso en un servidor distinto. Por ejemplo, puede estar esperando a obtener respuesta de una llamada RPC, a obtener respuesta de una llamada por sockets, o a que se libere una sección crítica. En ocasiones, como ya adelantaba antes, estas contenciones pueden ser permanentes si esa respuesta nunca llega o la sección crítica nunca se libera (siguiendo con el ejemplo anterior).

     

    Para este tipo de problemas es interesante capturar tres volcados con un intervalo de un minuto entre cada uno (aproximadamente), y cuando sea posible capturar volcados de todos los procesos implicados en la aplicación cuando se esté reproduciendo el problema.

     

    Esto nos permitirá ver cómo evoluciona el proceso con el tiempo (por eso cogemos varios volcados), y además obtendremos datos de todos los procesos implicados dado que a priori no podemos saber en qué proceso se produce la contención.

     

    Las dos herramientas más comunes para capturar estos volcados son Debug Diagnostics y Adplus. En los siguientes posts encontraréis la información detallada sobre cómo generar los volcados:

     

    ·         Cómo capturar volcados de hang con Debug Diagnostics Tool

    ·         Cómo capturar volcados de hang con Adplus (próximamente)

     

    Contención y consumo de CPU elevado

    Para este tipo de problemas, al contrario que la categoría anterior, es más evidente cual es el proceso que nos interesa analizar (el que consume CPU). Por lo tanto, la forma de capturar los volcados es ligeramente distinta.

     

    Para este tipo de problemas es interesante capturar tres volcados con un intervalo de un minuto entre cada uno (aproximadamente) del proceso específico con elevado consumo de CPU cuando se esté reproduciendo el problema.

     

    Al igual que en el anterior escenario, podemos utilizar las herramientas Debug Diagnostics y Adplus para capturar este tipo de volcados. Adicionalmente, existe una herramienta llamada ProcDump diseñada especialmente para generar volcados cuando un proceso supere un determinado umbral de consumo de CPU. En los siguientes posts encontraréis la información detallada sobre cómo generar los volcados:

     

    ·         Cómo capturar volcados de hang con Debug Diagnostics Tool

    ·         Cómo capturar volcados de hang con Adplus (próximamente)

    ·         Cómo capturar volcados de hang con ProcDump (próximamente)

     

    Próximamente veremos cuándo y cómo capturar volcados de memoria en modo crash.

     

    Hasta pronto

    - Daniel Mossberg

  • The code is out there

    Detalles sobre el error HTTP 413 - Request entity too large

    Posted over 3 years ago
    by Daniel Mossberg
    • 1 Comments

    Imaginemos el siguiente escenario: Tenéis una aplicación web que requiere o acepta certificados de cliente, y que mediante un formulario HTML hace POST para subir ficheros al servidor. En algunas ocasiones, cuando los ficheros superan un determinado tamaño, la petición falla y en los logs de IIS vemos un error HTTP 413 – Request entity too large.

     

    Este es un comportamiento conocido cuando están habilitados certificados de cliente en combinación con que se realiza un petición HTTP de gran tamaño (por ejemplo un POST HTTP adjuntando ficheros). El motivo es que IIS lee los primeros n bytes de la petición (ahora veremos qué determina esa n), asumiendo que deberían haber llegado todos los encabezados de la petición (HTTP headers), pero no necesariamente todos los datos asociados (entity body) de la petición.

     

    Esto habitualmente no supone un problema, pero en nuestro escenario en particular, IIS examina los encabezados de la petición, encuentra que la página requiere certificados de cliente y que por lo tanto necesita renegociar la conexión SSL. Desafortunadamente, el cliente (IE) no puede renegociar la conexión porqué está esperando a poder enviar el resto de datos del entity body a IIS. Para evitar que se produzca un deadlock (IIS esperando a poder renegociar la conexión SSL e IE esperando a poder mandar el entity body), IIS devuelve un error HTTP 413 y cierra la conexión.

     

    Para evitar que se produzca este problema tenemos dos opciones:

     

    1)      Para que la renegociación de la conexión se pueda llevar a cabo, el entity body completo tiene que estar “precargado” utilizando SSL Preload. SSL Preload utiliza la propiedad de la metabase UploadReadAheadSize para determinar el tamaño del buffer en el que almacenará la petición (los n bytes a los que hacía referencia antes). Por lo tanto si el tamaño de este buffer es inferior al tamaño total de la petición HTTP (lo que incluye los encabezados HTTP y el entity body), IIS devuelve el error HTTP 413.

    El tamaño predeterminado de ese buffer son 48k, lo cual es un tamaño insuficiente en muchas ocasiones, pero que fue establecido así para evitar ataques de denegación de servicio subiendo ficheros “basura” de gran tamaño.

    La sintaxis para aumentar dicho buffer es la siguiente, y se puede especificar de forma granular a nivel de directorio virtual:

    C:\inetpub\adminscripts>cscript adsutil.vbs set w3svc/1/root/myApp/uploadreadaheadsize 20000000

    Microsoft (R) Windows Script Host Version 5.6

    Copyright (C) Microsoft Corporation 1996-2001. All rights reserved.

    uploadreadaheadsize             : (INTEGER) 20000000


    El número indicado es el número de bytes, por lo que 20.000.000 bytes (como en el ejemplo) serían aproximadamente unas 19,1MB.

     

    2)      La otra alternativa es habilitar la clave de la metabase SSLAlwaysNegoClientCert de forma que forcemos a que por cada nueva conexión SSL que se establezca, el servidor negociará inmediatamente el certificado de cliente. De esta forman se previene la renegociación, lo cual supone una ganancia de rendimiento en sí misma, y además evita el problema asociado a las peticiones con entity body de gran tamaño. La sintaxis para habilitar esta clave es:

    C:\inetpub\adminscripts>cscript adsutil.vbs set w3svc/1/SSLAlwaysNegoClientCert true

    Microsoft (R) Windows Script Host Version 5.6

    Copyright (C) Microsoft Corporation 1996-2001. All rights reserved.

     

    SSLAlwaysNegoClientCert         : (BOOLEAN) True

     

    INFORMACIÓN ADICIONAL

    Client cannot renegotiate request and returns an HTTP 413 error (IIS 6.0)

    http://www.microsoft.com/technet/prodtechnol/WindowsServer2003/Library/IIS/7e0d74d3-ca01-4d36-8ac7-6b2ca03fd383.mspx?mfr=true

                           

     Happy hacking

    - Daniel Mossberg

  • The code is out there

    Acentos y eñes no se muestran correctamente

    Posted over 3 years ago
    by Daniel Mossberg
    • 2 Comments

    Los ordenadores procesan texto utilizando tablas de codificación para convertir secuencias de bits en caracteres alfanuméricos y viceversa. Cuando desarrollamos aplicaciones, y muy especialmente aplicaciones distribuidas o aplicaciones web, tenemos que tener en cuenta la codificación (o enconding) con la que “ciframos” y “desciframos” los mensajes, dado que si utilizamos codificaciones distintas el mensaje resultante puede resultar incorrecto.

     

    Antes de meternos de lleno en las consideraciones específicas de desarrollo, revisemos brevemente los encodings más comunes que puede ser interesante conocer.

     

    ASCII

    ASCII (American Standard Code for Information Interchange) se desarrolló en los años 60 y es una tabla de codificación que utiliza 7 bits para representar 128 caracteres, de los cuales 94 son caracteres legibles y 33 son caracteres de control y el espacio que se considera un carácter invisible. Esta codificación no sirve para representar la ‘ñ’ o los acentos, y hoy en día en muchos contextos se considera obsoleta.

     

    Windows-1252 (Western European)

    Históricamente era la codificación predeterminada en muchos contextos de Windows. Es una codificación de 8 bits para representar 256 caracteres, e incluye la mayoría de los caracteres utilizados en los alfabetos de Europa occidental.

     

    ISO-8859-1 (Latin 1)

    Esta codificación ISO de 8 bits fue publicada en 1985, y es un subconjunto de la codificación Windows-1252 compuesto por 191 caracteres. Es informalmente conocida como Latin 1.

     

    ISO-8859-15 (Latin 9)

    En 1999 se publicó esta codificación como una actualización de ISO-8859-1 para corregir algunas de sus limitaciones. Sigue utilizando 8 bits para representar cada carácter, y entre otros cambios se añadieron algunos caracteres del alfabeto fines (Š y Ž), y el símbolo del euro (€). Para poder acomodar estos cambios, se tuvieron que eliminar algunos otros caracteres de uso poco frecuente, entre los cuales se encontraban: ¤, ¦, ¨, ´, ¼, ½, y ¾.

     

    UTF-8

    UTF-8 (8-bit Unicode Transformation Format) es una codificación de longitud variable entre 1 y 4 bytes. La representación de un byte (8 bits) de UTF-8 se reserva exclusivamente a los 128 caracteres de la tabla ASCII lo cual lo hace compatible hacia atrás. Los siguientes 1920 caracteres de UTF-8 requieren dos bytes para ser codificados, entre los cuales se incluyen el alfabeto latino, griego, cirílico, hebreo, árabe, sirio, etc.

     

    Por lo tanto, la moraleja de este breve resumen, es que aunque tanto Windows-1252 y UTF-8 sean capaces de representar el carácter ‘Ñ’, lo hacen de forma distinta. De hecho, para ser más precisos lo hacen así:  

    Codificación

    Glifo

    Representación Binaria

    Representación Hexadecimal

    Windows-1252

    Ñ

    1101001

    D1

    UTF-8

    Ñ

    1100011 10010001

    C3 91

    Por lo tanto, queda claro que si codificamos un texto utilizando Windows-1252 y posteriormente lo decodificamos los bytes resultantes utilizando UTF-8, lo que inicialmente era un ‘Ñ’ va a pasar a ser cualquier otra cosa excepto una ‘Ñ’ al decodificarlo.

     

    Ahora que ya tenemos más clara la problemática, os detallo algunas consideraciones concretas para ASP.NET:

     

    1)      Dado que ASP.NET nos permite configurar la codificación utilizada para generar las respuestas, y la codificación predeterminada para decodificar las peticiones, es importante asegurarse de que se utiliza la misma codificación en la otra parte implicada, el cliente. Esta es la configuración predeterminada de ASP.NET:

    <configuration>
      <
    system.web>
        <
    globalization

          requestEncoding="utf-8"

          responseEncoding="utf-8" />
      </
    system.web>
    </
    configuration>

     

    2)      En una respuesta HTTP podemos especificar la codificación del contenido en dos sitios. En el encabezado HTTP Content-Type o en un meta tag dentro del propio documento HTML. En caso de conflicto entre ambos (como en el ejemplo), tiene preferencia la configuración especificada en el encabezado HTTP.

     

    HTTP/1.1 200 OK

    Date: Tue, 1 Dec 2009 10:23:34 GMT

    Server: Microsoft-IIS/6.0

    Content-Length: 48

    Content-Type: text/html; charset=utf-8

    Cache-control: private


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

      <head>
        <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" />
      </
    head>
      <
    body>
        …
      </body>

    </html>

     

    Un problema frecuente es enviar respuestas HTTP sin especificar en ningún sitio la codificación utilizada. Cuando se da el caso, el cliente que recibe la respuesta tiene que determinar la codificación que utilizará para decodificar el contenido. Habitualmente, es tan sencillo como que el cliente utilizará la codificación predeterminada del sistema operativo, por lo que existe un elevado riesgo de que en algún cliente con una determinada configuración se muestre incorrectamente.

    3)      Otro problema con el que me he encontrado en varias ocasiones es relativo al dialogo de descarga de Internet Explorer. Cuando generamos una respuesta HTTP dinamicamente desde ASP.NET para enviar un fichero, podemos encontrarnos con que el dialogo de descarga muestra el nombre del fichero con caracteres incorrectos:

    image

    Este problema se debe a que ASP.NET (1.1 y 2.0) por defecto codifican los encabezados HTTP con UTF-8. En ASP.NET 1.1 es necesario instalar la siguiente actualización para poder especificar la codificación de los encabezados:

    FIX: The response header will always be encoded as UTF-8 when you use the Response.Addheader method in ASP.NET

    http://support.microsoft.com/default.aspx?scid=kb;EN-US;895262

     

    Una vez instalada la actualización, podemos especificarla en el web.config de la aplicación:

    <globalization responseHeaderEncoding="Windows-1252"/>

     

    En ASP.NET 2.0 se puede cambiar la codificación de los encabezados HTTP programáticamente además de mediante la opción del web.config (igual que en ASP.NET 1.1):

     

    protected void Page_Load(object sender, EventArgs e)

    {

        //Leemos el fichero DOCX y lo almacenamos en un array de bytes

        string FileName = "Diseño gráfico.docx";

        string FilePath = MapPath(FileName);

        byte[] FileBytes = File.ReadAllBytes(FilePath);       

       

        //ASP.NET codifica los encabezados HTTP con 'utf-8' de forma

        //predeterminada. Especificamos que utilice la codificación 

        //ANSI predeterminada del OS, que en mi caso es 'Windows-1252'

        Response.HeaderEncoding = System.Text.Encoding.Default;   

     

        //Establecemos el MIME type de la respuesta y añadimos el

        //encabezado HTTP 'Content-Disposition'           

        Response.ContentType = "application/docx; charset=utf-8";

        Response.AddHeader("Content-Disposition", "Inline; filename=" +

            FileName);

          

        //Envíamos el fichero en formato binario

        Response.BinaryWrite(FileBytes);           

    }

     

    Hasta el próximo post

    - Daniel Mossberg

Page 1 of 1 (5 items)
  • © 2012 Microsoft Corporation.
  • Terms of Use
  • Trademarks
  • Privacy Statement
  • Report Abuse
  • 5.6.402.223