5

ユーザーコントロールを動的に読み込んで、WebフォームのControlsコレクションに追加しています。

レンダリング中に未処理の例外が発生した場合は、ユーザーコントロールを非表示にします。

そこで、各UserControlのErrorイベントにフックしてみましたが、Pageクラスの場合のように、このイベントがUserControlsに対して発生することはないようです。

いくつかグーグルをしましたが、それは有望ではないようです。ここに何かアイデアはありますか?

4

7 に答える 7

12

mmilic、私の前のアイデアへのあなたの応答に続いて..

追加のロジックは必要ありません!それがポイントです。問題のクラスには何もせず、インスタンス化のバブルラップでラップするだけです。:)

OK、箇条書きにするつもりでしたが、この作品を自分で見たかったので、非常に大まかなコードをまとめましたが、コンセプトはそこにあり、うまくいくようです。

長い投稿をお詫びします

SafeLoader

これは基本的に私が言及した「バブル」になります。それはコントロールHTMLを取得し、レンダリング中に発生するエラーをキャッチします。

public class SafeLoader
{
    public static string LoadControl(Control ctl)
    {
        // In terms of what we could do here, its down
        // to you, I will just return some basic HTML saying
        // I screwed up.
        try
        {
            // Get the Controls HTML (which may throw)
            // And store it in our own writer away from the
            // actual Live page.
            StringWriter writer = new StringWriter();
            HtmlTextWriter htmlWriter = new HtmlTextWriter(writer);
            ctl.RenderControl(htmlWriter);

            return writer.GetStringBuilder().ToString();
        }
        catch (Exception)
        {
            string ctlType = ctl.GetType().Name;
            return "<span style=\"color: red; font-weight:bold; font-size: smaller;\">" + 
                "Rob + Controls = FAIL (" + 
                ctlType + " rendering failed) Sad face :(</span>";
        }
    }
}

そしていくつかのコントロール..

ここで2つのコントロールをモックアップしました。一方はスローし、もう一方はジャンクをレンダリングします。ここを指して、私はがらくたを与えません。これらは、カスタムコントロールに置き換えられます。

BadControl

public class BadControl : WebControl
{
    protected override void Render(HtmlTextWriter writer)
    {
        throw new ApplicationException("Rob can't program controls");
    }
}

GoodControl

public class GoodControl : WebControl
{
    protected override void Render(HtmlTextWriter writer)
    {
        writer.Write("<b>Holy crap this control works</b>");
    }
}

ページ

では、「テスト」ページを見てみましょう。ここでは、コントロールをインスタンス化し、HTMLを取得して出力します。その後、デザイナーのサポートなどについて考えます。

ページコード-ビハインド

    protected void Page_Load(object sender, EventArgs e)
    {
        // Create some controls (BadControl will throw)
        string goodHtml = SafeLoader.LoadControl(new BadControl());
        Response.Write(goodHtml);

        string badHtml = SafeLoader.LoadControl(new GoodControl());
        Response.Write(badHtml);
    }

考え

OK、私はあなたが考えていることを知っています、「これらのコントロールはプログラムでインスタンス化されます、デザイナーのサポートはどうですか?私はこれらのコントロールをデザイナーにとって良いものにするために何時間も費やしました、今あなたは私のモジョをいじっています」。

OK、私はまだこれを実際にテストしていません(おそらく数分で実行されます!)が、ここでのアイデアは、ページのCreateChildControlsメソッドをオーバーライドし、フォームに追加された各コントロールのインスタンスを取得して、SafeLoaderを介して実行することです。コードが合格した場合は、通常どおりControlsコレクションに追加できます。そうでない場合は、誤ったリテラルなどを作成できます。

ついに..

繰り返しになりますが、長い投稿で申し訳ありませんが、これについて話し合うことができるように、ここでコードを取得したいと思いました:)これが私のアイデアを実証するのに役立つことを願っています:)

アップデート

デザイナにコントロールを追加し、これを使用してCreateChildControlsメソッドをオーバーライドすることでテストしました。正常に機能し、見栄えを良くするためにクリーンアップが必要になる場合がありますが、それはお任せします;)

protected override void CreateChildControls()
{
    // Pass each control through the Loader to check
    // its not lame
    foreach (Control ctl in Controls)
    {
        string s = SafeLoader.LoadControl(ctl);
        // If its bad, smack it downnnn!
        if (s == string.Empty)
        {
            ctl.Visible = false; // Prevent Rendering
            string ctlType = ctl.GetType().Name;
            Response.Write("<b>Problem Occurred Rendering " + 
                ctlType + " '" + ctl.ID + "'.</b>");
        }
    }
}

楽しみ!

于 2008-08-15T07:49:57.927 に答える
4

