在C#中确定会话变量是否为空的最佳方法是什么?

80
什么是在ASP.NET C#中检查会话变量是否存在的最佳方法?
我喜欢使用String.IsNullOrEmpty() 来检查字符串,想知道是否有类似于Session的方法。目前我所知道的唯一方法是:
 var session;
 if (Session["variable"] != null)
 {
     session = Session["variable"].ToString();
 }
 else
 {
     session = "set this";
     Session["variable"] = session;
 }
12个回答

115

继续其他人所说的,我倾向于有两个层次:

核心层。这在几乎所有web应用程序项目中都添加了一个DLL。在这里,我有一个SessionVars类,它为Session状态的获取器/设置器做了大量的工作。它包含以下代码:

public class SessionVar
{
    static HttpSessionState Session
    {
        get
        {
            if (HttpContext.Current == null)
                throw new ApplicationException("No Http Context, No Session to Get!");

            return HttpContext.Current.Session;
        }
    }

    public static T Get<T>(string key)
    {
        if (Session[key] == null)
            return default(T);
        else
            return (T)Session[key];
    }

    public static void Set<T>(string key, T value)
    {
        Session[key] = value;
    }
}

注意泛型可以获取任何类型。

我还为特定类型添加了Getter / Setter,尤其是字符串类型,因为我通常更喜欢使用string.Empty而不是null来表示向用户呈现的变量。

例如:

public static string GetString(string key)
{
    string s = Get<string>(key);
    return s == null ? string.Empty : s;
}

public static void SetString(string key, string value)
{
    Set<string>(key, value);
}

于是我创建了包装器来将其抽象化并提升到应用程序模型。例如,如果我们有客户详细信息:

public class CustomerInfo
{
    public string Name
    {
        get
        {
            return SessionVar.GetString("CustomerInfo_Name");
        }
        set
        {
            SessionVar.SetString("CustomerInfo_Name", value);
        }
    }
}

你明白我的意思了吧? :)
注意:当使用状态服务器时,在将对象存储在Session中时,始终确保这些对象是可序列化的。在Web Farm上使用泛型尝试保存对象时可能会出现问题。我在工作中部署在Web Farm上,因此在核心层中添加了代码检查对象是否可序列化,这也是封装Session Getter和Setter的另一个好处 :)

很棒的方法!我已经使用类似的方法很长时间了,但是没有加入泛型。这避免了许多不同开发人员创建相似会话变量的问题。 - DOK
如果执行“throw new ApplicationException("No Http Context, No Session to Get!");”语句时出现异常,我该怎么处理?我对自动实现属性感到困惑,我在代码的哪个部分可以捕获异常发生的位置。 - Marztres
不错的方法。我在C#类库中实现时遇到了问题。我无法解决对HttpSessionState/HttpContext的引用。您是否需要在DLL中安装MVC库以导入正确的命名空间? - seebiscuit

20

这就是基本操作了。不过,你可以使用更短的语法。

sSession = (string)Session["variable"] ?? "set this";

这句话的意思是,如果会话变量为null,则将sSession设置为"set this"。


1
你不能这样做... Session["variable"] 是一个对象,编译器会将其转换为字符串,因为 sSession 是一个字符串。如果 Session["variable"] 不存在,它会抛出一个异常! - balexandre
你是绝对正确的。如果Session不为空,我更新了代码以将字符串转换。 - Ely

14

将其包装在属性中可能使事情更加优雅。

string MySessionVar
{
   get{
      return Session["MySessionVar"] ?? String.Empty;
   }
   set{
      Session["MySessionVar"] = value;
   }
}

那么您可以将其视为字符串。

if( String.IsNullOrEmpty( MySessionVar ) )
{
   // do something
}

这是我的做法,可以更轻松地访问应用程序中的会话变量。我倾向于为数据创建类,并使用静态属性来执行所有空值检查工作。 - Rob Cooper
如果您在Session中存储的是一个对象而不仅仅是一个字符串,该怎么办? - Aaron Palmer
1
请看我的回答,使用泛型可以在存储其他对象时实现类型安全。 - Rob Cooper
对不起,请问 'Session(“”)' 部分正确吗?我一直在收到错误。 - Jesus Zamora
会用VB来完成。:) 将被改为方括号。 - oglester

