2012-02-03 16 views
1

私のサーバーに公開されているASP.NET c#Webアプリケーションがあります。それは3ページで構成され、それぞれに3ページのログインのようなフォームがあります。 3番目のページのフォームが検証されると、ユーザーは別のサイトに送信されます。ここで少し図はので、私はそれをよりよく説明することができます:ボタンが「このページを表示できません」にリダイレクトされることがあります

NamePage ---> DateOfBirthPage ---> IDNumberPage ---> OtherSiteこれは、我々の開発・テストとストレスのすべてにおいて素晴らしい仕事をしている

テスト。ただし、IDNumberPageの[次へ]ボタンをクリックすると、「このページを表示できません」と表示され、「接続の問題を診断する」ボタンが表示されることがあります。これが1人のユーザーに対して発生すると、同じ問題がすべてのユーザーに発生します(一度発生すれば誰も完全に認証できません)。 NamePageとDateOfBirthPageは常に動作し、クラッシュが発生すると、IDNumberPageリンクは変更されず、OtherSiteにリダイレクトされた後ではなく、アプリケーションのこの側でクラッシュが発生していることが示唆されます。私はフレンドリーなHTTPエラーをオフにしていますが、ページにエラーを表示していません。サーバに入ってアプリケーションを再起動すると、再び動作します。

わかりやすい部分は、このエラーをどのように/なぜ発生しているのか見るために複製できないことです。

注目すべきいくつかの点:

  • 各ページには、MS SQL Serverデータベース
  • に1つのクエリを使用して各ページには4つのセッション変数テキストボックスフォームに入力されたものを含む(わずかなストリングスまで渡します前のページにある)
  • 最後の「次へ」ボタンをクリックするとセッションが中断されます。
  • リダイレクトする前にすべてのresultsets/connections /コマンドを閉じます。このすべてが非常にあいまいですが、問題自体は私たちから隠れの妙に良い仕事をしている場合
  • リダイレクトは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); 
} 
+0

コード/サイトを表示しなくても何かを示唆するのは本当に難しいです。テスト版へのリンクを送信する可能性はありますか? –

+0

すべてがイントラネットなのでリンクできませんが、一部のコードで編集します – rownage

+0

おそらくサイト名が正しくフォーマットされていない可能性があります。 – Aristos

答えて

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

すべてがクリーンアップされるまでリダイレクトされないことに注意してください。

SqlConnection,SqlCommandおよびSqlDataReaderはすべてIDisposableを実装しています。使用後に適切にクリーンアップする必要があります。そうしないと、リソースがハングアップしてしまいます。これを行う "最良の"方法は、using句でそれらを囲むことです。これにより、コードブロックが他のオブジェクトのようにガベージコレクトされないので、コードブロックが終了すると、それらが適切に削除されます。


また、上記のコードには優れた利点があります。つまり、エラーが発生した場合は、後でそれを消去します。投稿された元のコードは、DBサーバが応答しなかった場合や、クエリの実行中に何らかのタイプのエラーが発生した場合にはっきりとリークします。

dboCheck、lastname、およびmrnパラメータに含まれる値によっては、クエリがエラーになることがあります。たとえば、doBCheckフィールドに「BOB」が渡された場合、またはmrnにNothingが渡された場合... dobがデータベースのdatetimeフィールドである場合、クエリではリークした接続が発生するエラーがスローされます。十分な時間を過ごして、あなたのサイトはダウンしています。

これ以上のレビューでは、おそらく起こっていることを推測しています。人々は、あなたのアプリがこの時点までに取得できるデータが不足しているため、クエリが失敗しています。おそらく、これはあなたがテストケースで扱ったことではないでしょう。


サイドノート:はconcatentationを使用してSQL文を作成しないでください。それは完全なセキュリティではありません。少なくとも、これらのクエリをパラメータ化します。

+0

ここでは、問題を少し詳しく説明した良い記事です:http://www.alwaysgetbetter.com/blog/2008/02/15/sql-connections-in-aspnet-what-you-learned-is-wrong/ – NotMe

+0

私はガベージデータについてよく分かりません(このアプリケーションを使用する場所はタッチスクリーンですが、フィールドフィールドに必要なキーのみを表示するように画面キーボードを設計しました。 'using'ステートメントを使用します。私は今日まで後で展開することはできませんが、私はあなたの投稿を続けます。私は不思議です...リダイレクトは本当に 'using'ステートメントの外にある必要がありますか? – rownage

+0

@newage:リダイレクトで不明です。個人的には、2つのルールがあります。まず、使用節をできるだけ早く終了する必要があります。次に、リダイレクトが常に最後になるようなコードを作成します。あなたは確かに両方の方法を試みることができます。 – NotMe

0

良い答えクリス、1つの質問は、usingステートメントに欠落している.Close()ステートメントはありませんか。接続とデータレアの両方:

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

実際には、usingステートメント内に.close()を呼び出す必要はありません。コードブロックが終了すると、disposeメソッドが呼び出され、.close()メソッドが呼び出されます。 – NotMe

+0

素晴らしい、ありがとうクリス:) – CoderRoller

関連する問題