miércoles, 18 de noviembre de 2015

Entender la Compilación Dinámica de ASP.NET

Entendiendo la compilación dinámica de ASP.NET


Cuando se hace un request a un sitio web, ASP.NET primero parsea y luego compila el código de la aplicación Web para convertirlo en uno o más assemblies. Cuando se compila el código, es traducido a una representación que es independiente del lenguaje y del CPU llamada Microsoft Intermediate Language (MSIL). En tiempo de ejecución, MSIL corre en el contexto del .NET Framework, el cual traduce MSIL en instrucciones específicas para ese CPU y para el procesador que corre la aplicación en dicho computador.



Compilación en el primer request


Por defecto, las páginas web de ASP.NET y el código embebido se compilan dinámicamente cuando los usuarios hacen el primer request a un recurso, como una página web ASP.NET (un .aspx). Luego que las páginas y el código embebido se compila por primera vez, se dejan estos recursos en un caché, así los subsecuentes request a esa misma página son extremadamente eficientes.
ASP.NET soporta Compilación dinámica de las páginas ASP.NET (.aspx), ASP.NET Web services (.asmx), ASP.NET HTTP handlers (.ashx) y ASP.NET application files (Global.asax), pero también otros archivos de código fuente como (*.aspx.vb) y clases (*.aspx.cs). Para más información de los tipos de archivo de ASP.NET, ver Web Site File Types. Para más información del proceso de compilación de ASP.NET, ver la sección "Compilation Life Cycle" de ASP.NET Application Life Cycle Overview.

Recompilación cuando hay cambios


Cualquier cambio de un archivo dinámicamente compilado invalida el assembly que está en caché y gatilla una recompilación de todos los recursos afectados. La próxima vez que se haga un request, ASP.NET reconoce que el código cambió y recompila los recursos afectados de la aplicación web. Este sistema permite desarrollar aplicaciones con un mínimo de sobrecarga en el proceso de compilación. (Notar que dependiendo del cambio que hay sobre un recurso, ASP.NET recompilará una sola página o todo el sitio Web.)

Dependencias de la compilación


Cuando se hace el primer request a la aplicación, ASP.NET compila los archivos en un orden específico. Los primero ítems en ser compilados son los llamados ítems de primer nivel.
Luego del primer request, los ítems de primero nivel se recompilan sólo si cambian las dependencias.
Los ítems de primer nivel incluyen las carpetas App_GlobalResources, App_WebResources, propiedades del perfil, carpeta App_Code y archivo Global.asax. Luego que los ítems de primer nivel se compilan, ASP.NET compila los ítems adicionales. Estos ítems incluyen la carpeta App_LocalResources, páginas ASP.NET (.aspx files), ASP.NET user controls (.ascx), ASP.NET HTTP Handlers (.ashx) y módulos ASP.NET HTTP (.asmx files), themes, master pages y otros archivos fuente. Para más información ver ASP.NET Web Site Layout y ASP.NET Application Life Cycle Overview.

Salida de la compilación


Cuando el código es compilado, los assemblys resultantes son "cacheados" en una carpeta en el servidor. Esta carpeta requiere los permisos apropiados para que tu código compilado se ejecute correctamente. Puedes configurar tanto la ubicación de la carpeta de compilación como los permisos con los que opera tu código compilado.

En producción, la primera vez que se accede al sitio, se compila y genera una carpeta dentro de Temporary ASP.NET Files de forma automática y se copian las DLL desde el \Bin a esta nueva carpeta dentro de Temporary ASP.NET Files.
Dejemos claro que no se genera una nueva carpeta aquí cada vez que se reinicia el IIS, a menos que esté bloqueado la carpeta \Bin y no deja copiarse a Temporary ASP.NET Files (problema conocido como "Copias Sombras/Shadow Copy". El error No se puede crear ni realizar copias sombra de 'dll' si el archivo ya existe/Cannot create/shadow copy 'dll' when that file already exists. Este error se resuelve desinstalando Windows Search del servidor, expluyendo la carpeta Temporary ASP.NET Files del escaneo del Antivirus, en el IIS moviendo la WebApp que da problemas a una AppPool propio cuando comparte el AppPool con más sitios), entonces al hacer un IIS reset verás la DLL copiada aquí.

Ubicación de la carpeta de compilación

Por defecto, cuando compilas una aplicación web, el código compilado queda en la conocida carpeta Temporary ASP.NET Files. Esta carpeta está dentro de la carpeta donde tienes instalado el Framework .Net. La ruta típica es:
%SystemRoot%\Microsoft.NET\Framework\versionNumber\Temporary ASP.NET Files
Por ejemplo, en una máquina de 64 bits, si está instalado el Framework 2.0 tendrías la carpeta:
C:\Windows\Microsoft.NET\Framework64\v2.0.50727\Temporary ASP.NET Files

Permisos requeridos para la carpeta de compilación

El proceso de instalación del Framework .NET crea la carpeta Temporary ASP.NET Files y le asigna permisos de acceso a la cuenta local de ASP.NET, el cual tiene los permisos necesarios para acceder al código compilado. Si modificas la configuración u opciones de la cuenta de usuario, asegúrate que la cuenta tenga suficientes permisos a la carpeta de Temporary ASP.NET Files. Para más detalles, ve How to: Run aspnet_wp.exe Under a User Account.

Configuración de la carpeta de compilación

ASP.NET crea una subcarpeta dentro de la carpeta Temporary ASP.NET File para cada aplicación. Puedes configurar la ubicación raíz usando el atributo tempDirectory de la sección compilación del archivo de configuración. Este atributo opcional permite especificar el directorio para almacenar los archivos temporales durante la compilación. Por defecto es un string vacío (""). En caso de ser un string vacío y si el proceso actual tiene los permisos de acceso necesario, los archivos son guardados en el siguiente directorio:
%FrameworkInstallLocation%\Temporary ASP.NET Files
Para más información, ver el Elemento compilación (ASP.NET Settings Schema) y la propiedad TempDirectory de la sección CompilationSection.

Soporte multilenguaje


ASP.NET 2.0 soporta múltiples lenguajes de programación en una misma aplicación web. En la carpeta App_Code, puedes especificar una subcarpeta para cada lenguaje, como C# y Visual Basic. ASP.NET creará un assembly separado para cada subcarpeta. Para más información ver Shared Code Folders in ASP.NET Web Sites y Walkthrough: Developing Web Sites Using Multiple Programming Languages.

Optimizando la compilación dinámica


A partir de un HotFix del Framework 3.5 se puede usar el atributo optimizeCompilations del web.config. Más info aquí.

Ventajas y desventajas de las compilación dinámica


La compilación dinámica de ASP.NET permite modificar el código fuente sin tener que explícitamente tener que compilar el código ni hacer un deploy en un servidor (Nota del traductor: como ejemplo práctico, permite que tengas un sitio web en un ambiente pre-productivo por ejemplo, donde tienes las dll tanto como los fuentes *.aspx.cs, y poder cambiar estos fuentes en "caliente", le das F5 al navegador y listo, el código se verá reflejado en el sitio. sirve para probar más rápidamente un cambio de un sitio en la capa web. Ahora si el proyecto web, usa un dll de otro proyecto, aunque tengas los fuentes de ese otro proyecto, si los cambias, no tomará el cambio en el proyecto web ya que ahí si requiere compilar dicha dll). Si modificas un código fuente, ASP.NET automáticamente recompila el archivo y actualiza todos los recursos que usan dicho archivo. No es necesario restetear el IIS para que tome el cambio a menos que la sección del web.config haya cambiado. Adicionalmente, puedes extender el sistema de compilación de ASP.NET al crear proveedores para que nuevos tipos de archivos sean llamados durante la compilación. La compilación dinámica beneficia al sistema de compilación de ASP.NET y es compatible con las estructuras y tipos de aplicación antiguas.

Hay ciertos aspectos que la compilación dinámica no ofrece. La Compilación dinámica puede hacer más lento el tiempo de respuesta de la carga inicial de un sitio por parte del usuario, ya que las páginas y archivos de código deben ser compilados la primera vez que son solicitados. Esto podría ser un problema si es un sitio muy grande y es cambiado frecuentemente.
La Compilación dinámica no identifica errores de compilación antes que los usuarios accedan al sitio.
También, la compilación dinámica no provee la funcionalidad de crear una versión compilada de un sitio que ya ha sido deployado en producción sin tener el código fuente.
Si alguno de esos problemas te afecta, lo mejor es precompilar el sitio y deployarlo a producción sólo con los elementos necesarios (sin todos los fuentes), un ejemplo clásico es la opción Publicar de Visual Studio. Para más información, ver ASP.NET Web Site Precompilation Overview.

Fuente


lunes, 16 de noviembre de 2015

Testeando UrlScan 3.1 para IIS 7.5

Instalación


