后redirect – 获取ASP.NET

我怎样才能实现ASP.NET的后redirect获取模式?

button点击执行一些处理:

<asp:Button id="bbLaunch" OnCommand="bbLaunch_Click" /> 

用户点击button,航天器启动,网页重新显示。 如果用户按下F5,则会发出警告:

在这里输入图像说明

问题的解决scheme是Post-Redirect-Get模式。

什么是PRG可以在ASP.NET中实现的方法?


问题围绕以下问题展开:

  • <asp:Button>执行一个POST到一个不是它的原始forms的地方?
  • 当您发布到不读取视图状态的表单时, ViewState会怎样?
  • 当您redirect到“真正的”aspx网页表单时, ViewState会变成什么样子?
  • ViewState从根本上与ASP.net不兼容Post-Redirect-Get?
  • 是ASP.net从根本上不兼容后redirect – 获取
  • 如何 (即什么代码)你redirect到“真正的”aspx网页forms?
  • 如何 (即什么url)你redirect到“真正的”aspx网页forms? 关系问题提到Response.Redirect(Request.RawUrl);
  • 什么时候 (即在什么事件处理程序),你redirect到“真正的”aspx网页forms?
  • 相关的问题引发如何发布表单数据的问题。 这意味着HTML 表单不能被使用 – 所有的表单数据都必须被添加到查询string中。 这是真的? 如果是这样,为什么? 如果没有,为什么不呢? 浏览器可以将查询string中的表单数据?
  • 一个相关的问题提到Server.Transfer 。 使用Server.Transfer是完全错误的,绝不会解决Post-Redirect-Get问题(因为没有redirect )。 正确?
  • aspxaspx.cs文件中必须发生哪些代码更改才能支持PRG? 据推测,至less必须将代码更改为除MyPage.aspx之外的MyPage.aspx

换句话说: 你如何做后redirect – 获取在ASP.net?

注意 :ASP.net(即不是ASP.net MVC)

也可以看看

  • 如何在asp.net WebForms中实现Post / Redirect / Get模式?
  • 如何在asp.net中使用“发布/redirect/获取”又名“发布后redirect”

通常,您可以通过使用查询string来指示要加载/处理哪个logging的aspx Web表单来完成此操作。

假设您有一个页面让您更新一些客户信息:

 http://www.mysite.com/customer.aspx 

您可以在查询string中使用一个ID加载表单:

 http://www.mysite.com/customer.aspx?CustomerId=42 

