1

I'm trying to use my master page's code-behind to display a message to the user after a redirect. Specifically,

public partial class SiteMaster : System.Web.UI.MasterPage
{
    protected void Page_Load(object sender, EventArgs e)
    {
        if (Session["redirect_message"] != null)
        {
            // put the message in a hidden field for JavaScript to put in an alert()
            Session.Remove("redirect_message");
        }
    }
}

Any page that then wants to show a message can do this:

Session["redirect_message"] = "I've sent you to OtherPage.aspx";
Response.Redirect("~/OtherPage.aspx");

That works the way I want it to...I first get OtherPage.aspx's Page_Load event, then I get the master's Page_Load event. However, I read in many places (like here) that this way of redirecting is not advisable. So, I changed to the recommended way:

Session["redirect_message"] = "I've sent you (nicely this time) to OtherPage.aspx";
Response.Redirect("~/OtherPage.aspx", false); // don't use Response.End()
Context.Application.CompleteRequest();

and unfortunately now my master page's Page_Load event is being called before OtherPage.aspx begins loading. I see from this response that there's no good way to stop processing the page (other than to use MVC, which isn't an option for me)--is there a way to at least prevent the master page controls from loading?

Community
  • 1
  • 1
John Riehl
  • 1,270
  • 1
  • 11
  • 22

1 Answers1

0

Here's one approach, but it's applicability is somewhat limited and it seems pretty inelegant. If I can make the decision to redirect in the Page_PreInit event, I can replace the master page with another master page that doesn't process the Session["redirect_message"] variable:

public partial class FirstPage : Page {
    private bool redirected = false;

    protected void Page_PreInit(object sender, EventArgs e) {
        if (redirect_condition_is_true) {
            Session["redirect_message"] = "I've sent you (nicely this time) to OtherPage.aspx";
            MasterPageFile = "~/Redirect.master";
            Response.Redirect("~/OtherPage.aspx", false); // don't use Response.End()
            Context.Application.CompleteRequest();

        }
    }

    protected void Page_Load(object sender, EventArgs e) {
        // for all Page events we're processing, start with:
        if (redirected) {
            return;
        }
    }
}

You can't just do MasterPageFile = null, since the page's elements are looking for a master page. You have to do this at PreInit because that's the last time you can change the master page. The alternative master page must have all the ContentPlaceHolder elements referenced in the page that's initiating the redirect, and it must also specify a ScriptManager if the page has a ScriptManagerProxy. Like I said, not terribly elegant...still looking for something better.

EDIT

I figured out a better way. Instead of using the master page's code-behind, I implemented a subclass of Page that includes the behavior I'm looking for, then any page that's a redirect target inherits from that subclass. So:

public class BasePage : System.Web.UI.Page {
    protected virtual void Page_Load(object sender, EventArgs e) {
        if (Session["redirect_message"] != null) {
            ClientScript.RegisterStartupScript(GetType(), "redirect_message",
                String.Format("alert('{0}');", (string)Session["redirect_message"]),
                true);
            Session.Remove("redirect_message");
        }
    }
}

and

public class OtherPage : BasePage {
    protected override void Page_Load(object sender, EventArgs e) {
        base.Page_Load(sender, e);
        // page-specifc logic here
    }
}

then when I redirect, I use:

Session["redirect_message"] = "I've sent you (nicely this time) to OtherPage.aspx";
Response.Redirect("~/OtherPage.aspx", false); // don't use Response.End()
Context.Application.CompleteRequest();

Having a base class also allows my to put other common functionality in one class. Comments welcome.

John Riehl
  • 1,270
  • 1
  • 11
  • 22