c# - 按钮有时会重定向到 "This page cannot be displayed"

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

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

NamePage ---> DateOfBirthPage ---> IDNumberPage ---> OtherSite

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

令人沮丧的是,我们无法复制此错误以了解它是如何发生的/为什么会发生。

一些值得注意的事情:

  • 每个页面在 MS SQL 服务器数据库上使用一个查询
  • 每个页面最多传递 4 个 Session 变量(仅包含在上一页文本框表单中输入的内容的小字符串)
  • 单击最后一个“下一步”按钮时, session 将被放弃。
  • 在重定向之前关闭所有结果集/连接/命令。
  • 重定向使用重载版本 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);
}

最佳答案

问题是由于 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 子句中。这确保它们在代码块退出后被正确删除,因为它们不像其他对象那样被垃圾回收。


另请注意,上面的代码还有一个很好的附带好处。也就是说,如果出现错误,它仍然会在您之后进行清理。而如果数据库服务器在运行查询时没有响应或抛出某种类型的错误,则发布的原始代码显然会泄漏。

查询可能会出错,具体取决于 dboCheck、lastname 和 mrn 参数中包含的值。例如,如果为 dobCheck 字段传递了“BOB”,或者没有为 mrn 传递任何内容……如果 dob 是数据库中的日期时间字段,那么查询将抛出一个错误,导致连接泄漏。这样做的次数足够多,您的网站就会关闭。

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


旁注:不要使用连接创建 sql 语句。那是一个完整的安全性,不,不。至少,参数化这些查询。

关于c# - 按钮有时会重定向到 "This page cannot be displayed",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9135288/

相关文章:

c# - 确定在 C# 中定义函数的位置?

asp.net - 构建动态 LINQ 查询的最佳方式

javascript - 突出显示当前页面菜单项。当选择子菜单项时也突出显示主菜单项

asp.net - 登录期间使用sql server验证asp.net中区分大小写的密码

sql - Entity Framework 和 CROSS/OUTER APPLY

c# - c#问题中的正则表达式

c# - 一旦 frame 导航到另一个 Page 就销毁 ViewModel 和 Page 的实例

c# - 如何在迭代器中使用 Html.DisplayFor?

c# - 如何在 ASP.NET Core 中的 DbSet 实例上使用 Find(params object[] keyValues) 方法?

sql-server - Hibernate4,Grails 2.5-缓存的数据在两次重启之间仍然存在吗?