C# 为什么会话对象会抛出空引用异常?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/10536136/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-09 14:13:10  来源:igfitidea点击:

Why does session object throw a null reference exception?

c#asp.netsession

提问by NoviceToDotNet

on some of my aspx page I am checking session like this

在我的某些 aspx 页面上,我正在检查这样的会话

if (bool.Parse(Session["YourAssessment"].ToString()) == false
    && bool.Parse(Session["MyAssessment"].ToString()) == true)
{
    Response.Redirect("~/myAssessment.aspx");
}

It works fine if I keep playing with the pages frequently, but if I don't do anything with the page at least even for 5 min, running the page throws the error

如果我经常玩这些页面,它就可以正常工作,但是如果我至少在 5 分钟内没有对页面做任何事情,运行该页面会引发错误

Object reference not set to an instance of an object.

Following is the stack for this

以下是此堆栈

[NullReferenceException: Object reference not set to an instance of an object.]
   yourAssessment.Page_Load(Object sender, EventArgs e) in d:\Projects\NexLev\yourAssessment.aspx.cs:27
   System.Web.Util.CalliHelper.EventArgFunctionCaller(IntPtr fp, Object o, Object t, EventArgs e) +14
   System.Web.Util.CalliEventHandlerDelegateProxy.Callback(Object sender, EventArgs e) +35
   System.Web.UI.Control.OnLoad(EventArgs e) +91
   System.Web.UI.Control.LoadRecursive() +74
   System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +2207

Could some body explain me this weird behaviour?

有人可以向我解释这种奇怪的行为吗?

And as we know by default the session last for is 20 min.

正如我们所知,默认情况下,会话持续时间为 20 分钟。

EDITED

已编辑

See I have a page default aspx, it has got a button which fixes on the some basis where to redirect On default page it check like this

请参阅我有一个页面默认 aspx,它有一个按钮,该按钮在某些基础上修复了重定向的位置 在默认页面上,它像这样检查

protected void Page_Load(object sender, EventArgs e)
{
    if (!HttpContext.Current.Request.IsAuthenticated)
    {
        Response.Redirect("~/login.aspx");
    }
    else
    {
        Session["YourAssessment"] = false;
        Session["MyAssessment"] = false;
    }
}

on button click it has

在按钮上单击它有