El otro día estaba viendo algo UrlScan, es una herramienta free de Microsoft para analizar requests así protegerte de ataques SQL Injection o Script Injection de forma simple, definiendo parámetros y opciones en un archivo ini.

Bajé la versión de 64 bits de https://www.microsoft.com/en-us/download/details.aspx?id=5728

Leí la documentación de: https://support.microsoft.com/es-es/kb/326444

El .ini queda instalado por defecto en: C:\Windows\System32\inetsrv\urlscan\UrlScan.ini

(Mi .ini que usé lo dejé al final)

La carpeta con los Logs: C:\Windows\System32\inetsrv\urlscan\logs\ le dí permiso de escritura al usuario IIS. En IIS 6 darle permiso de escritura al usuario IIS_WPG, y para IIS 7 u superior dale permisos a IIS_IUSRS.

En mi caso sólo usaré un filtro global, pero si quieres aplicar el filtro sólo para un sitio web, debes registrar la DLL como filtro en Web Sites -> Properties -> ISAPI Filters como dice aquí.

Al final de la instalación, reinicié el IIS con la línea de comandos iisreset.

Pruebas


NOTA: Por cada cambio en el .ini recomiendan Reciclar el Pool del sitio probado para que tome el cambio, si embargo a veces me tomaba sin necesidad de esto.

Error tilde IIS

Para corregir este conocido error de IIS 7 y 8: Microsoft IIS tilde directory enumeration, debes ir a Inicio -> Ejecutar:

%windir%\system32\inetsrv\urlscan

Agregar en UrlScan.ini (no requiere reiniciar el servidor, si aplicar un IIS reset)

[DenyUrlSequences]
~ ; para corregir error Microsoft IIS tilde directory enumeration

NOTA: Si tienes instalado Acunetix para auditar la seguridad de tus sitios, este error de tilde lo detecta de una, pero con esta corrección deja de aparecer el error.

SQL INJECTION

Al probar con la URL que tiene un "intento" de SQL Injection:

http://misitio.cl/index.asp?select=1

Resultado: Error 404 con detalles



Resultado desde fuera del sitio: Error 404 sin detalles (este error daría si el UrlScan está en producción y queremos acceder desde afuera):



Como nota, el mismo error da cuando escribimos un "intento" de Script Injection:

http://misitio.cl/index.asp?title=<meta%20http-equiv="refresh"%20content="0;">

Logging


El log, en mi caso, urlscan.111615.log, (es 16-nov-2015) va quedando con las entradas bloqueadas y el string o secuencia inválida:

#Software: Microsoft UrlScan 3.1
#Version: 1.0
#Date: 2015-11-16 20:09:41
#Fields: Date Time c-ip s-siteid cs-method cs-uri x-action x-reason x-context cs-data x-control
2015-11-16 20:09:43 172.31.17.26 9 GET /index.asp?item=%3C Rejected disallowed+query+string+sequence query+string - <

Errores comunes

El log solo logea los títulos de las columnas

-Revisa el archivo ini, que no tengas un [Options] ya que en el ejemplo del mismo .ini dice [Options].

Yo tenía:

[Options]
RuleList=SQL Injection

Y debe ser sólo:

RuleList=SQL Injection

-Revisa que le hayas dado permisos de escritura a la carpeta log al usuario de IIS.

Conclusión


