문제

웹 양식의 Controls 컬렉션에 사용자 컨트롤을 추가하여 동적으로 로드하고 있습니다.

렌더링하는 동안 처리되지 않은 예외가 발생하는 경우 사용자 컨트롤을 숨기고 싶습니다.

그래서 각 UserControl의 Error 이벤트에 연결을 시도했지만 이 이벤트는 Page 클래스처럼 UserControls에 대해 발생하지 않는 것 같습니다.

인터넷 검색을 좀 해봤는데 유망한 것 같지 않습니다.여기에 아이디어가 있나요?

도움이 되었습니까?

해결책

mmilic에 이어 당신의 응답 나에게 이전 아이디어..

추가 논리가 필요하지 않습니다!문제의 클래스에 아무 작업도 수행하지 않고 인스턴스화 버블랩으로 래핑하는 것이 요점입니다!:)

좋아, 요점만 설명하려고 했으나 이 작품을 직접 보고 싶어서 몇 가지를 엮었습니다. 매우 대략적인 코드이지만 개념은 있고 작동하는 것 같습니다.

긴 게시물에 대한 사과

세이프로더

이것은 기본적으로 제가 언급한 "거품"이 될 것입니다..렌더링 중에 발생하는 모든 오류를 포착하여 컨트롤 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>";
        }
    }
}

그리고 일부 컨트롤..

좋아, 방금 여기에 두 개의 컨트롤을 함께 모의했습니다. 하나는 다른 하나를 던져 정크를 렌더링합니다.여기를 지적하세요. 나는 헛소리하지 않습니다.이는 사용자 정의 컨트롤로 대체됩니다.

BadControl

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

굿컨트롤

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

생각

좋아, 나는 당신이 "이러한 컨트롤은 프로그래밍 방식으로 인스턴스화됩니다. 디자이너 지원은 어떻습니까? "라고 생각하는 것을 알고 있습니다.나는 디자이너를 위해 이러한 컨트롤을 좋게 만드는 데 엄청난 시간을 보냈는데 이제 당신은 내 매력을 망치고 있습니다."

좋아, 아직 실제로 테스트하지는 않았지만(아마 몇 분 안에 완료할 것입니다!) 여기서의 아이디어는 페이지에 대한 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>");
        }
    }
}

즐기다!

다른 팁

이것은 흥미로운 문제입니다..사용자 정의 컨트롤 등에 관해서는 아직 꽤 낯설지만 여기에 제 생각이 있습니다(자유롭게 댓글을 달거나 수정해 주세요!)..(나는 여기서 큰 소리로 생각하고 쓰고 있습니다!)

  • 어떤 경우에는 렌더링 도중에 오류가 발생하면 너무 늦지 않을까요?(일부 컨트롤 HTML이 이미 작성자 및 출력으로 전송되었을 수 있으므로)
  • 따라서 사용자 컨트롤의 Render 메서드를 래핑하는 것이 가장 좋지 않을까요? "라이브" HtmlTextWriter에 대한 참조를 전달하는 대신 자체 전달하고 모든 것이 순조롭게 진행된다면 이 작은 안전 "버블"에서 발생한 모든 예외를 트랩합니다. , 그런 다음 결과 HTML을 실제 HtmlTextWriter에 전달합니까?
  • 이 논리는 런타임에 컨트롤을 동적으로 로드/렌더링하는 데 사용하는 일반 래퍼 클래스에 포함될 수 있습니다.
  • 오류가 발생하더라도 필요한 모든 정보를 마음대로 사용할 수 있습니다!(즉, 제어 참조 등).

내 생각만 불태우세요!:D ;)

오류가 발생한 위치에 따라 다음과 같은 작업을 수행할 수 있습니다.

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을 상속합니다.

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(안녕 Karl!)이 HttpHandler를 대신 사용하는 방법에 대한 게시물을 올렸습니다.

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

(복제 허가가 무엇인지는 모르겠지만 답변을 작성하고 싶다면 내 Upvote를 받으십시오 ☺)

렌더링 및 로드 메서드를 오류 처리하는(원하는 대로 숨길 수 있도록) UserControl의 새 하위 클래스를 추가한 다음 이를 사용자 컨트롤에 대해 상속하는 것은 어떻습니까?

내가 이해했는지 잘 모르겠어 당신의 응답..컨트롤을 어떻게 로드하고 컨트롤 컬렉션에 추가합니까?

이것이 "업데이트" 섹션에 추가된 비트의 요점이었습니다.다음을 유연하게 사용할 수 있습니다. 세이프로더 당신이 원하는 곳 어디든지.

왜 HTML에 대한 액세스/제어권이 없다고 생각하는지 잘 모르겠습니다.SafeLoader의 목표는 케어 html이 무엇인지 간단히 말하면 ("버블" 내에서) 컨트롤을 "출력"하고 현재 상태에서 정상적으로 로드되는지 확인하기만 하면 됩니다.

만약 그렇다면 (즉,html이 반환됨) 그런 다음 원하는 작업을 수행하고, html을 출력하고, 컨트롤 컬렉션에 컨트롤을 추가하는 등 무엇이든 할 수 있습니다!

그렇지 않다면 다시 원하는 대로 할 수 있고, 오류 메시지를 렌더링하고, 사용자 정의 예외를 던질 수 있습니다.선택은 당신의 것입니다!

이 내용이 이해에 도움이 되기를 바랍니다. 그렇지 않은 경우 소리를 지르시기 바랍니다. :)

@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));
     }
  }
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top