CrossPagePostback in new window...

Hey All,

As you may know to postback a page to another page i..e Cross Page Postback you set the PostBackUrl to the page you would like to post the page to. But what if you would like to post back the page and have it open in a new window. I thought easy just set the forms target before it does the postback and presto. But this is not posible as when you overrides the target the nexttime you postback on that page it will still open in a new window and also as the action of the page is overriden for the Cross page postback to work nothing works anymore.

To fix this I knew I had to somehow remember the current action before a postback, change the target, post the form, reset action and target. This has prooved painful. I have created a custom Button control and found that the scripts etc for doing the crosspage postback are added in the AddAttributesToRender method. I have overriden this event and changed it so that it adds the scripts I would like. And then call the base.AddAttributesToRender method. Problem with this is the base method will add its script again, I think the only way to stop this is do a complete override of the AddAttributesToRender method and basically replicate what the current control does. I am just doing this as a test at the moment so am not doing this.

The other trick is to make sure the form is doing a client side script postback, this helps in being able to change the target and reset it back again. Because I originally was not doing this and could not get it working.

The code below works and in my tests I could not find an issue using it. Cross page postbacks in a new window work fine and subsuquent postbacks also work ok. If anyone has any better ideas on howto override this script another way please let me know....

Code:

    public class CustomButton : Button {
        
        protected override void AddAttributesToRender(HtmlTextWriter writer) {
            System.Text.StringBuilder currentScript = new System.Text.StringBuilder();               
           
            // Get the current onclientclick script.
            currentScript.Append(this.OnClientClick);

            // Get the script from our attributes and then remove the onclick
            // attribute.
            if (base.Attributes["onclick"] != null) {
                currentScript.Append(base.Attributes["onclick"]);
                base.Attributes.Remove("onclick");
            }

            // Get postback options, and make sure we are doing a client script submit,
            // this helped in fixing the issue of changing the action and reverting back,
            // granted it needs js but the cross page postback needs js anyway.
            PostBackOptions opt = this.GetPostBackOptions();
            opt.ClientSubmit = true;

            // Get the postback script.
            string postback = this.Page.ClientScript.GetPostBackEventReference(opt, false);
           
            if (postback != null) {              
                               
                if (this.PostBackUrl != string.Empty) {
                    // Remember the current action.
                    currentScript.Append("var oldAction = document.forms[0].action;");
                    // Change target to a new form.
                    currentScript.Append("document.forms[0].target='_blank';");
                }
               
                // Add the postback script.
                currentScript.Append(postback + ";");               
               
                if (this.PostBackUrl != string.Empty) {
                    // Reset target back to self.
                    currentScript.Append("document.forms[0].target='_self';");
                    // Reset the action.
                    currentScript.Append("document.forms[0].action=oldAction;");
                    // Return false to stop page submitting.
                    currentScript.Append("return false;");
                }

            }

            // Add our new onclick attribute.
            if(currentScript.Length > 0)
                writer.AddAttribute("onclick", currentScript.ToString());

            base.AddAttributesToRender(writer); 

        }

        protected override void Render(HtmlTextWriter writer) {
            // Render using our custom decerator which allows us to emit the onclick
            // that the base button control adds...
            base.Render(new ButtonWriter(writer));
        }

        private class ButtonWriter : HtmlTextWriter {
            internal ButtonWriter(HtmlTextWriter writer)
                : base(writer) {
            }
            public override void AddAttribute(HtmlTextWriterAttribute key, string value) {
                if (key == HtmlTextWriterAttribute.Onclick)
                    return;
                base.AddAttribute(key, value);
            }
            public override void AddAttribute(string name, string value) {
                base.AddAttribute(name, value);
            }
        }
       
    }

 

Update:

Thanks to this blog I found on creating a decorator to hook  into rendering:

http://haacked.com/archive/2006/01/18/usingadecoratortohookintoawebcontrolsrenderingforbetterxhtmlcompliance.aspx

