Я динамически загружаю пользовательские элементы управления, добавляя их в коллекцию Controls веб-формы.
Я хотел бы скрыть пользовательские элементы управления, если они вызывают необработанное исключение во время рендеринга.
Поэтому я попробовал подключиться к событию Error каждого UserControl, но кажется, что это событие никогда не срабатывает для UserControls, как это происходит для класса Page.
Я немного погуглил и это не кажется многообещающим. Есть идеи?
mmilic, исходя из Ваш response к моему предыдущие idea..
Никакой дополнительной логики не требуется! Что'ы точке, ваш не делает ничего, чтобы классы в вопрос, просто завернув их в пузырчатый полиэтилен экземпляра! :)
ОК, я собирался просто жирная точка, но я хотел увидеть эту работу для себя, так что я слепленная каким-то грубым код чрезвычайно но понятие есть, и это, кажется, работает.
ПРОШУ ПРОЩЕНИЯ ЗА ДЛИННЫЙ ПОСТ
Это будет в основном в "пузырь" Я упомянул.. он будет получать 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>";
}
}
}
Ок, я просто глумились вместе два контроля, один бросит другой выносит мусор. Дело здесь, я не'т дать дерьмо. Они будут заменены пользовательских элементов управления..
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);
}
ОК, я знаю, что вы думаете, что "эти элементы управления создаются программно, что о поддержке дизайнера? Я потратил чертовых часа получать эти элементы неплохо для дизайнера, теперь вы'повторно связался с моим Моджо и".
Итак, я действительно еще не проверял это (наверное сделаю в Мин!) но идея в том, чтобы переопределить метод render для страницы, и взять экземпляр каждого элемент добавляется на форму и запустить его через SafeLoader. Если код проходит, вы можете добавить его в коллекцию controls как нормальные, если нет, то можно создать ошибочный литералы или что-то, до вас, мой друг.
Опять же, извините за длинный пост, но я хотел сделать вот код, чтобы мы могли обсудить это :) Я надеюсь, что это помогает продемонстрировать мою идею :) Обновление ## Проверенные зажимные управления в конструктор и переопределить метод render с этим, нормально работает, Может нужно немного зачистить, чтобы сделать вещи лучше выглядит, но я'МР оставляю вам ;)
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>");
}
}
}
Наслаждайтесь!
Это интересная проблема... Я все еще довольно свеж, когда дело доходит до пользовательских элементов управления и т.д., но вот мои мысли (не стесняйтесь комментировать/корректировать людей!)... (Я как бы думаю/пишу вслух здесь!)
Это только мои мысли, не стесняйтесь! :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*/ }
}
}
Затем наследовать 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();
}
Кроме того, Карл Сегуин (Hi Karl!) опубликовал статью об использовании HttpHandler вместо этого:
http://codebetter.com/blogs/karlseguin/archive/2006/06/12/146356.aspx
(Не уверен, что есть разрешение на воспроизведение, но если вы хотите написать ответ, вы получили мой Upvote ☺)
Как насчет добавления нового подкласса UserControl, который обрабатывает ошибки в своих методах render и load (так, чтобы они скрывались по вашему желанию), а затем наследоваться от него для ваших пользовательских элементов управления?
Я не уверен, я понимаю ваше response](https://stackoverflow.com/questions/10793/catching-unhandled-exceptions-in-aspnet-usercontrols#15999).. как ты заряжаешь свой контроль и добавить их в элементы коллекции?
В этом был весь смысл немного добавил в "обновить" в разделе.. у вас есть возможность использовать SafeLoader где угодно.
Я не знаю, почему вы чувствуете, что вы Дон'т иметь доступа/контроля над HTML? Цель SafeLoader заключается в том, что вы не care что такое html, то можно просто попробовать и "Выход" в управление (в графе "пузырь", У) и определить, если он загружает нормально в его нынешнем состоянии.
Если это произойдет (т. е. HTML-код возвращается), то вы можете делать, что хотите с ним, вывода HTML, добавить элемент управления в коллекцию controls, что угодно!
Если нет, то опять же, вы можете делать то, что вам нравится, предоставляете сообщение об ошибке, бросить пользовательское исключение.. выбор за вами!
Я надеюсь, что это помогает прояснить вещи для вас, если нет, то пожалуйста, кричите :)
Я использовал @Кит'ы подход, но проблема в том, что элемент управления будет отображаться вплоть до исключения, что потенциально может привести к открыть 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));
}
}