UrlScan es la solución para evitar andar programando en el código (IF request ("%, <, >, etc...) == "error") ya que sólo mediante configuración filtras todo lo malo .

Referencias



Anexo: Mi archivo ini


Mi .ini que usé es este. Notar que dejé ScanHeaders=Cookie para incluir que si se crea una Cookie, se validen los strings que tenga como valor:
[options]

UseAllowVerbs=1                ; If 1, use [AllowVerbs] section, else use the
                               ; [DenyVerbs] section.   The default is 1.

UseAllowExtensions=0           ; If 1, use [AllowExtensions] section, else
                               ; use the [DenyExtensions] section. The
                               ; default is 0.

NormalizeUrlBeforeScan=1       ; If 1, canonicalize URL before processing.
                               ; The default is 1.  Note that setting this
                               ; to 0 will make checks based on extensions,
                               ; and the URL unreliable and is therefore not
                               ; recommend other than for testing.

VerifyNormalization=1          ; If 1, canonicalize URL twice and reject
                               ; request if a change occurs.  The default
                               ; is 1.

AllowHighBitCharacters=0       ; If 1, allow high bit (ie. UTF8 or MBCS)
                               ; characters in URL.  The default is 0.

AllowDotInPath=0               ; If 1, allow dots that are not file
                               ; extensions. The default is 0. Note that
                               ; setting this property to 1 will make checks
                               ; based on extensions unreliable and is
                               ; therefore not recommended other than for
                               ; testing.

RemoveServerHeader=0           ; If 1, remove the 'Server' header from
                               ; response.  The default is 0.

EnableLogging=1                ; If 1, log UrlScan activity.  The
                               ; default is 1.  Changes to this property
                               ; will not take effect until UrlScan is
                               ; restarted.

PerProcessLogging=0            ; This property is deprecated for UrlScan
                               ; 3.0 and later.  UrlScan 3.0 and later can
                               ; safely log output from multiple processes
                               ; to the same log file.  Changes to this
                               ; property will not take effect until
                               ; UrlScan is restarted.

AllowLateScanning=0            ; If 1, then UrlScan will load as a low
                               ; priority filter.  The default is 0.  Note
                               ; that this setting should only be used in
                               ; the case where there another installed
                               ; filter is modifying the URL and you wish
                               ; to have UrlScan apply its rules to the
                               ; rewritten URL.  Changes to this property
                               ; will not take effect until UrlScan is
                               ; restarted.

PerDayLogging=1                ; If 1, UrlScan will produce a new log each
                               ; day with activity in the form
                               ; 'UrlScan.010101.log'. If 0, UrlScan will
                               ; log activity to urlscan.log.  The default
                               ; is 1.  Changes to this setting will not
                               ; take effect until UrlScan is restarted.

UseFastPathReject=0            ; If 1, then UrlScan will not use the
                               ; RejectResponseUrl.  On IIS versions less
                               ; than 6.0, this will also prevent IIS
                               ; from writing rejected requests to the
                               ; W3SVC log.  UrlScan will log rejected
                               ; requests regardless of this setting.  The
                               ; default is 0.

LogLongUrls=0                  ; This property is deprecated for UrlScan 3.0
                               ; and later. UrlScan 3.0 and later will
                               ; always include the complete URL in its log
                               ; file.

UnescapeQueryString=1          ; If 1, UrlScan will perform two passes on
                               ; each query string scan, once with the raw
                               ; query string and once after unescaping it.
                               ; If 0, UrlScan will only look at the raw
                               ; query string as sent by the client.  The
                               ; default is 1. Note that if this property is
                               ; set to 0, then checks based on the query
                               ; string will be unreliable.

;
; If UseFastPathReject is 0, then UrlScan will send
; rejected requests to the URL specified by RejectResponseUrl.
; If not specified, '/Rejected-by-UrlScan' will be used.
; Changes to this setting will not take effect until UrlScan
; is restarted.
;
; Note that setting "RejectResponseUrl=/~*" will put UrlScan into Logging
; Only Mode.  In this mode, UrlScan will process all requests per the
; config settings, but it will only log the results and not actually
; reject the requests.  This mode is useful for testing UrlScan settings
; on a production server without actually interrupting requests.
;

RejectResponseUrl=

;
; LoggingDirectory can be used to specify the directory where the
; log file will be created.  This value should be the absolute path
; (ie. c:\some\path).  If not specified, then UrlScan will create
; the log in the same directory where the UrlScan.dll file is located.
; Changes to this setting will not take effect until UrlScan is
; restarted.
;

LoggingDirectory=Logs

;
; If RemoveServerHeader is 0, then AlternateServerName can be
; used to specify a replacement for IIS's built in 'Server' header
;

AlternateServerName=

;
; UrlScan supports custom rules that can be applied in addition to the other
; checks and options specified in this configuration file.  Rules should be
; listed in a comma separated string in the RuleList property.  Each rule in
; the list corresponds to two sections in this configuration file, one
; containing the options for the rule, and one containing deny strings for
; the rule.
;
; Here is an example:
;
;   [Options]
;   RuleList=Rule1
;
;   [Rule1]
;   AppliesTo=.exe,.dll        ; A comma separated list of file extensions to
;                              ; which the rule applies.  If not specified,
;                              ; the rule will be applied to all requests.
;
;   DenyDataSection=Rule1 Data ; The name of the section containing the
;                              ; rule's deny strings
;
;   ScanURL=0                  ; If 1, the URL will be scanned for deny
;                              ; strings. The default is 0.
;
;   ScanAllRaw=0               ; If 1, then the raw request header data will
;                              ; be scanned for deny strings.  The default
;                              ; is 0.
;
;   ScanQueryString=0          ; If 1, the the query string will be scanned
;                              ; for deny strings.  The default is 0.  Note
;                              ; that if UnescapeQueryString=1 is set in the
;                              ; [Options] section, then two scans will be
;                              ; made of the query string, one with the raw
;                              ; query string and one with the query string
;                              ; unescaped.
;
;   ScanHeaders=               ; A comma separated list of request headers to
;                              ; be scanned for deny strings.  The default is
;                              ; no headers.
;
;   DenyUnescapedPercent=0     ; If 1, UrlScan will scan the specified part
;                              ; of the raw request for a % character that is
;                              ; not used as an escape sequence.  If found,
;                              ; the request will be rejected.  This check
;                              ; can be used with ScanQueryString=1,
;                              ; ScanAllRaw=1, or the list of ScanHeaders.
;                              ; The default is 0.  Note that if you want to
;                              ; deny non-escaped % characters in the URL,
;                              ; you can set VerifyNormalization=0 in the
;                              ; [Options] section and then add % as a
;                              ; [DenyUrlSequences] entry.
;
;   [Rule1 data]
;   string1
;   string2
;

RuleList=SQL Injection

[SQL Injection]
AppliesTo=.asp,.aspx
DenyDataSection=SQL Injection Strings
ScanUrl=0
ScanAllRaw=0
ScanQueryString=1
ScanHeaders=Cookie:


[SQL Injection Strings]
--
@ ; also catches @@
alter
cast
convert
create
declare
delete
drop
exec ; also catches execute
fetch
insert
kill
select

[RequestLimits]

;
; The entries in this section impose limits on the length
; of allowed parts of requests reaching the server.
;
; It is possible to impose a limit on the length of the
; value of a specific request header by prepending "Max-" to the
; name of the header.  For example, the following entry would
; impose a limit of 100 bytes to the value of the
; 'Content-Type' header:
;
;   Max-Content-Type=100
;
; Any headers not listed in this section will not be checked for
; length limits.
;
; There are 3 special case limits:
;
;   - MaxAllowedContentLength specifies the maximum allowed
;     numeric value of the Content-Length request header.  For
;     example, setting this to 1000 would cause any request
;     with a content length that exceeds 1000 to be rejected.
;     The default is 30000000.
;
;   - MaxUrl specifies the maximum length of the request URL,
;     not including the query string. The default is 260 (which
;     is equivalent to MAX_PATH).
;
;   - MaxQueryString specifies the maximum length of the query
;     string.  The default is 2048.
;

MaxAllowedContentLength=30000000
MaxUrl=260
MaxQueryString=2048

[AllowVerbs]

;
; The verbs (aka HTTP methods) listed here are those commonly
; processed by a typical IIS server.
;
; Note that these entries are effective if "UseAllowVerbs=1"
; is set in the [Options] section above.
;

GET
HEAD
POST

[DenyVerbs]

;
; The verbs (aka HTTP methods) listed here are used for publishing
; content to an IIS server via WebDAV.
;
; Note that these entries are effective if "UseAllowVerbs=0"
; is set in the [Options] section above.
;

PROPFIND
PROPPATCH
MKCOL
DELETE
PUT
COPY
MOVE
LOCK
UNLOCK
OPTIONS
SEARCH

[DenyHeaders]

;
; The following request headers alter processing of a
; request by causing the server to process the request
; as if it were intended to be a WebDAV request, instead
; of a request to retrieve a resource.
;

Translate:
If:
Lock-Token:
Transfer-Encoding:

[AllowExtensions]

;
; Extensions listed here are commonly used on a typical IIS server.
;
; Note that these entries are effective if "UseAllowExtensions=1"
; is set in the [Options] section above.
;

.htm
.html
.txt
.jpg
.jpeg
.gif

[DenyExtensions]

;
; Extensions listed here either run code directly on the server,
; are processed as scripts, or are static files that are
; generally not intended to be served out.
;
; Note that these entries are effective if "UseAllowExtensions=0"
; is set in the [Options] section above.
;
; Also note that ASP scripts are denied with the below
; settings.  If you wish to enable ASP, remove the
; following extensions from this list:
;    .asp
;    .cer
;    .cdx
;    .asa
;

; Deny executables that could run on the server
.exe
.bat
.cmd
.com

; Deny infrequently used scripts
.htw     ; Maps to webhits.dll, part of Index Server
.ida     ; Maps to idq.dll, part of Index Server
.idq     ; Maps to idq.dll, part of Index Server
.htr     ; Maps to ism.dll, a legacy administrative tool
.idc     ; Maps to httpodbc.dll, a legacy database access tool
.shtm    ; Maps to ssinc.dll, for Server Side Includes
.shtml   ; Maps to ssinc.dll, for Server Side Includes
.stm     ; Maps to ssinc.dll, for Server Side Includes
.printer ; Maps to msw3prt.dll, for Internet Printing Services

; Deny various static files
.ini     ; Configuration files
.log     ; Log files
.pol     ; Policy files
.dat     ; Configuration files
.config  ; Configuration files

[AlwaysAllowedUrls]
;
; URLs listed here will always be explicitly allowed by UrlScan
; and will bypass all UrlScan checks.  URLs must be listed
; with a leading '/' character.  For example:
;
;   /SampleURL.htm
;

[DenyUrlSequences]
;
; If any character sequences listed here appear in the URL for
; any request, that request will be rejected.
;

..  ; Don't allow directory traversals
./  ; Don't allow trailing dot on a directory name
\   ; Don't allow backslashes in URL
:   ; Don't allow alternate stream access
%   ; Don't allow escaping after normalization
&   ; Don't allow multiple CGI processes to run on a single request

[AlwaysAllowedQueryStrings]
;
; Query strings listed here will always be explicitly allowed by
; UrlScan and will bypass all query string based checks.
;


[DenyQueryStringSequences]
;
; If any character sequences listed here appear in the query
; string for any request, that request will be rejected.
;

<   ; Commonly used by script injection attacks
>   ; Commonly used by script injection attacks

lunes, 9 de noviembre de 2015

NullReferenceException en método AjaxRequestProcessor.Run() con AjaxPro 5.7.22.2

Antecedentes


Alguien se le ocurrió una vez, que la mejor forma de conectarse de forma asíncronica desde Javascript (no existía jQuery como ahora) al servidor Web era usando AjaxPro (Ajax.dll). Bueno, eso funcionó, pero trajo un problema arrastrado por años, ahora que me dijeron "resuélvelo de una vea papá". Bueno, el error lo logré resolver luego de semanas cabezeandome. El mensaje en el Visor de Eventos decía en resumen:

NullReferenceException en Ajax.AjaxRequestProcessor.Run()

Antecedentes productivos:

  • Se usaron dos tipos de servidores, web primero Windows Server 2003 32 bit y luego Windows Server 2008 64 bit.
  • El ambiente productivo usa Framework 2.0 y Visual Basic .NET.
  • La arquitectura es un balanceador con 4 servidores Web y un servidor de base de datos.
  • Son 4 aplicaciones Web, las 4 usan 4 AppPool, 3 AppPool tienen 3 worker process y uno tiene 7. Todos tienen diferente tiempo de reciclaje.
  • El ambiente tiene mediana carga 2000 RPM (Request por Minuto) según la fabulosa herramienta Newrelic.
  • Las 4 aplicaciones usan Ajax.dll 5.7.22.2 liberada por el año 2005.

Antecedentes del error:

  • El error da irregularmente, sin un horario dado.
  • El problema puede dejar de dar durante días.
  • El error no daba en ambiente de desarrollo (lo típico).

El error registrado en el visor de Eventos es:

Event code: 3005 
Event message: An unhandled exception has occurred. 
Event time: 10/18/2015 3:12:47 PM 
Event time (UTC): 10/18/2015 6:12:47 PM 
Event ID: 305bbfa9f184433986b6655786e66f72 
Event sequence: 50 
Event occurrence: 1 
Event detail code: 0 
 
Application information: 
    Application domain: /LM/W3SVC/416041936/Root/SitioTest-1-130896653636875000 
    Trust level: Full 
    Application Virtual Path: /SitioTest 
    Application Path: C:\Inetpub\wwwroot\Test\Sitio\1.0\SitioTest\ 
    Machine name: Servidor-1 
 
Process information: 
    Process ID: 6948 
    Process name: w3wp.exe 
    Account name: NT AUTHORITY\NETWORK SERVICE 
 
Exception information: 
    Exception type: NullReferenceException 
    Exception message: Object reference not set to an instance of an object. 
 
Request information: 
    Request URL: http://sitio.cl/folder/ajax/SitioWebDotNet.namespace_clase,App_Web_datos.aspx.fe7917e2.ashx 
    Request path: /sitio/ajax/SitioWebDotNet.sitio_namespace_sitio,App_Web_datos.aspx.fe7917e2.ashx 
    User host address: X.X.X.X 
    User:  
    Is authenticated: False 
    Authentication Type:  
    Thread account name: NT AUTHORITY\NETWORK SERVICE 
 
Thread information: 
    Thread ID: 1 
    Thread account name: NT AUTHORITY\NETWORK SERVICE 
    Is impersonating: True 
    Stack trace:    at Ajax.AjaxRequestProcessor.Run()
   at Ajax.AjaxHandler.ProcessRequest(HttpContext context)
   at System.Web.HttpApplication.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()
   at System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously)
 
 
Custom event details: 

For more information, see Help and Support Center at http://go.microsoft.com/fwlink/events.asp.

Si uno miraba el contenido del ashx indicado en el error: http://sitio.cl/folder/ajax/SitioWebDotNet.namespace_clase,App_Web_datos.aspx.fe7917e2.ashx, no había nada raro.

Lo que intenté, sin que funcionara

  • Cambiar la DLL 5.7.22.2 a la última versión 9.2.17.1. No fue posible por que la versión que uso no usa JSON y la nueva usa JSON, cambiar todo el código, validar las entradas y salidas era mucho trabajo, quizá de meses.
  • Dejar sólo un servidor, sacándolo del balanceador de carga.
  • Revisar el código fuente: JS, código VB.Net, no encontré errores.
  • Dejar todos los Pool con 3 WP y el mismo tiempo de reciclaje.
  • Evalué pasar de AjaxPro a Ajax 1.0 de Microsoft, pero la cantidad de código era inmensa.
  • El error no da cuando se recicla un pool, era una teoría que tenía
  • Revisé los LOGS de IIS de los 4 servidores y no había algún de patrón del error, que fallara en todos a una hora, o que luego de un reciclaje de los pool fallara.

Solución


La solución fue para cada uno de los 4 Pool de las aplicaciones bajar todos los Worker Process a 1. De pasada dejarles el mismo tiempo de reciclaje. Me acordé que en el blog de Google se hablaba que tenía problemas en balanceo, y quizá pensé el error se da en Web Farm y Web Garden. Y era eso, ¡toque y fama!. Luego de monitorear los errores del visor de eventos durante 2 semanas observé que el problema desapareció. Recomiendo usar para visualizar de mejor forma los Event Logs la herramienta Event Log Explorer, que tiene una licencia Free.

Referencias



Bueno, espero que les sirva de ayuda, en caso que tengan este engorroso error.

lunes, 28 de septiembre de 2015

Combo autocomplete VS 2005 Framework 2.0 VB.Net con jQueryUI

Hola, a todos los geeeks. El otro día me pidieron hacer combo autocomplete para una aplicación Web en Visual Studio 2005, Framework 2.0 y además con VB.NET. Tarea que no fue de media hora como pensé.

Primero en aplicación Web se llaman DropDownList y no Combobox como en las aplicaciones de Escritorio.

Vamos a usar jQuery y jQueryUI.

Lo otro importante es que no implementaremos un combo propiamente autocomplete, sino que haremos un textbox autocomplete, ese el truco. Se verá como un combo pero no lo es.

Código de ASPX

<%@ Page Language="vb" AutoEventWireup="false" CodeBehind="Default.aspx.vb" Inherits="TestCombo._Default" %>

<!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>Demo autocomplete textbox VB.Net 2005 jQuery</title>    
    <link rel="stylesheet" href="css/jquery-ui.css"> 
    <script type="text/javascript" src="js/jquery-1.11.0.min.js"></script> 
    <script src="js/jquery-ui-1.10.3.custom.js"></script>
</head>
<body>

    <% =Autocompletar()%>    

    <script type="text/javascript">
        $(document).ready(function() {
         Autocompletar();       
        });
    </script>

    <form id="form1" runat="server">        
        <input type="text" name="combo" id="combo" class="combo" placeholder="Escriba dos letras" maxlength="50" size="50" />        
        <br />
        Valores posibles:<br /><br />
        Hamburguesa, Hamburguesa c/ queso, Quesadillas, Torta de pierna, Torta mixta, Torta ahogada, Paquete Torta con refresco, Refresco, Café, Té 
</form>
</body>
</html>

Código de VB.NET

Partial Public Class _Default
    Inherits System.Web.UI.Page

    Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load

    End Sub

    Public Function Autocompletar() As String
        Dim tags As String

        tags = "'Hamburguesa','Hamburguesa c/ queso','Quesadillas','Torta de pierna','Torta mixta','Torta ahogada','Paquete Torta con refresco','Refresco','Café','Té'"

        Autocompletar = ""

    End Function

End Class
La Solución se ve así:

Probando

Si seleccionamos un elemento se ve el combo:

Luego si usamos la consola de Chrome con F12 y ejecutamos

$('#combo').val()

La consola entrega: "Paquete Torta con refresco"

lunes, 20 de julio de 2015

Forms TimeOut vs sessionState Timeout vs ExecutionTimeout

En este artículo hablaremos de los timeout que se configuran en el web.config en aplicaciones .Net:

  • timeout del tag Form
  • timeout del tag sessionState
  • ExecutionTimeout del tag httpRuntime

Ejemplo de una configuración del web.config:

<system.web>
<authentication mode="Forms">
<forms name="test" loginUrl="~/test.aspx" protection="All" path="/" timeout="40" slidingExpiration="false/true" />
</authentication>

<httpRuntime maxRequestLength="138000" executionTimeout="36000"></httpRuntime>
<sessionState timeout="480"></sessionState>
</system.web>

timeout del tag Form


Por defecto 30 minutos. En el ejemplo está en 40 minutos. Es el tiempo en minutos que el ticket de autenticación es válida (no de la cookie donde esté almacenada el ticket que puede tener otro tiempo o no tener por lo que caduca cuando se cierra el navegador), pasado este tiempo el ticket expira, y al siguiente request te tira al sitio de inicio/login deforma automática. En caso de que la cookies es persistente, el tiempo de timeout es el mismo entre el ticket y la cookie donde está la cookie.

slidingExpiration: Por defecto True en todos los Frameworks, aunque en MSDN hay un error ya que en algunas referencias dice que es False para Framework 2.0 pero en los mismos comentarios MSDN dicen que es True, por ejemplo aquí indica que es True: https://msdn.microsoft.com/en-us/library/system.web.security.formsauthentication.slidingexpiration(v=vs.80).aspx y aquí dice que por defecto es False para Framework 2.0: https://msdn.microsoft.com/es-cl/library/1d3t3c61(v=vs.80).aspx. Bueno oficialmente por defecto es True para todos los Frameworks.

En modo false es lo que es conocido como absolute expiration, si el tiempo timeout es 30 (30 min) si un usuario hace un request a las 13 hrs, luego si a las 13:31 hace un nuevo request, este no se procesará y en cambio, le dejará automáticamente en el login.

En modo true, sliding expiration (expiración corrida), la cookie y el ticket se actualizan si el usuario hace un request luego que haya pasado la mitad del tiempo. Por ejemplo si el timeout es 20 y usas sliding expiration en true, y el usuario visita el sitio a las 14 hrs, el usuario recibirá una cookie que expirará a las 14:20 hrs. La cookie se actualiza solo si el usuario visita el sitio luego de las 14:10 hrs.
Si el usuario hace una visita a las 14:12 hrs, la cookie se actualiza y ahora expirará a las 14:32 hrs.
Si el usuario visita el sitio a las 14:09 hrs, la cookie no se actualizará y si se da que el usuario visita el sitio a las 14:21 hrs, el ticket estará expirado y lo dejará en el home de forma automática.

Cuando ticket expira, da el famoso error de Ticket expirado:

Event code: 4005
Event message: Forms authentication failed for the request. Reason: The ticket supplied has expired.


Si no usa el tag authentication en el web.config, por defecto el Framework lo setea así (en Framework 2.0): https://msdn.microsoft.com/en-us/library/532aee0e(v=vs.80).aspx para v2.0, o https://msdn.microsoft.com/en-us/library/532aee0e(v=vs.100).aspx para v4.0.

<authentication mode="Windows">
</authentication> Este modo en el web.config es solo para decirle a .NET como manejar la autenticación no tiene que ver con IIS o el servidor.
De echo, si miras IIS en la sección Autenticación, solo quedará el modo anónimo que es el modo que por defecto trae habilitado. Si quieres modo Windows Authentication y que pida el usuario y clave, debes cambiar en el IIS en la sección Autenticación, y dejar modo Anónimo desactivado y Windows modo activado. Y al ejecutar el sitio pedirá un usuario y clave de Windows.

Si se cambia en el IIS 7 esta configuración, estás afectando a la sección de tu web.config:
system.webServer/security/authentication o applicationHost.config
Y no a <authentication> de <system.web>
En IIS 6 este cambio afecta a la metabase y no a un web.config.

Si no usa el tag forms dentro de authentication en el web.config, por defecto el Framework lo setea así (en Framework 2.0): https://msdn.microsoft.com/es-cl/library/1d3t3c61(v=vs.80).aspx

<forms
name=".ASPXAUTH"
loginUrl="login.aspx"
defaultUrl="default.aspx"
protection="All"
timeout="30"
path="/"
requireSSL="false"
slidingExpiration="true"
cookieless="UseDeviceProfile" domain=""
enableCrossAppRedirects="false">
<credentials passwordFormat="SHA1" />
</forms>

timeout del tag sessionState


Por defecto es 20 minutos. Es el tiempo en minutos que estarán los datos en memoria para una sesión en particular. Por ejemplo, si guardas un objeto en la clase Session se pierde la información a los 480 minutos. El time out se resetea en cada request.
Solo válido si se usa sessionState, es decir que no está como:

<sessionState mode="Off">

Como dato, por defecto el sessionState es InProc:

<sessionState mode="InProc">

Si no usa el tag sessionState en el web.config, por defecto el Framework lo setea así en Framework 2.0: https://msdn.microsoft.com/en-us/library/h6bb9cz9(v=vs.80).aspx

<sessionState
mode="InProc"
stateConnectionString="tcpip=127.0.0.1:42424"
stateNetworkTimeout="10"
sqlConnectionString="data source=127.0.0.1;Integrated Security=SSPI"
sqlCommandTimeout="30"
customProvider=""
cookieless="UseCookies"
cookieName="ASP.NET_SessionId"
timeout="20"
allowCustomSqlDatabase="false"
regenerateExpiredSessionId="true"
partitionResolverType=""
useHostingIdentity="true">
<providers>
<clear />
</providers>
</sessionState>

executionTimeout del tag httpRuntime


Por defecto es 110 segundos. En el ejemplo tiene 36000 (10 hrs). Es el número máximo de segundos que se permite que se ejecute una solicitud antes de que ASP.NET la concluya automáticamente y quede como failed o de el famoso error The request has been aborted. Request timed out.

Este tiempo de espera solo se aplica si el atributo de depuración del elemento

<compilation> está establecido en false. Así que executionTimeout sólo lo toma funciona en modo release, de lo contrario toma el valor por defecto, 110 seg.

Si estas haciendo una aplicación que sube un archivo pesado, por ejemplo de 50 MG, este valor debe ser por ejemplo 3600 (1 hr) para que .NET no la cierre automáticamente.

Tamaño de archivos de subida: maxRequestLength y maxAllowedContentLength

Si quieres permitir que el peso máximo de un archivo a subir sea de 200 MB debes setear dos tag maxRequestLength y maxAllowedContentLength ambos deben ir en el web.config.

El tag maxRequestLength está en KB e indica el tamaño máximo de un archivo soportado por ASP.NET. Si son 200 MB el valor sería 2048000. Por defecto está en 4096 es decir 4 MB.

Si no se usa el tag httpRuntime en el web.config, por defecto el Framework lo setea así en Framework 2.0: https://msdn.microsoft.com/en-us/library/e1f13641(v=vs.80).aspx

<httpRuntime
executionTimeout="110"
maxRequestLength="4096"
requestLengthDiskThreshold="256"
useFullyQualifiedRedirectUrl="false"
minFreeThreads="8"
minLocalRequestFreeThreads="4"
appRequestQueueLimit="5000"
enableKernelOutputCache="true"
enableVersionHeader="true"
requireRootedSaveAsPath="true"
enable="true"
shutdownTimeout="90"
delayNotificationTimeout="5"
waitChangeNotification="0"
maxWaitChangeNotification="0"
requestPriority="Normal"
enableHeaderChecking="true"
sendCacheControlHeader="true"
apartmentThreading="false"
/>

En IIS 7 además se debe setear el atributo maxAllowedContentLength que está en Bytes, indica el tamaño máximo de un archivo a subir soportado por IIS. Aquí los 200 MB serían 2097152000. El valor por defecto es 30000000, lo que equivale a 28.6 MB.
Ojo si que en IIS 7 este valor va en una estructura aparte:

<system.webServer>
<security>
<requestFiltering>
<requestLimits maxAllowedContentLength="2097152000"/>
</requestFiltering>
</security>
</system.webServer>

NOTA: Si estás con IIS 7 o superior, debes setear AMBOS TAG en el mismo valor, sino tomará el menor de ellos como el valor con prioridad.

Referencias


martes, 14 de julio de 2015

Configuración correcta del plugin de video ePSXe 1.9.0 para Chrono Cross de PSX

Como saben algunos, un grupo de expertos romhackers ha traducido hace un tiempo el Chrono Cross de PSX al Español, de hecho la última versión del parche salió en agosto del 2014. El parche se puede descargar de su sitio oficial http://www.chronocrossesp.esforos.com/portal.php. Una vez lo dejé en español, me di cuenta que hay muchas configuraciones posibles en el plugin de video del ePSXe para dejar el juego funcionando a la perfección.


En este artículo expondré dos configuraciones de video para Chrono Cross de PSX usando el emulador ePSXe y veremos su diferencia.

EL PC que use es un core i7, tiene Windows 8.1 y una buena tarjeta de video.

Bajar el emulador y plugin


Bajar la versión 1.9.0 del emulador desde: http://www.epsxe.com/ (aun no he probado si lo aquí explicado anda bien con la última versión 1.9.25 salida en enero de este 2015)

Luego debes bajar el plugin de video Pete's OpenGL2 PSX GPU versión 2.9 de: http://www.pbernert.com/html/gpu.htm

Configuración


Esta configuración es una opción, se ve muy bien, modo ventana de 1280 x 800, con un efecto Shared level 4 toma un efecto nublado, como si estuviéramos en una TV (haz clic sobre la imagen para agrandarla):

Los efectos al entrar en batalla se ven ok:


Si la opción Shared level lo dejas en 1, se ve más al estilo PC, sin ese suavizado. Personalmente me gusta más:



Usar Suprimir durante el juego

Puedes usar tecla Suprimir del teclado para ejecutar algunos cambios de opciones gráficas o de frames por segundo durante la ejecución del juego. Yo recomiendo usar esta para una mejor fluidez a 60 FPS:

Presionar Supr y se verá esto:
Luego presiona tecla Avanzar Página, y presionar tecla Inicio para cambiar la configuración y dejarla en 0:
Con ese menú superior morado abierto, con la tecla Insert se ve la descripción de dichas opciones:

Adelantar con F4


Con F4 puedes saltar frames por lo tanto es como jugar en cámara rápida, esto es muy útil cuando no quieres avanzar o correr grandes distancias a la velocidad normal del juego.

Algunos errores típicos


Si de ta el error de WNASPI32.dll al iniciar baja esta dll de aquí y déjala en el mismo directorio que el epsx.exe.

Si te da el error Missing Render Texture Extension! al ejecutar la ISO, debes cambiar la configuración del Plugin de video:

  • Streching mode: 1 Scale to windows...
  • Render mode: 1 Render to buffer...

Mas info aquí: https://www.youtube.com/watch?v=SJtIGq91sR4

Referencias


viernes, 10 de julio de 2015

Cómo Jugar The Dig de Steam y parcharlo al Español

Obteniendo el juego

Hola, ahora les traigo The Dig, la versión lazada en 1995 para Steam. Primero deben comprarlo por 5,99 USD o adquirir "por ahí" la versión en inglés:

http://store.steampowered.com/app/6040/?l=spanish

La versión de Steam, juego tiene los videos, textos y voces en Inglés. Lo he probado en Windows XP/7/8.



Parche para dejarlo en español

El Parche lo deja sólo con los textos en Español. Los video y voces siguen en Inglés.

El parche se descarga de:

http://traducciones.clandlan.net/index.php?page=academia%2Fsearch&search=The+Dig

Allí escriben el captcha y hacen clic en ¡Descarga!, con eso se descargará un ZIP que pesa apenas 239 KB. El ZIP lo descomprimes y adentro hay un The_Dig_castellano.exe. Ejecuta ese .exe y selecciona una carpeta del disco como C:\Temp\

Ahora ve a C:\Temp\ y verás una carpeta VIDEO y una archivo LANGUAGE.BND. Copia dichos archivos en:

C:\Program Files (x86)\Steam\steamapps\common\The Dig\DIG

Si Windows te consulta si quieres sobrescribir, escoge que si.

Finalmente juega de nuevo y verás el juego traducido. Con F5 se ven las opciones como Cargar, Grabar o Salir.






viernes, 26 de junio de 2015

¿El ViewState de ASP.NET está poniendo lenta tu página?

Un desafío muy común entre desarrolladores y diseñadores web es crear sitios web que sean interactivos, con buen diseño, responsivos y que carguen rápido, de esta forma mantener al usuario feliz. ASP.NET es una plataforma de desarrollo fantástica, pero como desarrolladores podemos tener problemas de performance causados por el viewstate, sobretodo si trabajamos con .Net Framework 2.0.

¿Que es el viewstate?

El Viewstate es una técnica usada por ASP.NET para manejar los estados de los web forms a través de los postbacks. Un postback es un intercambio de datos de un formulario con el server. El viewstate de una página es, por defecto, almacenado en un campo oculto del formulario de la página web llamado __VIEWSTATE y es de donde pueden surgir los problemas:

< input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" value="/wEPDwULLTEwNzcyMTI4ODkPZBYCAgMPZBYGAgMPD2QWAh4Dc3JjBRVDb250cm9sL0dldEltYWdlLmFzaHhkAgcPDxYCHgRUZXh0BSJNw7NkdWxvIENhcnRlcmEgLSBNZWRpc3luIENvbG9tYmlhZGQCCQ8PFgIfAQUIQ3RyMDAxaXdkZBgBBR5fX0NvbnRyb2xzUmVxdWlyZVBvc3RCYWNrS2V5X18WAgULaWJ0bkFjZXB0YXIFC2lidG5MaW1waWFyA3FR8EtTrIE9o6Xpg7IeJ9eVFzg=" >

¿Porque es un problema?

El volumen de datos almacenado en este campo oculto puede ser muy largo. Esto implica que se incrementa la carga de la página y ya que todo el contenido del campo oculto debe ser intercambiado durante un postback, se puede ver un notorio aumento del tiempo de completitud del request HTTP.

Los desarrolladores web actualmente están dispuestos a pulir el sitio, dejándolo operativo para conexiones lentas, mantenido el user-friendly, todo esto para minimizar el tamaño de datos almacenado e intercambiado en el viewstate. A esto hay que sumarle que Google confirmó que el tiempo de carga de un sitio web es uno de los factores que influye en como aparecen en el SERP, lo que hace que el desarrollador web se incentive a que el sitio cargue rápido. Quizá lo que más importa, desde la perspectiva de SEO, es que los datos de un viewstate en general preceden al contenido de una página importante en el orden de origen y puede inflar significativamente el código de la página.

¿Qué podemos hacer?

1) En general, un sitio no debería basarse en el viewstate. Esto debe ser decidido en un comienzo ya que desactivarlo una vez el sitio está desarrollado puede traer resultados inesperados (y el sitio dejará de funcionar).