これは興味深い問題です..カスタムコントロールなどに関してはまだかなり新鮮ですが、ここに私の考えがあります(コメント/訂正してください!)..(私はちょっと考えています/ここで大声で書きます!)

  • レンダリング中にエラーが発生した場合、場合によっては手遅れではないでしょうか?(一部のコントロールHTMLは、既にWriterと出力に送信されている可能性があるため)。
  • したがって、ユーザーコントロールのRenderメソッドをラップするのは最善ではありませんが、「ライブ」HtmlTextWriterへの参照を渡すのではなく、独自のメソッドを渡し、この小さな安全な「バブル」で発生した例外をトラップします。 、次に、結果のHTMLを実際のHtmlTextWriterに渡しますか?
  • このロジックは、実行時にコントロールを動的にロード/レンダリングするために使用する汎用ラッパークラスに変更される可能性があります。
  • エラーが発生した場合は、必要なすべての情報を自由に使用できます。(つまり、コントロール参照など)。

ただ私の考え、炎上!:D;)

于 2008-08-14T08:51:47.853 に答える
1

エラーが発生している場所に応じて、次のようなことができます...

public abstract class SilentErrorControl : UserControl
{
    protected override void Render( HtmlTextWriter writer )
    {
        //call the base's render method, but with a try catch
        try { base.Render( writer ); }
        catch ( Exception ex ) { /*do nothing*/ }
    }
}

次に、UserControl の代わりに SilentErrorControl を継承します。

于 2008-08-14T11:56:38.053 に答える
0

Global.asaxとApplication_Error?

http://www.15seconds.com/issue/030102.htm

または、個々のページでのみPage_Errorイベント:

http://support.microsoft.com/kb/306355

void Page_Load(object sender, System.EventArgs e)
{
    throw(new ArgumentNullException());
}

public void Page_Error(object sender,EventArgs e)
{
    Exception objErr = Server.GetLastError().GetBaseException();
    string err =    "<b>Error Caught in Page_Error event</b><hr><br>" + 
                    "<br><b>Error in: </b>" + Request.Url.ToString() +
                    "<br><b>Error Message: </b>" + objErr.Message.ToString()+
                    "<br><b>Stack Trace:</b><br>" + 
                      objErr.StackTrace.ToString();
    Response.Write(err.ToString());
    Server.ClearError();
}

また、Karl Seguin(Hi Karl!)には、代わりにHttpHandlerの使用に関する投稿がありました。

http://codebetter.com/blogs/karlseguin/archive/2006/06/12/146356.aspx

(それを複製する許可が何であるかはわかりませんが、答えを書きたい場合は、私の賛成票を受け取ります☺)

于 2008-08-14T08:11:14.503 に答える
0

レンダリングメソッドとロードメソッドをエラー処理するUserControlの新しいサブクラスを追加して(必要に応じて非表示にするように)、それをユーザーコントロールに継承するのはどうですか?

于 2008-08-14T08:42:16.733 に答える
0

あなたの反応がよくわかりません..どのようにコントロールを読み込んでコントロール コレクションに追加していますか?

それが、「更新」セクションに追加されたビットの要点でした.. 好きな場所でSafeLoaderを柔軟に使用できます。

Html へのアクセス/制御がないと感じる理由がわかりません。SafeLoader の目的は、html が何であるかを気にする必要がないことです。コントロールを (「バブル」内で) 「出力」して、現在の状態で正常に読み込まれるかどうかを判断するだけです。

ある場合 (つまり、html が返された場合)、それで好きなことをしたり、html を出力したり、コントロールをコントロール コレクションに追加したりできます。

そうでない場合は、好きなことをしたり、エラー メッセージを表示したり、カスタム例外をスローしたりできます。選択はあなた次第です。

これがあなたのために物事を明確にするのに役立つことを願っています.そうでない場合は、叫んでください:)

于 2008-08-20T12:59:40.653 に答える
0

@Keith のアプローチを使用しましたが、例外がスローされるまでコントロールがレンダリングされ、HTML タグが開いている可能性があるという問題があります。また、デバッグ モードの場合は、コントロールに例外情報をレンダリングしています。

  protected override void Render(System.Web.UI.HtmlTextWriter writer)
  {
     try
     {
        // Render the module to a local a temporary writer so that if an Exception occurs
        // the control is not halfway rendered - "it is all or nothing" proposition
        System.IO.StringWriter sw = new System.IO.StringWriter();
        System.Web.UI.HtmlTextWriter htw = new System.Web.UI.HtmlTextWriter(sw);
        base.Render(htw);

        // We made it!  Copy the Control Render over
        writer.Write(sw.GetStringBuilder().ToString());
     }
     catch (System.Exception ex)
     {
        string message = string.Format("Error Rendering Control {0}\n", ID);
        Log.Error(message, ex);
        if (Page.IsDebug)
           writer.Write(string.Format("{0}<br>Exception:<br><pre>{1}\n{2}</pre>", message, ex.Message, ex.StackTrace));
     }
  }
于 2012-06-08T18:32:52.790 に答える