在代码隐藏你会有这样的事情:

 protected void Page_Load(object sender, EventArgs e) { if (!IsPostBack) { int customerId = 0; if (!string.IsNullOrEmpty(Request.QueryString["CustomerId"])) { int.TryParse(Request.QueryString["CustomerId"], out customerId ); } if (customerId == 0) { //handle case when no valid customer id was passed in the qs here } else { //load customer details, bind controls etc //make sure to handle the case when no customer was found using the id in the qs } } } 

然后在你的页面的某个地方,你会有一个button来保存更改。 该button将在后面的代码中有一个OnClick处理程序:

 protected void SaveClicked(object sender, EventArgs e) { //save changes to database here //Redirect if all went well Response.Redirect("http://www.mysite.com/customer.aspx?CustomerId=" + idOfSavedCustomer.ToString()); } 

这基本上应该是这样。 redirect将导致浏览器对redirect(…)中的URL发出新的GET请求。 它将加载页面, if (!IsPostBack)将运行,并使用刚刚在上一个post中保存的新值初始化页面。

在整个过程中,浏览器和服务器之间的stream量将如下所示:

 Browser: GET http://www.mysite.com/customer.aspx?CustomerId=42 Server: 200 (send back some html) Browser: POST http://www.mysite.com/customer.aspx?CustomerId=42 (post data sent in request) Server: 302 (point to http://www.mysite.com/customer.aspx?CustomerId=42) Browser: GET http://www.mysite.com/customer.aspx?CustomerId=42 Server: 200 (send html) 

在中间步骤中,服务器基本上是这样说的:

“你发给我的邮件请求,我完成了,现在请到这里的另一页…”

事实上,url实际上引用了同一个页面并不重要。


一些思考回应你的问题清单:

  • 如何执行POST到一个不是它的原始forms的地方?

您可以通过在表单上设置action属性来完成此action ,也可以在button上设置PostBackUrl

  • 当您发布到不读取视图状态的表单时,ViewState会怎样?

依靠。 如果您只是将表单发布到其他页面,则可以使用<%@ PreviousPageType … />指令来告诉post来自哪里的“新”页面。 这将简单地处理新页面上发布的数据。 详细信息请参阅此链接 。

  • 当您redirect到“真正的”aspx网页表单时,ViewState会变成什么样子?

视图状态在发布请求中发送。 redirect时,浏览器将加载一个新页面,并创build它自己的viestate。

  • ViewState从根本上与ASP.net不兼容Post-Redirect-Get?

取决于你如何看待它。 redirect之后,新页面将无法访问页面的视图状态。

  • 是ASP.net从根本上不兼容后redirect – 获取?

不可以看上面的例子。

  • 如何(即什么代码)你redirect到“真正的”aspx网页forms?

Response.Redirect的(URL)。 这会向浏览器发送一个响应,告诉它做一个新的获取请求。

  • 什么时候(即在什么事件处理程序),你redirect到“真正的”aspx网页forms?

当你完成了处理邮寄请求所需的所有工作。

  • 相关的问题引发了您如何发布表单数据的问题。 这意味着HTML表单不能被使用 – 所有的表单数据都必须被添加到查询string中。 这是真的? 如果是这样,为什么? 如果没有,为什么不呢? 浏览器可以将查询string中的表单数据?

redirect发布请求不是很好的支持,应该可以避免。 这可以通过使用http响应307来完成(通过一些浏览器)。当这样做的时候,服务器有效地告诉浏览器“ 我不会处理你的请求,请把它发送到这个其他页面 ”。

  • 一个相关的问题提到Server.Transfer。 使用Server.Transfer是完全错误的,绝不会解决Post-Redirect-Get问题(因为没有redirect)。 正确?

Server.Transfer(…)是发生在服务器端的东西。 浏览器不知道它。 基本上一个页面可以使用Server.Transfer为了让其他页面做一些处理,并且该页面将负责将响应发送回浏览器。 但浏览器会认为这是原始页面的回应。

  • aspx或aspx.cs文件中必须发生哪些代码更改才能支持PRG? 据推测,至less必须将代码更改为除MyPage.aspx之外的其他位置。

不,可以使用常规邮寄回来。 诀窍是在处理发布的数据之后,在页面上有一个(或几个)特定的事件处理程序来执行Repsonse.Redirect。

Q)如何执行一个POST到一个不是它的原始forms的地方?

A)使用PRG,您不会POST到不同的页面,而是回到同一页面(请参阅您链接到的维基百科页面上的图表)。但该页面的响应必须是30X响应(通常是302 。)

Q)当您发布到不读取视图状态的表单时,ViewState会变成什么样子?

A)当你开机自检时,视图状态就在那里,但是在那里,你正在进行一个GET的新页面的视图状态将不存在。

Q)当您redirect到“真正的”aspx网页表单时,ViewState会变成什么样子?

A)以上,没有更多的视图状态redirect到页面。

问)是ViewState从根本上与ASP.net不兼容?

A)ViewState与ASP.NET不兼容。 P / R / G用于渲染redirect到的页面(大部分)是无用的。

问)是ASP.net从根本上不兼容后redirect – 获取?

A)否 – 但不能过分依赖使用一页,并保持所有状态在视图状态,如上所述。 也就是说,ASP.MVC映射好多了P / R / G

问)你怎么(即什么代码)你redirect到“真正的”aspx网页forms?

A)old_page_you_are_posting_from.aspx的bbLaunch_Click方法中的Response.Redirect(“new_page_you_are_redirecting_to.aspx”)

Q)你是如何(即什么url)redirect到“真正的”aspx网页forms? 关系问题提到Response.Redirect(Request.RawUrl);

A)见上文

问)什么时候(即在什么事件处理程序),你redirect到“真正的”aspx网页forms?

A)按下button后,将数据保存到数据库(或会话等),然后再写入任何其他内容到响应stream。

问)相关的问题引发了你如何发布表单数据的问题。 这意味着HTML表单不能被使用 – 所有的表单数据都必须被添加到查询string中。 这是真的?

A)否 – ASP.NET WebForms中的button按下将回发到页面。

问)如果是这样,为什么? 如果没有,为什么不呢?

A)比这更简单,为什么不呢。 影像两页:first_page.asp和second_page.aspx。 First_page.aspx上有它的button(以及用户已经填写的其他ASP.NET Web控件,如文本框等)。当他们按下button时,POST是对first_page.aspx进行的。 在处理完数据之后(这可能在viewstate内部,尽pipe这是抽象出来的),您可以使用Response.redirect将用户redirect到second_page.aspx。 Second_page.aspx可以显示你想要的。 如果你想(或需要)显示与first_page.aspx相似的UI,包括控件和input的内容,你可以在会话中存储一个cookie,URL作为querystring params来设置这些控件在second_page.aspx上。 (但是您可能不需要在second_page.aspx上显示与first_page.aspx相似的任何内容 – 因此这里没有一般规则。)

问)浏览器可以将查询string中的表单数据?

