トップ回答者
ProviderExceptionで例外発生

質問
-
方法:サンプルメンバーシップを実装する を参考にして
プログラムを書きました。
イベントログが書かれるかテストしています。
コネクションの文字列を変えてみたとこと
Throw New ProviderException(exceptionMessage)
の次でエラーになってしまいました。
ユーザーコードによってハンドルされませんでした。
と表示されています。
Finallyでは拾ってもらえないのでしょうか?
サンプルソースにもthrowしたものを拾っている箇所が見当たりません。
どんな仕組みが想定されているのでしょうか?
よろしくお願いします。
Try
conn.Open()Catch ex As SqlException
If WriteExceptionsToEventLog Then
WriteToEventLog(ex, "ValidateUser")
Throw New ProviderException(exceptionMessage)
Else
Throw ex
End If
Finally
If Not reader Is Nothing Then
reader.Close()
End If
conn.Close()
End Try
回答
-
単にスローした例外を補足するコードが書かれていないだけでしょう。
これはFinallyではダメということでしょうか?
Throw New ProviderException(exceptionMessage)
の後
Else
で落ちてしまいます。
サンプルは Throw New ProviderException(exceptionMessage) の後
Elseの中に入って Throw を実行して イベントが終わるようになっているのでしょうか?
Finally句を記述しても例外を補足したことにはなりません。サンプルのソースがどうなっているのかはわかりませんが、往々にしてサンプルコードは例外処理等の冗長な処理は省かれて記述されることが多いと思います。
.NETの例外処理については、こちらが参考になります。
.NETの例外処理 Part.1 - とあるコンサルタントのつぶやき - Site Home - MSDN Blogs
.NETの例外処理 Part.2 - とあるコンサルタントのつぶやき - Site Home - MSDN Blogs
.NETの例外処理 Part. 3 - とあるコンサルタントのつぶやき - Site Home - MSDN Blogs
.NET の例外処理 Part. 4 - とあるコンサルタントのつぶやき - Site Home - MSDN Blogs
Blog:プログラマーな日々 http://d.hatena.ne.jp/JHashimoto/- 回答としてマーク 絶対初心者 2011年3月11日 4:31
-
ProviderExceptionをcatchするのは
呼び出し元関数のログイン関数の部分をtry catchにするということでしょうか。例外をスローする関数を利用する部分、あるいはそれをさらに利用する部分など、適切な場所で try-catch を書いて、例外が発生したときにどうするかを記述することでしょう。
普通に使っていて起きる例外は try-catch で処理し、あり得ない例外は素直に Application_Error でロギングするぐらいでしょうか。ところで、ProviderException とやらは発生して良い例外なんですか?普通に起きるものなんですか?
それが妥当なのかは、第三者には判断不可能なので、自分で判断してください。Global.asaxとweb.configにコードを追加しましたが例外を拾ってくれません。
設定が足りないのでしょうか。この手の 最終手段 はデバッガーで例外を検知するタイミングよりも後の処理になります。(つまり、デバッガーで実行しているとみることのできない画面となる)
デバッガーなしで実行した場合に表示されるのはこのためだと予想します。あくまで 最終手段 であって、通常起きうる例外は適切な処理(エラーの内容をわかりやすくユーザーに伝える、代替処理を実行するなど)を実装するべきです。
質問スレッドで解決した場合は、解決の参考になった投稿に対して「回答としてマーク」のボタンを押すことで、同じ問題に遭遇した別のユーザが役立つ投稿を見つけやすくなります。- 回答としてマーク 絶対初心者 2011年3月11日 4:31
すべての返信
-
Finallyでは拾ってもらえないのでしょうか?
Finally句は例外発生時にも必ず実行されます。単にスローした例外を補足するコードが書かれていないだけでしょう。
サンプルソースにもthrowしたものを拾っている箇所が見当たりません。
どんな仕組みが想定されているのでしょうか?
よろしくお願いします。
集約例外ハンドラという機構があります。こちらが参考になると思います。
本題からは逸れますが、「Throw ex」と書くとそれを書いた箇所が例外の基点となってしまい、本来の例外発生箇所を示すスタックトレースが失われ、障害調査が困難になります。なので単に「Throw」と書くのが定石です。
FxCopではちゃんとエラーとして検出してくれます。
【C#プログラミングレッスン】 No.226-FxCopに学ぶ(8): CA2200 [C#プログラミングレッスン] - メルマ!
Blog:プログラマーな日々 http://d.hatena.ne.jp/JHashimoto/ -
単にスローした例外を補足するコードが書かれていないだけでしょう。
これはFinallyではダメということでしょうか?
Throw New ProviderException(exceptionMessage)
の後
Else
で落ちてしまいます。
System.Configuration.Provider.ProviderException はユーザー コードによってハンドルされませんでした。
Message=An exception occurred. Please check the Event Log.
Source=App_Code.xpw2ruer
StackTrace:
場所 CustomMembershipProvider.ValidateUser(String username, String password) 場所 D:\WebSite2\App_Code\CustomMembershipProvider.vb:行 271
場所 System.Web.Security.Membership.ValidateUser(String username, String password)
場所 LoginAuth.Login1_Authenticate(Object sender, AuthenticateEventArgs e) 場所 D:\WebSite2\LoginAuth.aspx.vb:行 9
場所 System.Web.UI.WebControls.Login.OnAuthenticate(AuthenticateEventArgs e)
場所 System.Web.UI.WebControls.Login.AttemptLogin()
場所 System.Web.UI.WebControls.Login.OnBubbleEvent(Object source, EventArgs e)
場所 System.Web.UI.Control.RaiseBubbleEvent(Object source, EventArgs args)
場所 System.Web.UI.WebControls.Button.OnCommand(CommandEventArgs e)
場所 System.Web.UI.WebControls.Button.RaisePostBackEvent(String eventArgument)
場所 System.Web.UI.WebControls.Button.System.Web.UI.IPostBackEventHandler.RaisePostBackEvent(String eventArgument)
場所 System.Web.UI.Page.RaisePostBackEvent(IPostBackEventHandler sourceControl, String eventArgument)
場所 System.Web.UI.Page.RaisePostBackEvent(NameValueCollection postData)
場所 System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)
InnerException:
サンプルは Throw New ProviderException(exceptionMessage) の後
Elseの中に入って Throw を実行して イベントが終わるようになっているのでしょうか?
「Throw ex」については勉強になりました。
ありがとうございます。
-
単にスローした例外を補足するコードが書かれていないだけでしょう。
これはFinallyではダメということでしょうか?
Throw New ProviderException(exceptionMessage)
の後
Else
で落ちてしまいます。
サンプルは Throw New ProviderException(exceptionMessage) の後
Elseの中に入って Throw を実行して イベントが終わるようになっているのでしょうか?
Finally句を記述しても例外を補足したことにはなりません。サンプルのソースがどうなっているのかはわかりませんが、往々にしてサンプルコードは例外処理等の冗長な処理は省かれて記述されることが多いと思います。
.NETの例外処理については、こちらが参考になります。
.NETの例外処理 Part.1 - とあるコンサルタントのつぶやき - Site Home - MSDN Blogs
.NETの例外処理 Part.2 - とあるコンサルタントのつぶやき - Site Home - MSDN Blogs
.NETの例外処理 Part. 3 - とあるコンサルタントのつぶやき - Site Home - MSDN Blogs
.NET の例外処理 Part. 4 - とあるコンサルタントのつぶやき - Site Home - MSDN Blogs
Blog:プログラマーな日々 http://d.hatena.ne.jp/JHashimoto/- 回答としてマーク 絶対初心者 2011年3月11日 4:31
-
Throw New ProviderException(exceptionMessage)
の後
Else
で落ちてしまいます。認識に少し誤りがあるようです。
このコードでは、ProviderException という例外をスローしているが、例外を処理するコードを書いていないので、ハンドルされていない例外としてデバッガー(Visual Studio)が検知して、処理を止めています。
実行位置は Else に見えるかもしれませんが、あくまで Throw の行を実行した直後の位置が表示されているだけであって、デバッグが止まったのは Throw で投げた(スローした)例外が処理されていないことが原因です。このコードを利用する人は、利用する側のメソッドやプロパティで ProviderException を Catch してあげなければなりません。
サンプルコードは部分的に掲載されていることが多いので、そういった Catch の部分が書かれていないだけでしょう。
質問スレッドで解決した場合は、解決の参考になった投稿に対して「回答としてマーク」のボタンを押すことで、同じ問題に遭遇した別のユーザが役立つ投稿を見つけやすくなります。 -
ありがとうございます。
例外をまとめて拾う仕組みは分かりました。
Global.asaxとweb.configにコードを追加しましたが
例外を拾ってくれません。
設定が足りないのでしょうか。
<Global.asax>
Sub Application_Error(ByVal sender As Object, ByVal e As EventArgs)
' ハンドルされていないエラーが発生したときに実行するコードです
Dim ex As Exception = Server.GetLastError
Dim errMsg = String.Format("エラーメッセージ\{0}\n\nスタックトレース\n{1}\n", ex.Message, ex.StackTrace)
eventlog.writeentry("Application", errMsg, eventlogentrytype.error)
Response.Redirect("error.htm")
End Sub<web.config>
<customErrors mode="On" defaultRedirect="error.htm" />
-
デバックではなくwebサイトに配置して実行したら
エラー画面に遷移できました。
イベントログに
イベント ID (0) (ソース Application 内) に関する説明が見つかりませんでした。リモート コンピュータからメッセージを表示するために必要なレジストリ情報またはメッセージ DLL ファイルがローカル コンピュータにない可能性があります。この説明を取得するために /AUXSOURCE= フラグを使用することができる可能性があります。詳細については、ヘルプとサポートを参照してください。次の情報はイベントの一部です: エラーメッセージ\種類 'System.Web.HttpUnhandledException' の例外がスローされました。\n\nスタックトレース\n 場所 System.Web.UI.Page.HandleError(Exception e)
場所 System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)
場所 System.Web.UI.Page.ProcessRequest(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)
場所 System.Web.UI.Page.ProcessRequest()
場所 System.Web.UI.Page.ProcessRequestWithNoAssert(HttpContext context)
場所 System.Web.UI.Page.ProcessRequest(HttpContext context)
場所 ASP.loginauth_aspx.ProcessRequest(HttpContext context)
場所 System.Web.HttpApplication.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()
場所 System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously)\n.と
イベント コード: 3005
イベント メッセージ: ハンドルされていない例外が発生しました。
イベント時間: 2011/03/10 15:21:16
イベント時間 (UTC): 2011/03/10 6:21:16
イベント ID: 16427637bcf3412490f8b99660b10c4f
イベント シーケンス: 4
イベント発生: 1
イベント詳細コード: 0
アプリケーション情報:
アプリケーション ドメイン: /LM/W3SVC/1/Root/website-1-129442116425156250
信頼レベル: Full
アプリケーションの仮想パス: /website
アプリケーション パス: C:\Inetpub\wwwroot\website\
コンピューター名: XXXX
プロセス情報:
プロセス ID: 2596
プロセス名: aspnet_wp.exe
アカウント名: XXXX\ASPNET
例外情報:
例外の種類: ProviderException
例外メッセージ: An exception occurred. Please check the Event Log.
場所 CustomMembershipProvider.ValidateUser(String username, String password)
場所 LoginAuth.Login1_Authenticate(Object sender, AuthenticateEventArgs e)
場所 System.Web.UI.WebControls.Login.OnAuthenticate(AuthenticateEventArgs e)
場所 System.Web.UI.WebControls.Login.AttemptLogin()
場所 System.Web.UI.WebControls.Login.OnBubbleEvent(Object source, EventArgs e)
場所 System.Web.UI.Control.RaiseBubbleEvent(Object source, EventArgs args)
場所 System.Web.UI.WebControls.Button.OnCommand(CommandEventArgs e)
場所 System.Web.UI.WebControls.Button.RaisePostBackEvent(String eventArgument)
場所 System.Web.UI.WebControls.Button.System.Web.UI.IPostBackEventHandler.RaisePostBackEvent(String eventArgument)
場所 System.Web.UI.Page.RaisePostBackEvent(IPostBackEventHandler sourceControl, String eventArgument)
場所 System.Web.UI.Page.RaisePostBackEvent(NameValueCollection postData)
場所 System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)
要求情報:
要求 URL: http://XXXX/website/LoginAuth.aspx?ReturnUrl=/website/member/20110114.pdf
要求パス: /website/LoginAuth.aspx
ユーザーのホスト アドレス: 192.168.XXX.XXX
ユーザー:
認証済み: False
認証の種類:
スレッド アカウント名: XXXX\ASPNET
スレッド情報:
スレッド ID: 1
スレッド アカウント名: XXXXX\ASPNET
偽装: False
スタック トレース: 場所 CustomMembershipProvider.ValidateUser(String username, String password)
場所 LoginAuth.Login1_Authenticate(Object sender, AuthenticateEventArgs e)
場所 System.Web.UI.WebControls.Login.OnAuthenticate(AuthenticateEventArgs e)
場所 System.Web.UI.WebControls.Login.AttemptLogin()
場所 System.Web.UI.WebControls.Login.OnBubbleEvent(Object source, EventArgs e)
場所 System.Web.UI.Control.RaiseBubbleEvent(Object source, EventArgs args)
場所 System.Web.UI.WebControls.Button.OnCommand(CommandEventArgs e)
場所 System.Web.UI.WebControls.Button.RaisePostBackEvent(String eventArgument)
場所 System.Web.UI.WebControls.Button.System.Web.UI.IPostBackEventHandler.RaisePostBackEvent(String eventArgument)
場所 System.Web.UI.Page.RaisePostBackEvent(IPostBackEventHandler sourceControl, String eventArgument)
場所 System.Web.UI.Page.RaisePostBackEvent(NameValueCollection postData)
場所 System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)
カスタム イベントの詳細:
詳細な情報は、http://go.microsoft.com/fwlink/events.asp の [ヘルプとサポート センター] を参照してください。が書かれていました。
2つめがちゃんと例外処理で動いた結果のような気がします。
1つめが出力されるのが合っているのかわかりません。
-
ProviderExceptionをcatchするのは
呼び出し元関数のログイン関数の部分をtry catchにするということでしょうか。例外をスローする関数を利用する部分、あるいはそれをさらに利用する部分など、適切な場所で try-catch を書いて、例外が発生したときにどうするかを記述することでしょう。
普通に使っていて起きる例外は try-catch で処理し、あり得ない例外は素直に Application_Error でロギングするぐらいでしょうか。ところで、ProviderException とやらは発生して良い例外なんですか?普通に起きるものなんですか?
それが妥当なのかは、第三者には判断不可能なので、自分で判断してください。Global.asaxとweb.configにコードを追加しましたが例外を拾ってくれません。
設定が足りないのでしょうか。この手の 最終手段 はデバッガーで例外を検知するタイミングよりも後の処理になります。(つまり、デバッガーで実行しているとみることのできない画面となる)
デバッガーなしで実行した場合に表示されるのはこのためだと予想します。あくまで 最終手段 であって、通常起きうる例外は適切な処理(エラーの内容をわかりやすくユーザーに伝える、代替処理を実行するなど)を実装するべきです。
質問スレッドで解決した場合は、解決の参考になった投稿に対して「回答としてマーク」のボタンを押すことで、同じ問題に遭遇した別のユーザが役立つ投稿を見つけやすくなります。- 回答としてマーク 絶対初心者 2011年3月11日 4:31