按钮有时会重定向到“此页面无法显示”

时间:2012-02-03 20:49:56

标签: c# asp.net sql-server session response.redirect

我将ASP.NET c#web应用程序发布到我们的服务器上。它由三个页面组成,每个页面都有一个表单,有点像3页登录。验证第三页的表单后,它会将用户发送到其他站点。这是一个小图,所以我可以更好地解释它:

NamePage ---> DateOfBirthPage ---> IDNumberPage ---> 其他网站

这在我们所有的开发测试和压力测试中都很有效。但是,在我们投入生产之后,有时当单击IDNumberPage上的“下一步”按钮时,用户会看到“此页面无法显示”,并显示“诊断连接问题”按钮。当一个用户发生这种情况时,所有用户都会出现同样的问题(这意味着一旦发生这种情况,没有人可以完全进行身份验证) NamePage和DateOfBirthPage始终有效,当崩溃发生时,IDNumberPage链接不会更改,这表明崩溃发生在应用程序的这一侧,而不是在重定向到OtherSite之后。我关闭了友好的HTTP错误,但它没有在页面上显示任何错误。如果我们进入服务器并重新启动应用程序,它将再次运行。

令人沮丧的是,我们无法复制此错误,看看它是如何/为何发生。

有些值得注意的事情:

  • 每个页面在MS SQL服务器数据库上使用一个查询
  • 每个页面最多传递4个会话变量(只包含在前一页上输入文本框表单中的内容的小字符串)
  • 点击最后​​一个“下一个”按钮时,会话将被放弃。
  • 重定向前,所有结果集/连接/命令都将关闭。
  • 重定向使用Response.Redirect(siteName, false)
  • 使用重载版本

很抱歉,如果所有这一切都非常模糊,但问题本身在躲避我们方面做得非常好。我们已经尝试用测试请求锤击服务器(许多一次,许多一段时间内等)以及登录/试图打破页面的不同组合,但无济于事。任何人都可以建议尝试诊断/修复/复制此问题吗?

编辑:导致问题的IDNumberPage代码隐藏的点击功能:

{ SqlConnection dbconn = new SqlConnection(Application["dbconn"].ToString());
                SqlCommand sqlValidate = dbconn.CreateCommand();
                dbconn.Open();
                sqlValidate.CommandText = "SELECT lastName, csn FROM Demographics WHERE lastName = '" + Session["lastName"].ToString() + "' " +
                    "AND dob = '" + Session["dobCheck"].ToString() + "' AND mrn = " + strMRN;
                SqlDataReader results = sqlValidate.ExecuteReader();
                if (results.HasRows)
                {
                    string csn = "";
                    while (results.Read())
                    {
                        if (!String.IsNullOrEmpty(results["csn"].ToString()))
                        {
                            csn = results["csn"].ToString();
                            break;
                        }
                    }
                    string url = Application["surveyUrlString"] + "&lastname=" + Session["lastName"].ToString() + "&mrn=" + strMRN + "&dobday=" + Session["dobday"].ToString() 
                                + "&dobmonth=" + Session["dobmonth"].ToString() + "&dobyear=" + Session["dobyear"].ToString() + "&csn=" + csn;
                    results.Close();
                    dbconn.Close(); 
                    Response.Redirect(url, false);
}

2 个答案:

答案 0 :(得分:5)

问题是由于sql连接泄漏造成的。

您没有妥善处理资源。随着时间的推移,这些将在连接池中堆叠,直到您到达池溢出且应用程序死亡的点。重置显然会解决问题。

此问题可能可能未显示在“压力”测试中,具体取决于您是否正在测试应用程序。

解决方案是重新格式化该代码以更好地处理数据库调用。

{ 
    string url = string.empty;

    using (SqlConnection dbconn = new SqlConnection(Application["dbconn"].ToString())) {
        using (SqlCommand sqlValidate = dbconn.CreateCommand()) {
            dbconn.Open();
            sqlValidate.CommandText = "SELECT lastName, csn FROM Demographics WHERE lastName = '" + Session["lastName"].ToString() + "' " +
                "AND dob = '" + Session["dobCheck"].ToString() + "' AND mrn = " + strMRN;
            using (SqlDataReader results = sqlValidate.ExecuteReader()) {
                if (results.HasRows) {
                    string csn = "";
                    while (results.Read())
                    {
                        if (!String.IsNullOrEmpty(results["csn"].ToString()))
                        {
                            csn = results["csn"].ToString();
                            break;
                        }
                    }
                    url = Application["surveyUrlString"] + "&lastname=" + Session["lastName"].ToString() + "&mrn=" + strMRN + "&dobday=" + Session["dobday"].ToString() 
                            + "&dobmonth=" + Session["dobmonth"].ToString() + "&dobyear=" + Session["dobyear"].ToString() + "&csn=" + csn;
                }
            } // sqldatareader
        } // using sqlcommand
    } // using sqlconnection
    if (!String.IsNullOrEmpty(url)) {
        Response.Redirect(url, false);
    }
}

请注意,在清理完所有内容之前,您不会重定向。

SqlConnectionSqlCommandSqlDataReader都实施IDisposable。您必须在使用后正确清理,否则资源将被搁置。执行此操作的“最佳”方法是将它们包装在using子句中。这样可以确保在退出代码块后正确删除它们,因为它们不会像其他对象一样被垃圾收集。


另请注意,上述代码具有良好的附带好处。也就是说,如果出现错误,STILL会在您之后清理。鉴于在运行查询时数据库服务器没有响应或抛出某种类型的错误,发布的原始代码会明显泄漏。

查询可能会出错,具体取决于dboCheck,lastname和mrn参数中包含的值。例如,如果为dobCheck字段传入了“BOB”,或者为mrn传递了Nothing,那么该怎么办?如果dob是数据库中的datetime字段,那么查询将抛出一个错误,导致泄漏的连接。做足够的时间,你的网站已关闭。

经过进一步审核,我猜测可能正在发生的事情:人们正在投入垃圾数据,您的应用程序允许达到这一点并且查询失败。很可能这不是您在测试用例中处理的内容。


附注:不要使用concatentation创建sql语句。这是一个完全的安全,不,不。至少,参数化这些查询。

答案 1 :(得分:0)

很好的答案Chris,一个问题不是Using语句中缺少的.Close()语句吗?连接和datareader都是:

         results.Close();
        } // using sqldatareader
       } // using sqlcommand
      dbconn.Close();
     } // using sqlconnection