答)是的,如果您将方法设置为GET而不是POST。 您无法重写WebForms来执行此操作,PRG不需要此操作

问)一个相关的问题提到Server.Transfer。 使用Server.Transfer是完全错误的,绝不会解决Post-Redirect-Get问题(因为没有redirect)。 正确?

A)本质上

Q)aspx或aspx.cs文件中必须发生什么样的代码变化才能支持PRG? 据推测,至less必须将代码更改为除MyPage.aspx之外的其他位置。

A)代码仍应回发(如上所述)。但是,然后Mypage.aspx应该重新指向button处理程序中的新页面。

Postredirect获取的确切步骤是这样的:

http://www.planethost.gr/P​​ostRedirectGet.jpg

你用数据填写表单,在你有效的提交(POST)之后,将它们插入到你的数据库中,然后给它们一个确认ID,然后你将用户redirect到带有这个确认ID的页面作为URL参数作为(GET)redirect后,每个F5刷新只读取数据,而不是再次插入它们。

插入的代码与显示确认的代码不同,您甚至可以使它们成为不同的页面 – 您可以使用只读文本框创build同一页面。

redirect很简单,asp.net的Responce.Redirect函数

在POST和redirect之后,唯一的想法就是连接你以前的操作是确认码(而不是视图状态)

这种方法的缺点是实际上不能识别刷新,只是做了一个额外的步骤,使刷新不再插入相同的数据 – 但需要额外的代码获取数据。

另一种方法是识别刷新,而不是redirect。 通过识别发回的刷新,您可以避免将相同的数据与单条消息插入到用户。 网上有一些例子,我已经实现了一个成功的例子。

一个例子: http : //www.codeproject.com/Tips/319955/How-to-prevent-Re-Post-action-caused-by-pressing-b

Post-Redirect-Get模式可以在Web窗体中使用。 我已经展示了如何通过将MVC NerdDinner应用程序转换为Web Forms( http://navigationnerddinner.codeplex.com/)来实现这一点。; 我已经保持导航细节完全一样,所以有很多PRG模式的例子。

但是,还有另一种避免F5 / Refresh问题的方法。 如果您将页面封装在UpdatePanel(ASP.NET Ajax的一部分)中,则所有回发将被转换为部分页面请求。 这意味着当按F5时,它只会刷新原来的GET请求(因为没有任何后续的POST),所以你不会得到警告。 (注意,如果JavaScript被禁用,警告仍然会出现)。

您可以调用Response.Redirect方法转到另一个位置。

有几件事情要做到这一点。

  1. 将主页面上的表单的action属性(我们称之为LaunchForm.aspx )设置为等于“代理”页面( ProxyLaunchForm.aspx )的URL。

    <form id =“form1”runat =“server”action =“ProxyLaunchForm.aspx”method =“POST”>

  2. (可选)将名为redirectUrl的隐藏input添加到表单中,并为URL告知ProxyLaunchForm.aspx完成执行启动(PRG的R部分)后redirect到的位置。

  3. 现在在ProxyLaunchForm.aspx上 ,实现应该在Page_Load事件处理程序中进行,因为它可以访问表单数据。 在这里执行启动。

  4. 随后(也在Page_Load中 ),执行redirect(使用#2中的redirectUrl或简单地使用引用页面URL):

    Response.Redirect(Request.Params [“redirectUrl”] Request.UrlReferrer.AbsoluteUri);

    视图状态依然存在。 我认为处理这个最简单的方法是改变视图状态的持续状态。 通常情况下,它被保存到页面上的一个隐藏的input元素,并在回发中检索(这当然意味着,由于HTTP的无状态性,在redirect之后它会丢失)。 但是,您可以覆盖ASP.net使用的方法,并使用Session来代替(即使在PRG代理操作之后它仍然存在)。 所以,最后…

  5. LaunchForm.aspx.cs中 ,使用基类Subclassed Page来覆盖SavePageStateToPersistenceMediumLoadPageStateFromPersistenceMedium方法来从会话中存储/检索它们,而不是从隐藏的表单字段中。 见下面( 这里有更多关于这是如何工作的信息 )。

*

 public class PersistViewStateToSession : Page { protected override void SavePageStateToPersistenceMedium(object viewState) { // serialize the view state into a base-64 encoded string LosFormatter los = new LosFormatter(); StringWriter writer = new StringWriter(); los.Serialize(writer, viewState); // save the string to session Session["LaunchViewState"] = writer.ToString(); } protected override object LoadPageStateFromPersistenceMedium() { if (!Session["LaunchViewState"] == null) return null; else { string sessionString = (string)Session["LaunchViewState"]; // deserialize the string LosFormatter los = new LosFormatter(); return los.Deserialize(viewStateString); } } }