I can do something like this:

        private class ButtonWriter : HtmlTextWriter {
            internal ButtonWriter(HtmlTextWriter writer)
                : base(writer) {
            }
            public override void AddAttribute(HtmlTextWriterAttribute key, string value) {
                if (key == HtmlTextWriterAttribute.Onclick)
                    return;
                base.AddAttribute(key, value);
            }           
        }

So when AddAttribute(HtmlTextWriterAttribute key, string value) is called which looking at reflector that is what the base button does I ignore any onclick attribute. In my code I use the AddAttribute(string name, string value) signature so it will still be added. Not perfect yet but closer. And then just override the render method to make use of our new decorator:

 protected override void Render(HtmlTextWriter writer) {
            base.Render(new ButtonWriter(writer));
 }


We now emit the old client script code and only have our custom code. The code above has been updated to reflect the new CustomButton...

---

Thanks 

Stefan 

Published Wednesday, January 16, 2008 7:11 PM by stefan.sedich

Comments

# CrossPagePostback in new window...

Wednesday, January 16, 2008 8:38 AM by DotNetKicks.com

You've been kicked (a good thing) - Trackback from DotNetKicks.com

# re: CrossPagePostback in new window...

Friday, January 18, 2008 5:30 AM by panos

Very helpful article. Could you give a sample of this ?

# re: CrossPagePostback in new window...

Friday, January 18, 2008 10:13 PM by stefan.sedich

Panos,

Would you like a sample project? if so send me an email @ stefan.sedich@gmail.com and let me know what you would like and I will try get something to you soon.

Thanks

Stefan

# re: CrossPagePostback in new window...

Tuesday, January 22, 2008 4:14 PM by Habib ur Rehman

Hi Dear!

Good day! I have a master page having a tree view control for menu and in content (Child) page its a parameter form.

When User fill up the parameter form I want to open report in a new window.

In the same window I don't have any problem. In short I want to open a new window on button's click only and want to post parameter data on newly opened window.

I don't wanna do it with session variables and cookies as well.

I want to use previous page or Request.Form.

Can you help me for this.

Regards,

Habib ur Rehman

habibjanjua@gmail.com

Pakistan.

# re: CrossPagePostback in new window...

Tuesday, January 22, 2008 7:32 PM by stefan.sedich

Hello this should work perfect for your example. Basically your would create the custom button control, add it to your page and set the postbackURL to the page you would like to post to. It would handle posting to a new window. If you would like I could create a control and supply the dll and source code for you. I would create a new button and add a Target property to it. This would allow to set a target for your cross page postbacks apart from _blank.

Send me an email @ stefan.sedich@gmail.com if you are interested or would like more help with this.

Thanks

Stefan

# re: CrossPagePostback in new window...

Thursday, January 24, 2008 7:38 AM by Habib ur Rehman

Good day! Thanks a lot!

I have done that, but can you tell me, we overrided on click event and on the button click what ever its doing is perfect but I want to add some more code on its click event not while creating the control but when we use this control on the web form.

Habib ur Rehman

habibjanjua@gmail.com

# re: CrossPagePostback in new window...

Thursday, January 24, 2008 5:37 PM by stefan.sedich

Hi,

Glad to hear it worked. If you are talking about adding javascript to the button when you click on it you could try adding an onclick attribute. Or even setting the OnClientClick property to the javascript you would like to run on click.

Thanks

Stefan

# Lipitor.

Saturday, June 28, 2008 4:03 AM by Lipitor.

Side effects from lipitor.

# re: CrossPagePostback in new window...

Wednesday, July 30, 2008 9:48 AM by Steven

This code is exactly what we require however I'm unsure how to go about using it. I've been coding in .net for a good few months now and thought I was getting to know most of it quite well but I've got stuck with this one.

A few simple pointers should do the trick!

Thanks!!

# re: CrossPagePostback in new window...

Tuesday, November 04, 2008 10:31 AM by mahoni

how can i put it running. iam mostly new in this.

Do i have to make a cs? and then?

Thank you!

# re: CrossPagePostback in new window...

Tuesday, November 24, 2009 7:27 AM by MdV

Thank you for sharing this solution!

As my web application is written in VB.Net, I translated your code to VB.Net and it's working just fine.

Leave a Comment

(required) 
(required) 
(optional)
(required)