2) Considera el uso de otros controles de estado de formulario, por ejemplo session state, application state, manualmente poblar/restaurar campos ocultos, cookies. El ASP.NET Cache puede ser usado para almacenar datos o repoblar controles para prevenir vueltas innecesarias a la base de datos.

3) Si usas controles de servidor intenta restringir el uso de tipos simples, por ejemplo repetidores en vez data grid/view.

4) El Viewstate puede ser eliminado de una página web cuando no se usan formularios o controles de servidor (con el atributo runat="server"), sin embargo el desarrollador es el responsable de escribir el código para hacer los post de los formularios manualmente al estilo antiguo (Request.Form, por ejemplo http://www.w3schools.com/asp/asp_inputforms.asp).

5) Viewstate puede ser desactivado de una aplicación, página o control usando el tag enableViewState="false". Si desactivas el viewstate de toda la aplicación se mantendrá "cierto" viewstate en todas las páginas (como el viewstate es usado para manejar que controles requieren postback). Esta es la forma de comunicación entre ASP.NET Web Forms y el modelo de postback.

6) En la mayoría de los casos, basta con desactivar el viewstate de un control y asegurarse que están llegando todos los datos en cada postback, proveen una reducción suficiente en el tamaño del viewstate. Cuando se hace esto, se debe repoblar los controles en el evento Init, no en evento Load. Hacer el data binding durante el evento Load tiene el riesgo de sobreescribir los valores los cuales serán restaurados desde los Formularios durante el evento Load.

