对于发布如此冗长的问题,我提前道歉。信不信由你,你在这里看到的实际上代表了手头问题/代码的一个相当浓缩的版本。虽然我会很感激任何关于更好或不同方法的指示,但我也非常希望了解这一点,以便我可以在晚上睡觉:)
我遇到了在不同的 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);
}
}
不幸的是,这不起作用。我已多次单步执行此代码,尽管母版页加载 NotificationMessage UserControl 并将其添加到适当的占位符而没有发生意外,但最终的 aspx HTML从未包含该 UserControl 的标记。我在 UserControl 的Page_Load中放置了断点,并验证了它们在执行过程中确实被击中。
如果我从内容页面内部动态加载 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 属性的基于代码的切换;还是没有骰子!
如果有人能阐明这个难题,我将不胜感激。