Заранее извиняюсь за размещение такого длинного вопроса. Верьте или нет, то, что вы видите здесь, на самом деле представляет собой довольно сжатую версию проблемы / кода под рукой. И хотя я был бы признателен за любые указатели на лучший или другой подход, я также очень хотел бы получить суть этого, чтобы я мог спать по ночам:)
Я столкнулся с требованием передавать сообщения подтверждения между различными страницами aspx. Я отказался от использования строковой переменной запроса, так как значения строки запроса "являются" липкими (то есть они сохраняются во всех последующих обратных передачах), и я не хотел иметь дело с добавлением связки условной логики вокруг этого.
Во всяком случае, я придумал очень простой класс, который использует Session для связи уведомлений с конкретными URL-адресами. Затем я подключил событие моей главной страницы Page_Load , чтобы запросить у этого класса любые уведомления, которые должны отображаться для текущего URL. Если он обнаруживает их, он динамически загружает пользовательский элемент управления NotificationMessage и отображает содержимое сообщения.
При попытке передавать уведомления между различными страницами aspx все работает как положено. Как и ожидалось, все не работает, когда страница содержимого пытается добавить к себе уведомление (т. Е. «Введенные вами данные недействительны, попробуйте еще раз»). Причина довольно ясна: к тому времени, когда страница контента добавляет для себя Уведомление, событие Page_Load главной страницы уже сработало, поэтому в жизненном цикле страницы уже слишком поздно, чтобы что-то делать. Соответствующий код вставлен ниже.
public class MyMasterPage:MasterPage{
protected void Page_Load(object sender, EventArgs e)
{
LoadNotifications(this.Request.Url.ToString());
}
private void LoadNotifications(string url)
{
//look for a notification
Notification? notification = NotificationManager.Instance.RetrieveNotification(url);
//there are no notifications, nothing to see here
if (!notification.HasValue)
{
return;
}
//there is a Notification for this url, so load it into a user control
NotificationMessage notificationMessageControl = (NotificationMessage)LoadControl("~/App_UserControls/NotificationMessage.ascx");
notificationMessageControl.ID = "notificationMessage";
notificationMessageControl.Notification = notification;
notificationMessageControl.Visible = true;
//find the placeholder on the master page
PlaceHolder placeHolder = (PlaceHolder)PageUtils.FindControlRecursive(this, "NotificationPlaceholder");
if (placeHolder == null)
{
throw new ApplicationException("NotificationPlaceholder control not found.");
}
//insert into control
placeHolder.Controls.Add(notificationMessageControl);
placeHolder.Visible = true;
//remove the notification so it doesn't show up next time
NotificationManager.Instance.RemoveNotification(url);
}
}
Учитывая жизненные циклы, указанные выше, я изменил класс NotificationManager, чтобы он вызывал событие всякий раз, когда для текущей страницы было добавлено уведомление. Главная страница перехватывает это событие, и, если Page_Load уже запущен, он снова запускает метод LoadNotifications.
//bind the event on the page constructor
public MyMasterPage()
{
NotificationManager.Instance.NotificationAdded += this.NotificationAdded;
}
private void NotificationAdded(string forUrl)
{
if (_pageLoaded){
LoadNotifications(forUrl);
}
}
К сожалению, это не работает. Я проходил этот код много раз, и, несмотря на тот факт, что главная страница загружает UserControl NotificationMessage и добавляет его к соответствующему заполнителю без происшествий, конечный aspx HTML никогда не содержит разметки для этого UserControl. Я установил точки останова внутри Page_Load в UserControl и убедился, что они действительно попадают во время выполнения.
Если я динамически загружаю UserControl изнутри страницы контента и вообще пропускаю главную страницу, он рендерится без помех:
public partial class MyContentPage:Page
{
public void DoSomethingCool(object sender, EventArgs e)
{
if (MyServiceLayer.Save(foo)==false){
Notification notification = new Notification(NotificationType.Error, "We’re sorry, your document was not saved.");
NotificationMessage notificationMessage = (NotificationMessage)LoadControl("~/App_UserControls/NotificationMessage.ascx");
notificationMessage.Notification = notification;
notificationMessage.Visible = true;
PlaceHolder holder = (PlaceHolder)PageUtils.FindControlRecursive(this, "NotificationPlaceholder");
holder.Controls.Add(notificationMessage);
}
}
}
Для записи я убрал динамическую загрузку UserControl, выбрав вместо этого статическое объявление в разметке главной страницы и переключение на основе кода свойства Visible элемента управления; до сих пор нет кости!
Если бы кто-то мог пролить свет на эту головоломку, я был бы очень признателен.