一、超级链接
从一个表单进入另一个表单最简单的方式是使用HTML超级链接控件。在Web表单中,使用超级链接的HTML代码类如:
<a href="WebForm2.aspx">WebForm2</a>
当用户点击该超级链接,WebForm2.aspx执行并将结果发送到浏览器。超级链接导航方式几乎可用于任何地方,包括HTML页面和普通的ASP页面。ASP.NET还提供了另一种可替换使用的方法,即HyperLink服务器控件:
<form id="Form1" method="post" runat="server">
<asp:HyperLink id="HyperLink1" runat="server"
NavigateUrl="WebForm2.aspx">WebForm2</asp:HyperLink>
</form>
上述HTML代码的运行结果和第一个例子相同,因为ASP.NET把HyperLink Web服务器控件视为一个HTML超级链接控件。但两者有一点重要的区别,HyperLink Web服务器控件可以在服务器端编程。具体地说,可以在程序代码中改变它的NavigateUrl属性,从而允许构造出具体目标可根据应用的当前状态动态变化的超级链接,例如:
Private Sub Button1_Click( _
ByVal sender As System.Object, _
ByVal e As System.EventArgs) _
Handles Button1.Click
HyperLink1.NavigateUrl = "WebForm3.aspx"
End Sub
这段代码执行后,如果用户点击链接,他看到的将是WebForm3.aspx,而不是WebForm2.aspx。
二、用程序控制重定向
虽然超级链接能够从一个页面导航到另一个页面,但这种导航方式是完全由用户控制的。有些时候,我们可能要用代码来控制整个导航过程,包括何时转到另一个页面。在这些场合,ASP.NET有三种不同的方式可以达到相似的目的:调用Response对象的Redirect方法,调用Server对象的Transfer或Execute方法。这三种导航方式的行为基本相似,但也有区别。
2.1 Response.Redirect
Response.Redirect方法导致浏览器链接到一个指定的URL。当Response.Redirect()方法被调用时,它会创建一个应答,应答头中指出了状态代码302(表示目标已经改变)以及新的目标URL。浏览器从服务器收到该应答,利用应答头中的信息发出一个对新URL的请求。
这就是说,使用Response.Redirect方法时重定向操作发生在客户端,总共涉及到两次与服务器的通信(两个来回):第一次是对原始页面的请求,得到一个302应答,第二次是请求302应答中声明的新页面,得到重定向之后的页面。
2.2 Server.Transfer
Server.Transfer方法把执行流程从当前的ASPX文件转到同一服务器上的另一个ASPX页面。调用Server.Transfer时,当前的ASPX页面终止执行,执行流程转入另一个ASPX页面,但新的ASPX页面仍使用前一ASPX页面创建的应答流。
如果用Server.Transfer方法实现页面之间的导航,浏览器中的URL不会改变,因为重定向完全在服务器端进行,浏览器根本不知道服务器已经执行了一次页面变换。
默认情况下,Server.Transfer方法不会把表单数据或查询字符串从一个页面传递到另一个页面,但只要把该方法的第二个参数设置成True,就可以保留第一个页面的表单数据和查询字符串。
同时,使用Server.Transfer时应注意一点:目标页面将使用原始页面创建的应答流,这导致ASP.NET的机器验证检查(Machine Authentication Check,MAC)认为新页面的ViewState已被篡改。因此,如果要保留原始页面的表单数据和查询字符串集合,必须把目标页面Page指令的EnableViewStateMac属性设置成False。
2.3 Server.Execute
Server.Execute方法允许当前的ASPX页面执行一个同一Web服务器上的指定ASPX页面,当指定的ASPX页面执行完毕,控制流程重新返回原页面发出Server.Execute调用的位置。
这种页面导航方式类似于针对ASPX页面的一次函数调用,被调用的页面能够访问发出调用页面的表单数据和查询字符串集合,所以要把被调用页面Page指令的EnableViewStateMac属性设置成False。
默认情况下,被调用页面的输出追加到当前应答流。但是,Server.Execute方法有一个重载的方法,允许通过一个TextWriter对象(或者它的子对象,例如StringWriter对象)获取被调用页面的输出,而不是直接追加到输出流,这样,在原始页面中可以方便地调整被调用页面输出结果的位置。
为说明其工作过程,下面我们创建一个Web表单,放入一个按钮控件(Button1)和一个文本控件(Literal1),在设计界面中转入代码视图,加入一个System.IO名称空间的Imports语句,然后加入用户点击按钮时执行的代码:
Private Sub Button1_Click( _
ByVal sender As System.Object, _
ByVal e As System.EventArgs) _
Handles Button1.Click
Dim sw As StringWriter = New StringWriter()
Server.Execute("WebForm2.aspx", sw)
Literal1.Text = sw.ToString()
End Sub
然后为同一个Web应用创建第二个页面WebForm2.aspx。转入该页面的HTML视图,修改其Page指令禁止ViewState检查:
<%@ Page Language="vb" AutoEventWireup="false" Codebehind="WebForm2.aspx.vb"
Inherits="Navigate.WebForm2" EnableViewStateMac="false"%>
再转到设计视图,为第二个页面增加一些控件。接下来,把第一个页面设置成默认页面,启动应用。点击按钮,WebForm2的控件将显示在WebForm1中放置Literal按钮的地方,如图一,注意页面标题和URL仍旧显示原始页面WebForm1。
图一:用Server.Execute合并两个源文件的页面
用Server.Transfer或Server.Execute方法实现导航时,还要注意一点:最后得到的页面可能不是合法的HTML页面,因为最终返回给客户端的页面可能包含多个<HTML>和<BODY>等标记。IE浏览器看来能够容忍并正确处理这类情形,但如果用户要用到其他的浏览器,最好仔细测试一下。
三、比较与选择
既然从一个页面导航到另一个页面的办法有这么多,应该如何选择最佳的导航方式呢?下面是一些需要考虑的因素:
·如果要让用户来决定何时转换页面以及转到哪一个页面,超级链接最适合。
·如果要用程序来控制转换的目标,但转换的时机由用户决定,使用Web服务器的HyperLink控件,动态设置其NavigateUrl属性。
·如果要把用户连接到另一台服务器上的资源,使用Response.Redirect。
·用Response.Redirect把用户连接到非ASPX的资源,例如HTML页面。
·如果要将查询字符串作为URL的一部分保留,使用Response.Redirect。
·如果要将执行流程转入同一Web服务器的另一个ASPX页面,应当使用Server.Transfer而不是Response.Redirect,因为Server.Transfer能够避免不必要的网络通信,从而获得更好的性能和浏览效果。
·如果要捕获一个ASPX页面的输出结果,然后将结果插入另一个ASPX页面的特定位置,则使用Server.Execute。
·如果要确保HTML输出合法,请使用Response.Redirect,不要使用Server.Transfer或Server.Execute方法。
原文:
Managing ASP.NET Navigation
by Mike Gunderloy
04/08/2003
In an ASP.NET application, you can move between Web Forms in a variety of ways: with hyperlinks, with Response.Redirect, with Server.Transfer, or with Server.Execute. In this article, I will take a look at these various navigation methods and help you choose the appropriate one for your application.
Hyperlinks
The simplest possible way to navigate from one Web Form to another is with an HTML hyperlink control. On a Web Form, that might look like this:
<a href="WebForm2.aspx">WebForm2</a>
When the user clicks on the hyperlink, WebForm2.aspx is served up to their browser. You can use this technique just about anywhere, including on HTML pages and in classic ASP. ASP.NET gives you another alternative, the HyperLink Web Server control:
<form id="Form1" method="post" runat="server">
<asp:HyperLink id="HyperLink1" runat="server"
NavigateUrl="WebForm2.aspx">WebForm2</asp:HyperLink>
</form>
At runtime, this HTML has exactly the same effect as the first example, since ASP.NET renders the HyperLink Web Server control as an HTML hyperlink control. There is one key difference, though: the Web Server control can be programmed on the server side. In particular, you can change its NavigateUrl property in code, opening up the possibility of a hyperlink whose destination depends on some part of your application's state:
Private Sub Button1_Click( _
ByVal sender As System.Object, _
ByVal e As System.EventArgs) _
Handles Button1.Click
HyperLink1.NavigateUrl = "WebForm3.aspx"
End Sub
If the user clicks on the hyperlink after this code has executed, then the link will serve up WebForm3.aspx instead of WebForm2.aspx.
Controlling Transfers Yourself
Although hyperlinks do transfer your application from one page to another, they do so completely under the control of the user. Sometimes it's convenient to control the entire process in code yourself, including deciding when to move to another page. As it happens, ASP.NET provides three different methods to accomplish this. You can call the Redirect method of the Response object, or the Transfer or Execute methods of the Server object. Although they behave very similarly, there are differences between these three methods.
Response.Redirect
The Response.Redirect method causes the browser to connect to a specified URL. When the Response.Redirect() method is called, it creates a response whose header contains a 302 (Object Moved) status code and the target URL. When the browser receives this response from the server, it uses this header information to generate another HTTP request to the new URL. When using the Response.Redirect method, the redirection happens at the client side and involves two round trips to the server: one to request the original page, which is met by the 302 response, and then a second to request the redirected page.
Server.Transfer
The Server.Transfer method transfers execution from the current ASPX file to another ASPX file on the same web Server. When your code calls the Server.Transfer method, the current ASPX page terminates execution and the flow of control is transferred to another ASPX page. The new ASPX page still uses the response stream created by the prior ASPX page. When you use this method to navigate between pages, the URL in the browser still shows the original page, because the redirection occurs on the server side and the browser remains unaware of the transfer.
By default, the Server.Transfer method does not pass the form data or the query string of the original page request to the transferred page. But you can preserve the form data and query string of the original page by setting the optional second argument of the method to True. When you use this technique, though, you need to aware of one thing: the destination page uses the same response stream that was created by the original page, and therefore the hidden _VIEWSTATE field of the original page ends up on the second page. This causes the ASP.NET machine authentication check (MAC) to assume that the ViewState of the new page has been tampered with. Therefore, when you choose to preserve the form and query string collection of the original page, you must set the EnableViewStateMac attribute of the Page directive to False for the destination page.
Server.Execute
The Server.Execute method allows the current ASPX page to execute a specified ASPX page on the same web server. After the specified ASPX page is executed, the control transfers back to the original page from which the Server.Execute method was called. This technique of page navigation is analogous to making a function call to an ASPX page. The called ASPX page has access to the form and query string collections of the calling page, and thus you need to set the EnableViewStateMac attribute of the Page directive to False on the executed page.
By default, the output of the executed page is added to the current response stream. This method also has an overloaded version in which the output of the redirected page can be fetched in a TextWriter object (or one of its children, such as a StringWriter object) instead of added directly to the response stream. This helps you to control where to place the output in the original page.
To see how this works, create a Web Form in a test ASP.NET application and place a Button control (Button1) and a Literal control (Literal1) on the Web Form. Switch to code view and add an Imports statement for the System.IO namespace. Then add code to execute when the user clicks the button:
Private Sub Button1_Click( _
ByVal sender As System.Object, _
ByVal e As System.EventArgs) _
Handles Button1.Click
Dim sw As StringWriter = New StringWriter()
Server.Execute("WebForm2.aspx", sw)
Literal1.Text = sw.ToString()
End Sub
Now create a second Web Form in the same application, WebForm2.aspx. Switch to the HTML view of this second Web Form and modify its Page directive to disable ViewState checking:
<%@ Page Language="vb" AutoEventWireup="false" Codebehind="WebForm2.aspx.vb"
Inherits="Navigate.WebForm2" EnableViewStateMac="false"%>
Switch back to design view and add some controls to the second Web Form. Now set the first Web Form as the default page and start the application. Click the button, and the controls from WebForm2 will be displayed in the area of WebForm1 where you placed the Literal control, as shown in Figure 1. You'll note from the URL and page title that the browser is still displaying WebForm1.
Figure 1: A page in the browser composed by using Server.Execute to combine two source files.
There's one more thing to be aware of when you use the Server.Transfer or Server.Execute methods to navigate: the ultimate page may not be valid HTML. That's because the response to the client will contain multiple <html> and <body> tags, among other tags. Internet Explorer seems to tolerate this situation just fine, but you may want to test the results carefully if your users prefer a different browser.
Decisions, Decisions
So, given these choices for navigating from page to page, how do you select the appropriate one for your application? Here are some things to think about:
·Hyperlinks are appropriate when you want the end user to control when navigation is performed, or to choose where to go.
·To control the user's destination, but let them decide when to get there, use a Web Server HyperLink control whose NavigateUrl property is dynamically set.
·Use Response.Redirect to connect to resources outside of the web server where your page is hosted.
·Use Response.Redirect to connect to non-ASPX resources such as HTML pages.
·Use Response.Redirect if you need to preserve a query string as an explicit part of the URL.
·When you want to transfer control to an ASPX page residing on the same web server, you should use Server.Transfer instead of Response.Redirect because Server.Transfer will avoid the unnecessary round trip and provide better performance and a better user experience.
·To capture the output from an ASPX page and display it at a specified location on another ASPX page, use Server.Execute.
·If valid HTML output is essential, use Response.Redirect instead of either the Server.Transfer or Server.Execute methods.