protected void imgClientFreeEval_Click(object sender,
    System.Web.UI.ImageClickEventArgs e)
{
    if (HttpContext.Current.Request.IsAuthenticated)
    {
        string sqlQuery = "SELECT count(*) FROM SurveyClient WHERE UserID='"
            + cWebUtil.GetCurrentUserID().ToString() + "'";
        SqlParameter[] arrParams = new SqlParameter[0];
        int countSurvey = int.Parse(
            Data.GetSQLScalerVarQueryResults(sqlQuery).ToString());
        if (countSurvey > 0)
        {
            Session["YourAssessment"] = true;
            Session["MyAssessment"] = false;
        }
        Response.Redirect((countSurvey > 0)
            ? "~/yourAssessment.aspx"
            : "~/myAssessment.aspx");
    }
    else
    {
        Response.Redirect("~/login.aspx");
    }

and on myAssessment page it check like this

并在 myAssessment 页面上检查如下

protected void Page_Load(object sender, EventArgs e)
{
    if (!HttpContext.Current.Request.IsAuthenticated)
    {
        Response.Redirect("~/login.aspx");
    }
    else
    {
        if (Session["YourAssessment"] != null
            && Session["MyAssessment"] != null
            && bool.Parse(Session["YourAssessment"].ToString())
            && !bool.Parse(Session["myAssessment"].ToString()))
        {
            Response.Redirect("~/yourAssessment.aspx");
        }
    }
}

and on yourAssessmtn it check like this

并在 yourAssessmtn 上像这样检查

protected void Page_Load(object sender, EventArgs e)
{
    if (!HttpContext.Current.Request.IsAuthenticated)
    {
        Response.Redirect("~/login.aspx");
    }
    else
    {
        if (Session["YourAssessment"] != null
            && Session["MyAssessment"] != null
            && !bool.Parse(Session["YourAssessment"].ToString())
            && bool.Parse(Session["MyAssessment"].ToString()))
        {
            Response.Redirect("~/myAssessment.aspx");
        }

        PopulateAllSurveyByUser();
        if (ViewState["surveyClientID"] != null)
        {
            grdSurveyDetail.Visible = true;
            PopulateSurveyDetails(
                int.Parse(ViewState["surveyClientID"].ToString()));
        }
        else
        {
            grdSurveyDetail.Visible = false;
        }
    }
}

what's wrong please explain?

有什么问题请解释一下?

采纳答案by Shai

You first need to check whether that session variable exists

您首先需要检查该会话变量是否存在

if(Session["YourAssessment"] != null)
    // Do something with it
else
    // trying to call Session["YourAssessment"].ToString() here will FAIL.

That happens since your session has a lifecycle, which means - it expires (the cookie that defines it expires) - thus your objects vanish. you could increase sessionState timeoutin web.config for your sessions to last longer.

发生这种情况是因为您的会话具有生命周期,这意味着 - 它会过期(定义它的 cookie 会过期) - 因此您的对象会消失。您可以增加 sessionState timeoutweb.config 以使您的会话持续更长时间。

For example, in web.config

例如,在 web.config

  <system.web>
      <sessionState timeout="40" />
  </system.web>

Will make your sessions last for 40 minutes, as long as the client doesn't clear it, and the web server is up&running.

将使您的会话持续 40 分钟,只要客户端不清除它,并且 Web 服务器已启动并正在运行。

回答by Nikhil Agrawal

First you can use you code like this

首先你可以像这样使用你的代码

if (!bool.Parse(Session["YourAssessment"].ToString()) && 
     bool.Parse(Session["MyAssessment"].ToString()))
    Response.Redirect("~/myAssessment.aspx");

You sure you Sessions are not null

你确定你的 Sessions 不是 null

Check like this

像这样检查

if (Session["YourAssessment"] != null && Session["MyAssessment"] != null && 
    !bool.Parse(Session["YourAssessment"].ToString()) && 
     bool.Parse(Session["MyAssessment"].ToString()))
        Response.Redirect("~/myAssessment.aspx");

回答by bitoshi.n

If Sessionis not null, please recheck that it has key "YourAssessment"and "MyAssessment".

如果Session不为空,请重新检查它是否有 key"YourAssessment""MyAssessment"

回答by Hrvoje Hudo

Always check for null when accessing Session object!
You can write some small utility that can be used for that:

访问 Session 对象时始终检查 null!
您可以编写一些可用于此目的的小实用程序:

public class SessionData
{
    public static T Get<T>(string key)
    {
        object value = HttpContext.Current.Session[key];

        if(value == null)
            return default(T);

        try
        {
            return (T)value;
        }
        catch(Exception e)
        {
            return default(T);
        }
    }

    public static void Put(string key, object value)
    {
        HttpContext.Current.Session[key] = value;
    }
}

Session can be null if app pool is recycled. That can happen because numerous reasons...

如果应用程序池被回收,会话可以为空。发生这种情况的原因有很多……

One trick for keeping your server from loosing session is making "pings" to server from javascript. It can make requests to some dummy url (empty page, or if you're perf freak, to .ashx handler) every minute or so. It can be useful for pages that you keep open for long time, like huge edit forms.
Also, beware, there are different session timeout values for debug and release configuration!

防止服务器丢失会话的一个技巧是从 javascript 对服务器进行“ping”。它可以每分钟左右向一些虚拟 url(空页面,或者如果你是个怪胎,到 .ashx 处理程序)发出请求。它对于您长时间保持打开状态的页面非常有用,例如巨大的编辑表单。
另外,请注意,调试和发布配置有不同的会话超时值!

回答by DRobertE

When your Session expires the objects you have placed in your session such as Session["YourAssessment"] become null and the .toString() method call on those objects will then throw an Object reference error. To work around this you must first check to make sure your session variables being null before attempting to perform the toString().

当您的会话过期时,您放置在会话中的对象(例如 Session["YourAssessment"] 变为 null,然后对这些对象的 .toString() 方法调用将引发对象引用错误。要解决此问题,您必须在尝试执行 toString() 之前首先检查以确保您的会话变量为空。

    if(Session["YourAssessment"] != null){
if (bool.Parse(Session["YourAssessment"].ToString()) == false &&    bool.Parse(Session["MyAssessment"].ToString()) == true)
        {
            Response.Redirect("~/myAssessment.aspx");
        }
    }

回答by banging

Instead of the .ToString and Boolean.Parse do Convert.ToBoolean(Session["YourAssessment"])

而不是 .ToString 和 Boolean.Parse 做 Convert.ToBoolean(Session["YourAssessment"])

When I try Boolean b = Convert.ToBoolean(null)b = false ;)

当我尝试Boolean b = Convert.ToBoolean(null)b = false ;)

回答by Antonio Bakula

Well after all that have been written about this it seems that problem is IIS application restarting and if your session is stored inproc that can couse deletion of session variables. So try to log application end events and see if this is a case, put this in Global.asax.cs application_end event, this code would log application restart and why it happened :

好吧,毕竟已经写了这么多,似乎问题是 IIS 应用程序重新启动,如果您的会话存储在进程中,可能会导致会话变量的删除。因此,尝试记录应用程序结束事件并查看是否是这种情况,将其放在 Global.asax.cs application_end 事件中,此代码将记录应用程序重新启动及其发生的原因:

protected void Application_End(object sender, EventArgs e)
{
  HttpRuntime runtime = (HttpRuntime)typeof(System.Web.HttpRuntime).InvokeMember("_theRuntime", BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.GetField, null, null, null);

  string shutDownMessage = "";

  if (runtime != null)
  {
    shutDownMessage = Environment.NewLine + "Shutdown: " +
                      (string)runtime.GetType().InvokeMember("_shutDownMessage", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.GetField, null, runtime, null) + 
                      Environment.NewLine + "Stack: " + Environment.NewLine +
                      (string)runtime.GetType().InvokeMember("_shutDownStack", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.GetField, null, runtime, null);
  }

  string logFile =  HttpContext.Current.Server.MapPath(~/AppEndLog.log");
  string logMsg = "";
  if (File.Exists(logFile))
    logMsg = logMsg + File.ReadAllText(logFile) + Environment.NewLine + Environment.NewLine;
  logMsg = logMsg + Environment.NewLine + "ApplicationEnd - " + DateTime.Now.ToString() + shutDownMessage;
  File.WriteAllText(logFile, logMsg);


}