Menú de navegaciónMenú
Categorías

La mejor forma de Aprender Programación online y en español www.campusmvp.es

?id=6d90bf3f-1e98-4810-b3c6-8dd69e4326ed

El nombre "Session" no existe en el contexto actual

asp-net-mvc

En los foros de programación con frecuencia encontramos preguntas parecidas a esta: "Al compilar mi aplicación ASP.NET, me da un error al acceder al Session quejándose de que no existe en el contexto actual. ¿A qué puede ser debido?"
Típicamente, cuando usamos la palabra clave Session en uno de nuestros formularios web, en realidad estamos accediendo a la propiedad Session heredada de System.Web.UI.Page. Y si se trata de una aplicación MVC, la propiedad Session se hereda de System.Web.Mvc. Controller.

     public partial class Default : System.Web.UI.Page 
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            Session["Prueba"] = "algo";
            //...
        }
    }

Si en Visual Studio pulsamos F12 sobre la palabra Session para ir a su definición, veremos que nos lleva al código fuente generado a partir de los metadatos de System.Web.UI.Page, donde podemos comprobar que, efectivamente, se trata de una propiedad de dicha clase:

 namespace System.Web.UI
{
    //...
    public class Page : TemplateControl, IHttpHandler
    {
        //...
        public virtual HttpSessionState Session { get; }
        //...
    }
}

El hecho de que Session sea una propiedad de la clase en la que estamos escribiendo nuestro código implica que no se reconocerá si intentamos escribirlo fuera de dicha clase. Esto puede ocurrir si lo escribimos dentro de otra clase anidada dentro de la propia clase generada para el code-behind de nuestra página, pero es más típico que suceda cuando desde el code-behind llamamos a alguna clase externa, que podría (por ejemplo) ser una clase auxiliar que contiene funciones para ser invocadas desde distintos puntos de nuestro programa.

     public class Herramientas
    {
        public void GuardarDatos()
        {
            Session["Prueba"] = "algo"; //<-- Error aquí
        }
    }

Una solución en estos casos consiste en acceder directamente al HttpSessionState mediante el contexto de HTTP, que podemos hacer accesible desde una clase cualquiera mediante el truco que se describe a continuación.

En primer lugar, nos fijaremos en el proyecto en el que se ha compilado la clase que contiene la llamada al Session (que en nuestro ejemplo anterior se llamaba Herramientas). Si forma parte del propio proyecto web, no hay que hacer nada, pero si se ha compilado por separado en una librería de clases, es necesario añadir una Referencia a System.Web.dll en el proyecto.

Referencia-SystemWebdll

 

A continuación, en nuestra clase, importaremos el espacio de nombres System.Web y ya estaremos en condiciones de acceder a HttpContext.Current.Session:

 using System;
using System.Web;

namespace MiLibreria
{
    public class Herramientas
    {
        public void GuardarDatos()
        {
            HttpContext.Current.Session["Prueba"] = "algo"; //<-- Ahora funciona
        }
    }
}

Nótese que si llamásemos a esa librería desde una aplicación que no fuese de ASP.NET (por ejemplo, una aplicación de tipo WinForms), el valor de HttpContext.Current sería null, cosa que deberíamos comprobar y tratar adecuadamente dentro de nuestra rutina.

¿Qué otras aplicaciones tiene este “truco”? Una vez que lo conocemos, a través de HttpContext.Current podemos acceder a muchas otras propiedades que normalmente sólo estarían disponibles dentro del code-behind de la página. Por ejemplo: Request, Response, Server, Profile, Cache, User, Trace, ...

De esta manera, podemos acceder a datos de ASP.NET desde una clase auxiliar, sin necesidad de pasarnos como argumento estos datos desde la página. Por ejemplo, HttpContext.Current.Request.QuesryString nos daría acceso al QueryString desde una clase cualquiera. También podríamos guardar datos en caché llamando a HttpContext.Current.Cache[“...”]. O podríamos depurar el funcionamiento en producción de una de nuestras librerías de clases escribiendo en las trazas: HttpContext.Current.Trace.Warn(“...”).
Finalmente, otro truco sirve para recuperar el Page: Basta preguntar por la propiedad Handler (que es del tipo IHttpHandler) y hacerle un “cast” al tipo Page (que implementa IHttpHandler). Esto nos permite usar el valor recuperado en cualquier lugar en el que usaríamos la propiedad Page en el code-behind, por ejemplo, para llamar a Page.ClientScript:

System.Web.UI.Page page = (System.Web.UI.Page) HttpContext.Current.Handler;
page.ClientScript.RegisterClientScriptBlock(...);

Desde luego, si llamásemos a esta función desde una ubicación de código que no pertenezca a un Page (por ejemplo, desde un .ashx), nos daría un error de “invalid cast exception”, por lo que hay que asegurarse de que esta funcionalidad sólo es invocada desde el llamante correcto antes de usarla indiscriminadamente en cualquiera de nuestras clases.

Fecha de publicación:
Alberto Población Alberto es MVP de C#, y lleva varias décadas desarrollando software. Cuenta entre otras con las certificaciones MCSE, MCDBA, MCITP, MCSD, MCPD. En la actualidad trabaja como consultor independiente dedicándose también a la formación. Es instructor certificado por Microsoft. Ver todos los posts de Alberto Población
Archivado en: Desarrollo Web

¿Te ha gustado este post?
Pues espera a ver nuestra newsletter...

Suscríbete a la newsletter

La mejor formación online para desarrolladores como tú

Agregar comentario

Los datos anteriores se utilizarán exclusivamente para permitirte hacer el comentario y, si lo seleccionas, notificarte de nuevos comentarios en este artículo, pero no se procesarán ni se utilizarán para ningún otro propósito. Lee nuestra política de privacidad.