8
在C# 3.0中,“as”符号非常简洁。由于所有的会话变量都是可空对象,因此可以将其值获取并放入您自己的类型化变量中,而不必担心抛出异常。大多数对象都可以通过这种方式处理。
string mySessionVar = Session["mySessionVar"] as string;

我的建议是将Session变量提取到本地变量中,然后进行适当处理。始终假设您的Session变量可能为null,不要将它们转换为非可空类型。

如果您需要非可空类型的变量,则可以使用TryParse来获取它。

int mySessionInt;
if (!int.TryParse(mySessionVar, out mySessionInt)){
   // handle the case where your session variable did not parse into the expected type 
   // e.g. mySessionInt = 0;
}

2

在我看来,最简单清晰易读的方法是:

 String sVar = (string)(Session["SessionVariable"] ?? "Default Value");

这可能不是最有效的方法,因为即使在默认情况下(将字符串转换为字符串),它也会将默认字符串值转换为字符串,但如果您将其作为标准编码实践,您会发现它适用于所有数据类型,并且易于阅读。

例如(一个完全虚假的例子,但它显示了重点):

 DateTime sDateVar = (datetime)(Session["DateValue"] ?? "2010-01-01");
 Int NextYear = sDateVar.Year + 1;
 String Message = "The Procrastinators Club will open it's doors Jan. 1st, " +
                  (string)(Session["OpeningDate"] ?? NextYear);

我喜欢泛型选项,但除非您希望在许多地方使用它,否则似乎过度。可以修改扩展方法以特定方式扩展Session对象,以便它具有“安全”获取选项,例如Session.StringIfNull(“SessionVar”)和Session [“SessionVar”] =“myval”; 它破坏了通过Session [“SessionVar”]访问变量的简单性,但这是干净的代码,并且仍允许在需要时验证null或string。


2

这种方法还不假设Session变量中的对象是字符串。

if((Session["MySessionVariable"] ?? "").ToString() != "")
    //More code for the Code God

所以基本上在将null变量转换为字符串之前,会将其替换为一个空字符串,因为ToStringObject类的一部分。


1

通过这种方式可以检查是否存在这样的键。

if (Session.Dictionary.ContainsKey("Sessionkey"))  --> return Bool

1

检查是否为null是正确的做法。

处理对象类型不是正确的方法。声明严格的类型并尝试将对象强制转换为正确的类型。(并使用强制转换提示或Convert)

 private const string SESSION_VAR = "myString";
 string sSession;
 if (Session[SESSION_VAR] != null)
 {
     sSession = (string)Session[SESSION_VAR];
 }
 else
 {
     sSession = "set this";
     Session[SESSION_VAR] = sSession;
 }

对于任何语法错误,我是一个日常 VB 程序员而已,抱歉。


1
通常我会使用强类型属性为会话中的项目创建SessionProxy。访问这些属性的代码会检查空值并将其转换为正确的类型。好处是所有与会话相关的项目都保存在一个地方,不必担心在代码的不同部分使用不同的键(并想知道为什么它不起作用)。通过依赖注入和模拟,我可以使用单元测试完全测试它。它遵循DRY原则,并允许我定义合理的默认值。
public class SessionProxy
{
    private HttpSessionState session; // use dependency injection for testability
    public SessionProxy( HttpSessionState session )
    {
       this.session = session;  //might need to throw an exception here if session is null
    }

    public DateTime LastUpdate
    {
       get { return this.session["LastUpdate"] != null
                         ? (DateTime)this.session["LastUpdate"] 
                         : DateTime.MinValue; }
       set { this.session["LastUpdate"] = value; }
    }

    public string UserLastName
    {
       get { return (string)this.session["UserLastName"]; }
       set { this.session["UserLastName"] = value; }
    }
}

1

我也喜欢用属性来封装会话变量。这里的设置器很简单,但我喜欢编写获取方法,使它们只有一个出口点。为了做到这一点,我通常会在返回会话变量值之前检查其是否为空,并将其设置为默认值。

就像这样:

string Name
{
   get 
   {
       if(Session["Name"] == Null)
           Session["Name"] = "Default value";
       return (string)Session["Name"];
   }
   set { Session["Name"] = value; }
}

}


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接