7) Puedes ver que páginas están usando de forma intensa el viewstate con una muy buena herramienta llamada ASP.NET View State Helper: http://www.binaryfortress.com/aspnet-viewstate-helper.
Explicación de las columnas en el herramienta:

  • Page Size: bytes que pesa la página de la columna Page URL.
  • View State Size: tamaño en bytes que pesa el viewstate y la cantidad de chunks si está dividido
  • View State %: del total de la página, cuanto % es del View State
  • View State %: del total de la página, cuanto % es del View State. Si es muy alto coloca amarillo.
  • Markup Size: tamaño en bytes del HTNL del código de la página que no es texto visible.
  • Markup %: del total del tamaño de la página, cuando corresponde a código no visible. El color amarillo por lo que leí acá el amarillo en esta columna significa que el valor está sobre un 90% o bajo un 10%.

8) Los ViewState muy grandes pueden ser fragmentada (chunk) en un número más pequeño de campos usando la opción maxPageStateFieldlength del web.config file. Esta opción permite setear la cantidad máxima en bytes. Por defecto es -1, por lo que no está dividido, pero si colocamos un entero, se dividirá hasta alcanzar ese valor. Por ejemplo si ponemos 40 se dividirá en trozos muy pequeños, pero si usamos 500 serán más grandes. Por ejemplo, usaremos chunks de 256 bytes por ejemplo quedaría así:

Si tenemos un ViewState:

<input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" value="/wEPDwUKLTk2Njk3OTQxNg9kFgICAw9kFgICCQ88KwANAGQYAQUJR3JpZFZpZXcxD2dk4sjERFfnDXV/hMFGAL10HQUnZbk=" />

Si cambiamos maxPageStateFieldlength en el web.config para dejar 256 bytes:

<system.web>
...
<pages maxPageStateFieldLength="256">
...
</system.web>

Así se verá el ViewState:

<input type="hidden" name="__VIEWSTATEFIELDCOUNT" id="__VIEWSTATEFIELDCOUNT" value="3" />
<input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" value="/wEPDwUKLTk2Njk3OTQxNg9kFgICAw9kFgICCQ88" />
<input type="hidden" name="__VIEWSTATE1" id="__VIEWSTATE1" value="KwANAGQYAQUJR3JpZFZpZXcxD2dk4sjERFfnDXV/" />
<input type="hidden" name="__VIEWSTATE2" id="__VIEWSTATE2" value="hMFGAL10HQUnZbk=" />

En la herramienta ASP.NET ViewState Helper así se ven los chunks:


9) El modelo ASP.NET MVC no usa ViewState. Considera usar MVC para la capa interfaz de tu aplicación y mantener lo que tienes del modelo de Web Form para el negocio o acceso a datos. MVC lo puedes usar con el Framework .NET 3.5 en adelante.

10) ASP.NET 4.0 Web Forms incluye la propiedad ViewStateMode, el cual permite desactivar el viewstate por defecto y activarlo solo a los controles que lo requieran.

Esperemos que estas sugerencias ayuden a los desarrolladores que luchan por bajar unos pocos kilobytes de sus páginas .NET.

No confundir errores de ViewState con errores de programación

