This is a question that comes up quite frequently: I have a form with several submit or link buttons and one or more of the buttons needs to open a new Window. How do I get several buttons to all post to the right window?

If you're building ASP.NET forms you probably know that by default the Web Forms engine sends button clicks back to the server as a POST operation. A server form has a <form> tag which expands to this:

<form method="post" action="default.aspx" id="form1">

Now you CAN change the target of the form and point it to a different window or frame, but the problem with that is that it still affects ALL submissions of the current form. If you multiple buttons/links and they need to go to different target windows/frames you can't do it easily through the <form runat="server"> tag.

Although this discussion uses ASP.NET WebForms as an example, realistically this is a general HTML problem although likely more common in WebForms due to the single form metaphor it uses. In ASP.NET MVC for example you'd have more options by breaking out each button into separate forms with its own distinct target tag. However, even with that option it's not always possible to break up forms - for example if multiple targets are required but all targets require the same form data to the be posted.

A common scenario here is that you might have a button (or link) that you click where you still want some server code to fire but at the end of the request you actually want to display the content in a new window. A common operation where this happens is report generation: You click a button and the server generates a report say in PDF format and you then want to display the PDF result in a new window without killing the content in the current window. Assuming you have other buttons on the same Page that need to post to base window how do you get the button click to go to a new window?

Can't  you just use a LinkButton or other Link Control?

At first glance you might think an easy way to do this is to use an ASP.NET LinkButton to do this - after all a LinkButton creates a hyper link that CAN accept a target and it also posts back to the server, right? However, there's no Target property, although you can set the target HTML attribute easily enough.

Code like this looks reasonable:

     <asp:LinkButton runat="server" ID="btnNewTarget" Text="New Target" 
                     target="_blank"  OnClick="bnNewTarget_Click" />

But if you try this you'll find that it doesn't work. Why? Because ASP.NET creates postbacks with JavaScript code that operates on the current window/frame:

<a id="btnNewTarget" target="_blank" 
href="javascript:__doPostBack(&#39;btnNewTarget&#39;,&#39;&#39;)">New Target</a>

What happens with a target tag is that before the JavaScript actually executes a new window is opened and the focus shifts to the new window. The new window of course is empty and has no __doPostBack() function nor access to the old document. So when you click the link a new window opens but the window remains blank without content - no server postback actually occurs.

Natch that idea.

Setting the Form Target for a Button Control or LinkButton

So, in order to send Postback link controls and buttons to another window/frame, both require that the target of the form gets changed dynamically when the button or link is clicked. Luckily this is rather easy to do however using a little bit of script code and jQuery.

Imagine you have two buttons like this that should go to another window:

        <asp:LinkButton runat="server" ID="btnNewTarget" Text="New Target" 
                        OnClick="ClickHandler" />

        <asp:Button runat="server" ID="btnButtonNewTarget" Text="New Target Button" 
                    OnClick="ClickHandler" />

ClickHandler in this case is any routine that generates the output you want to display in the new window. Generally this output will not come from the current page markup but is generated externally - like a PDF report or some report generated by another application component or tool. The output generally will be either generated by hand or something that was generated to disk to be displayed with Response.Redirect() or Response.TransmitFile() etc.

Here's the dummy handler that just generates some HTML by hand and displays it:

protected void ClickHandler(object sender, EventArgs e)
{
    // Perform some operation that generates HTML or Redirects somewhere else
    Response.Write("Some custom output would be generated here (PDF, non-Page HTML etc.)");
    
    // Make sure this response doesn't display the page content
    // Call Response.End() or Response.Redirect()
    Response.End();
}

To route this oh so sophisticated output to an alternate window for both the LinkButton and Button Controls, you can use the following simple script code:

    <script type="text/javascript">
        $("#btnButtonNewTarget,#btnNewTarget").click(function () {
            $("form").attr("target", "_blank");
        });
    </script>

So why does this work where the target attribute did not? The difference here is that the script fires BEFORE the target is changed to the new window. When you put a target attribute on a link or form the target is changed as the very first thing before the link actually executes. IOW, the link literally executes in the new window when it's done this way.

By attaching a click handler, though we're not navigating yet so all the operations the script code performs (ie. __doPostBack()) and the collection of Form variables to post to the server all occurs in the current page. By changing the target from within script code the target change fires as part of the form submission process which means it runs in the correct context of the current page. IOW - the input for the POST is from the current page, but the output is routed to a new window/frame. Just what we want in this scenario.

Voila you can dynamically route output to the appropriate window.