6

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

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

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

Object reference not set to an instance of an object.

以下是这个的堆栈

[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

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

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

已编辑

看到我有一个页面默认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;
    }
}

在按钮点击它有

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");
    }

在 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");
        }
    }
}

并在 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;
        }
    }
}

有什么问题请解释一下?

4

7 回答 7

11

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

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

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

例如,在 web.config

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

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

于 2012-05-10T14:28:55.773 回答
3

访问 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;
    }
}

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

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

于 2012-05-10T14:40:44.877 回答
1

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

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

你确定你的会话不是null

像这样检查

if (Session["YourAssessment"] != null && Session["MyAssessment"] != null && 
    !bool.Parse(Session["YourAssessment"].ToString()) && 
     bool.Parse(Session["MyAssessment"].ToString()))
        Response.Redirect("~/myAssessment.aspx");
于 2012-05-10T14:27:32.327 回答
1

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

于 2012-05-10T14:30:16.147 回答
1

当您的 Session 过期时,您放置在会话中的对象(例如 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");
        }
    }
于 2012-05-10T14:45:24.970 回答
1

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

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

于 2012-05-10T14:54:14.427 回答
1

好吧,在所有关于此的文章之后,问题似乎是 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);


}
于 2012-05-11T11:03:21.760 回答