A veces, sucede que se le puede atribuir al ViewState, errores que no son de este, pero si de programación JavaScript o de código ASPX (VB.NET o C#). Recomiendo validar el ViewState y ver que si sube pero luego se mantiene, el problema puede ser otro. En mi caso subía hasta 12000 bytes si lo analizaba con ASP.NET ViewState Helper, pero pasado ciertos request se mantenía en ese valor.
Si sucede esto, el problema puede no ser el ViewState, sino un código erróneo en la aplicación, en mi caso era un error de código JavaScript y la forma de detectarlo fue usando las herramientas de Internet Explorer o Chrome, ambos con F12, usando el Generador de Perfiles en IE o Profiles en Chrome.

En IE aparece un árbol de llamadas y allí se ven los tiempos y el número de veces que se ejecuta cierta función del JavaScript. En mi caso, aparecía una función que se llamaba 131 mil veces en cierto momento. La solución fue comentar un línea de código.

Generador de Perfiles de IE 8.

Generador de Perfiles de IE 11.

En Chrome se debe escoger el tipo de Perfil y presionar START. Luego se verán las llamadas y tiempos de las funciones JavaScript. Con Control + F puedes buscar un nombre de función, por si tienes alguna pista de algo que podría andar lento.





Referencias


Traducción con aclaraciones y mejoras del artículo: http://www.freshegg.co.uk/blog/web-design/creating-lean-fast-web-pages-view-state

jueves, 18 de junio de 2015

Jugar Riven, la sequela de Myst por Steam y parche al Español

En Steam están con las famosas Summer Sales hasta el 21/junio y el clásico juego Riven, la secuela de Myst está a 2 dólares!: http://store.steampowered.com/app/63610/.


Ahora, si probamos el juego de Steam, (en mi caso lo probé con Windows 8.1), veremos que está tanto textos como voces en Inglés. Para dejar los textos y las voces en Español encontré este grandioso parche:

http://www.clandlan.net/foros/topic/76623-traduccion-riven-the-sequel-to-myst/

Aquí están los enlaces directos:

https://mega.co.nz/#!uE5mhAYA!lWY5qKQ767FM9nyryv8dH9WagTeaH0fzOWfVbgCpjj8
https://mega.co.nz/#!rA4DiT4S!V3sA6D1nZXG2_VatV9qw6sHKmjlMcMT2UsEjjs3D4sE
https://mega.co.nz/#!mRRT2bwZ!pfruCB0lbfLNizF9ktfhK_U5byRmd4IlfsbjZI37gvA
https://mega.co.nz/#!DchCVIwQ!bdb_hC7eJMTKcg5yvOUK3faGT6c4Ti3aobZNQ2GgC_M

Estos 4 archivos que sumados pesan 1.83 GB, se deben descomprimir en una carpeta. Finalmente quedará una carpeta Data con varios archivos adentro pesando 2.67 GB.

Luego copias el contenido de ese Data dentro de:

C:\Program Files (x86)\Steam\steamapps\common\Riven\Data

Finalmente probamos de nuevo el juego y listo. Con la tecla ALT puedes guardar una partida, cargar o salir del juego.

En mi caso guarde una partida cuando lo tenía en Inglés, luego pasé al Español y pude cargar la partida normalmente.

NOTA 1: El juego tiene algunos problemas a veces y se cuelga en Windows XP/Vista/8/7, por lo que cada vez que salves, hazlo en 3 partidas a la vez (usando SAVE AS/GUARDAR COMO). Me ha pasó 2 veces un mismo día que estaba salvando y se colgó justo cuando salvaba, luego al cargar no me dejó ya que el archivo estaba corrupto :(

NOTA 2: A veces inicias el juego y cuando quieres cargar, el juego no te deja o presionas la tecla ALT y no sale el menú Load/Cargar. En ese caso, espera los videos, presiona ESPACIO para saltártelos, y al final cuando tengas el control del mouse, allí presiona ALT para cargar.



miércoles, 17 de junio de 2015

¿Cómo determinar que cuenta es la que IIS usa para ejecutar un sitio Web?

Es importante entender que cuenta es la que IIS ejecuta en un sitio web dado, sobretodo cuando necesitas hacer cambios a las opciones de seguridad. Por ejemplo, tu aplicación web escribe archivos en el disco o en una base de datos (por ejemplo un Access .mdb) y te toca darle los permisos correctos a dicha carpeta o base de datos. Antes de cambiar esas opciones de seguridad, deberías saber que cuenta está usando IIS. Este artículo detalla varias opciones disponibles, tanto para el ASP clásico como para ASP.NET.

Hay una gran diferencia entre las aplicación ASP y ASP.NET cuando se quiere determinar el contexto de usuario que ejecuta el IIS, así que este documento está dividido en dos secciones: ASP Clásico y ASP.NET.

ASP Clásico

Por defecto, si un sitio web que permite acceso anónimo, esta cuenta es llamada IUSR_NombreMáquina, donde NombreMáquina es el nombre del computador. Sin embargo, cuando usas un mecanismo de seguridad en IIS diferente a acceso Anónimo, puedes cambiar manualmente la cuenta que usa IIS, o puedes correr tu sitio web en modo "Out Of Process", o quizá usar la cuanta de otro usuario. La siguiente tabla lista las posibles cuentas de usuarios que IIS usa en diferentes escenarios:

Escenario: El Sitio Web / Directorio Virtual / Aplicación está configurada como Anonymous Access.
Cuenta usada: IUSR_NombreMáquina

Escenario: El Sitio Web / Directorio Virtual / Aplicación está configurado como Anonymous Access, y a la vez esta como "Out Of Process" (el campo Application Protection del IIS está seteada como High en el tab "Home Directory" o el tab de Virtual Directory de tu aplicación web)
Cuenta usada: IWAM_NombreMáquina

Escenario: El Sitio Web / Directorio Virtual / Aplicación está configurado como Basic Authentication o Integrated Windows Authentication.
Cuenta usada: La cuenta que usas para logearte en la aplicación web.

Escenario: El Sitio Web / Directorio Virtual / Aplicación está configurado como Anonymous Access, pero manualmente cambias la cuenta usada para usar anonymous access.
Cuenta usada: La cuenta que especificas.

Para encontrar como está configurado tu sistema, sigue estos pasos:

  • Ve al Administrative Tools -> Internet Information Services:

Figura 1: Internet Information Services del IIS 5.

  • Expande el lado izquierdo y verás Default Web Site. Si estás configurando otro Sitio Web / Directorio Virtual / Aplicación, selecciónalo en vez del por defecto. Este artículo asume que estás configurando Default Web Site.
  • Botón derecho sobre Default Web Site y escoge Properties.
  • Abre el tab Directory Security y haz clic en el botón Edit... en la sección Anonymous access y authentication control. Verás una pantalla similar a esta:

Figura 2: El diálogo Authentication Methods para un sitio dado en IIS 5.

  • Si está chequeado Anonymous access (como la pantalla de arriba), el nombre usuario que vez en el campo User name es la cuenta de IIS que se usa. Si no está chequeado Anonymous access y si lo está Basic y/o Integrated Windows authentication, la cuenta que estás usando para logearte al sitio web es usado por IIS. Nota que cuando está activo Anonymous access, no importa si está chequeado Basic o Integrated authentication; la cuenta usada por IIS sigue siendo la anonymous, IUSR_NombreMáquina o la cuenta.
  • Finalmente tienes que chequear si el sitio está corriendo Out of Process. Para hacer esto, cierra del diálogo Authentication Methods, y ve al tab Home Directory: 

Figura 3: El tab Home Directory IIS 5.

Figura 4 A: El tab Home Directory IIS 6.

Figura 4 B: IIS 5 Isolation mode en IIS 6. La cuenta de usuario que se asigna en este caso es la llamada ASPNET account.

  • Si la Application Protection está como Alto (High) (Aislada o Isolated) y estás usando Anonymous Access, la cuenta que está usando IIS es IWAM_NombreMáquina.
    Nota: Aislar una app significa que se configura para que corra como un proceso (espacio de memoria) que está separado del servidor web y de otras aplicaciones.
    En todos los restantes escenarios, IIS estará usando la cuenta determinada por los pasos anteriores.

ASP.NET

Para  ASP.NET, la cosa es un poco diferente. Por defecto, ASP.NET corre con una cuenta especial llamada ASPNET. Esta cuenta es la cuenta con "menos privilegios", lo que significa que está restringida a algunas pocas cosas que puede hacer en el sistema.

Para hacer un poco más confusas las cosas, en Windows Server 2003 que tiene IIS 6, un cuenta llamada Network Service (en los Windows en Español es Servicio de Red) es usada por defecto, en vez de la cuenta ASPNET. En Windows Server 2008 R2 que tiene IIS 7.5 es lo mismo, Network Service es la cuenta por defecto.

Nota: Todas las aplicaciones corren en un proceso.
En IIS 5 (y IIS 6 en modo de Isolation IIS 5), las aplicaciones web corren en el proceso llamado ASP.NET Worker Process (aspnet_wp.exe). Por defecto este proceso corre con la cuenta ASPNET.
En IIS 6 y superiores, las aplicaciones corren bajo el proceso llamado IIS Worker Process (w3wp.exe). Por defecto este proceso corre con la cuenta Network Service.

En IIS 6 había un grupo llamado IIS_WPG, el cual es un contenedor de todos las identidades de todos los applicacion pool.

Desde IIS 7 hacia arriba tenemos:

  • La cuenta IUSR reemplaza IUSR_NombreMáquina. No requiere password por ser del sistema.
  • El grupo IIS_IUSRS reemplaza al grupo IIS_WPG.

Así, si estás usando Anonymous Access o Basic / Integrated security, la cuenta siempre será ASPNET o la cuenta Network Service.

Para ver que tipo de acceso estás usando en IIS 7.5:



Figura 5: Modos de autenticación en IIS 7.5. Por defecto Autenticación Anónima está activa por defecto.

Figura 6: En IIS 6 hacia arriba, se puede configurar la identidad del AppPool. En IIS 7.5 por defecto es ApplicationPoolIdentity, en IIS 6/7 es NetworkService pero permite cambiarla a ApplicationPoolIdentity si deseas.

Figura 7: Seteando una identidad NetworkService

Figura 8: El grupo IIS_IUSRS (de IIS 7 hacia arriba) con las cuentas dinámicas APPPOOL/Sitio X.

Sin embargo, puedes cambiar esa cuenta modificando el web.config de la app. Para hacer esto, agrega <identity impersonate="true" /> en la sección <system.web>. Si agregas el elemento, IIS usará el usuario actual en vez de la cuenta ASPNET. Esto significa que con Anonymous Access activado, esta cuenta sería la cuenta anónima. Usualmente esta es la cuenta IUSR_MachineName, pero si usas ASP Clásico chequea IIS, el usuario seteado en User Name (Figura 2).

Si no estás usando Anonymous Access, pero si Basic o Integrated Security, la cuenta que se usa es aquella del usuario actual logeado. Puedes también explícitamente setear una cuenta dada con los atributos username y clave del elemento <identity>.

La siguiente tabla lista las diferentes posibilidades. La primera columna determina si se activa o no la impersonation en el archivo Web.Config. La segunda y tercera columna lista las opciones con y sin acceso Anonymous:

ASP.NET Impersonation: Desactivado
Acceso anónimo: cuenta ASPNET o Network Service
Acceso no anónimo (Basic, Integrated, otro): cuenta ASPNET o Network Service

ASP.NET Impersonation: Activada
Acceso anónimo: IUSR_NombreMáquina
Acceso no anónimo (Basic, Integrated, otro): usuario autenticado

ASP.NET Impersonation: Activada con una cuenta de usuario
Acceso anónimo: la cuenta dada
Acceso no anónimo (Basic, Integrated, otro): la cuenta dada

Resumen

La mayor parte del código ejecutado en una aplicación web se hace bajo un contexto de un IIS worker process y lo típico es que ese proceso corra con un identidad configurada en el application pool.
Por defecto, los AppPool están configurados para usar una cuenta interna, en IIS 7 es la cuenta Network Service, en IIS 7.5 es una cuenta virtual llamada ApplicationPoolIdentity que en verdad es una cuenta con un ID único, el nombre de la cuenta es IIS AppPool\host (ID único) por ejemplo: IIS APPPOOL\Misitio.cl (S-1-5-82-1545844221-6599888).
Cuando se inicia el worker process, en IIS 7 o superior, se hace automáticamente miembro del grupo IIS_IUSRS. En IIS 6 se hace miembro de IIS_WPG. IIS puede crear el grupo IIS_WPG por razones de retrocompatibilidad, en ese caso, IIS_IUSRS se hará miembro del grupo IIS_WPG.
Además, cierto código de la aplicación puede ejecutarse con la identidad del usuario autenticado asociado a cada request.

En resumen tenemos 2 contextos de identidad según lo que la aplicación necesita:

1. Identidad del AppPool: se usa cuando se accede a todos los archivos necesarios para la ejecución del worker process, cuando se accede al web.config, aplicaciones FASTCGI o ejecución de aplicaciones .Net.
Identidades involucradas (pueden ser las 3 a la vez): Primero una de estas 4: Network Service, ApplicacionPoolIdentity, LocalService o LocalSystem. Aparte está involucrada la cuenta de grupo IIS_IUSRS en IIS 7 o superior, IIS_WPG en IIS 6 y por último la cuenta Aplication Pool SID (IIS APPPOOLL\MiSitio.cl).

2. Usuario autenticado: Se usa para acceder a archivos estáticos, correr extensiones ISAPI o programas CGI, ejecutar aplicaciones FastCGI (si está activado impersonate), ejecutar aplicaciones .NET (si está activado impersonate).
Identidades asociadas (pueden ser 2): IUSR es por defecto cuando la autenticación es anónima en IIS 7, en IIS 6 es IUSR_NombreMáquina. Si no, es el usuario configurado en el Pool en Custom Account, alguna de las opciones de Application Pool Identity: Network Service, ApplicacionPoolIdentity, LocalService o LocalSystem. La segunda posible identidad asociada es el usuario autenticado si hay tokens en caso de que esté siendo usado Windows Authentication.

Permisos a carpetas


Vamos al asunto práctico de todo esto. Si debes darle permiso a una carpeta en particular (o archivo) ya que la aplicación te da error de permisos, ¿a qué cuenta de Windows darle?

Depende, si los archivos son vitales para la ejecución del worker process o aplicación web:

  • Si estás con IIS 5, dale a ASPNET.
  • Si estás con IIS 6, dale permisos a la cuenta Network Service, ApplicacionPoolIdentity (IIS APPPOOLL\MiSitio.cl), LocalService o LocalSystem (según como lo tengas configurado). Si IIS 6 está corriendo como IIS 5 Isolation mode, la cuenta a darle permisos sería ASPNET. Otra alternativa sería darle permiso al grupo de todos los pools, IIS_WPG, pero esto sería menos seguro.
  • Si estás con IIS 7 o superior, dale permisos Read o Full Control según el caso al grupo IIS_IUSRS del equipo local.

Ahora, si la carpeta es de archivos estáticos (imágenes, CSS/JS, carpeta con logs, base de datos MDB, etc.) y de uso de la aplicación:

  • Si estás con IIS 5, dale a IUSR_NombreMáquina si es acceso anónimo. Si es anónimo pero es out-of-process, dale a IWAM_NombreMáquina, sino es anónimo, dale a la cuenta dada.
  • Si estás con IIS 6, dale a la cuenta del Pool en particular, cuenta IUSR_NombreMáquina, en caso de autenticación anónima. Si no es anónimo, dale a Network Service, ApplicacionPoolIdentity (IIS APPPOOLL\MiSitio.cl), LocalService o LocalSystem (según como lo tengas configurado). Lo otro sería darle al grupo que tiene los usuarios del AppPool, IIS_WPG, pero esto sería menos seguro.
  • Si estás con IIS 7 o superior, dale permisos Read o Full Control según el caso al grupo IIS_IUSRS del equipo local.

Cuentas y grupos según IIS


  • ApplicationPoolIdentity: es una identidad, una cuenta virtual que puedes seleccionar en el AppPool del IIS. En IIS 7.5 es la que está por defecto. En IIS 6 y 7 por defecto la identidad es Network Service. ApplicationPoolIdentity crea una cuenta de usuario dinámico con un ID único. Por ejemplo si mi sitio web es MiSitio, la cuenta que se crea dinámicamente en el sistema es IIS APPPOOL / MiSitio. Accede a la red con esta misma cuenta. Esta cuenta permite darle permisos solo a este usuario que es de ese único AppPool y no a todos. Además, esta cuanta dinámica pasa a ser parte del Grupo IIS_IUSRS/IIS_WPG.
  • Network Service / Servicio de red: es la cuenta usada por IIS 6 en adelante que corre cuando el acceso es anónimo sin impersonation. Se creo con Windows Server 2003. Tiene muy pocos privilegios locales, incluso menos que LocalSystem y menos que la cuenta Administrador. Tiene acceso a la red. El worker process del AppPool corre con esta cuenta en IIS 6 y IIS 7 por defecto, pero la puedes cambiar.
  • LocalService: cuenta local del sistema, muy pocos privilegios, similar a cuenta Network Service pero sin acceso a la red.
  • LocalSystem: cuenta del sistema, es una cuenta local, pertenece al grupo de administradores, tiene acceso a todo el equipo. No tiene acceso a la red.

IIS 5


  • ASPNET: es una cuenta del sistema usada por IIS 5 para ejecutar aplicaciones .NET. Se crea cuando se instala .NET Framework.
  • Anonymous Access: es la autenticación por defecto. Usa la cuenta ASPNET que pertenece al grupo Guest. IIS no pedirá un nombre de usuario ni clave a algún request.
  • Basic Authentication: El cliente envía el nombre de usuario y contraseña en un string codificado como base64. Se recomienda que sólo se use en HTTPSya que no es muy seguro.
  • Digest Authentication: Hecho para reemplazar Basic Authentication, donde primero el servidor envía un string de datos random llamados nonce, luego el cliente envía el usuario, contraseña como hash hacia el servidor.
  • Integrated Windows Authentication (NTLM): El cliente envía usuario y contraseña como hash a través de la red. El navegador entiende que es información encriptada.

IIS 6


  • ASPNET: es una cuenta usada por IIS 6 pero sólo si está en IIS 5.0 isolation mode para ejecutar aplicaciones .NET.
  • IUSR_NombreMáquina: es la cuenta de usuario por defecto para el acceso anónimo a IIS.
  • IWAM_NombreMáquina: es la cuenta de usuario para ejecutar aplicaciones out-of-process en IIS 5.0 isolation mode.
  • IIS_WPG: cuenta de grupo con permisos y privilegios mínimos del usuario necesarias para crear y ejecutar un worker process en el servicio web.
  • Anonymous Authentication / Autenticación Anónima: es lo mismo que lo anterior pero se renombra así desde IIS 6 en adelante. Es la autenticación por defecto.

IIS 7


  • IUSR: en IIS 7 reemplaza al IUSR_NombreMáquina del IIS 6.
  • IIS_IUSRS: en IIS 7 reemplaza al grupo IIS_WPG del IIS 6.
  • Certificate Authentication: En esta versión de IIS, permite autentificar al cliente automáticamente al usar un certificado, es bastante seguro.

IIS 7.5 y superior


  • ApplicationPoolIdentity: es la identidad por defecto de los AppPool desde el IIS 7.5, antes era NetworkService.

Referencias



Traducido, comentado y completado con aspectos actuales del artículo: http://imar.spaanjaars.com/287/how-do-i-determine-the-security-account-that-iis-uses-to-run-my-web-site