\n
摘要:在这个Tip中,Stephen Walther介绍了当提交表单后如需重定向,为何需要调用RedirectToAction方法进行重定向,而不是直接返回一个视图。
\n
假设你正在用一个HTML表单从用户那里收集信息。该HTML表单是由名为HomeController.Create()的控制器action显示的,而数据提交到名为HomeController.New()的控制器action,它会将表单中的数据添加到数据库中。在表单数据提交后,你希望显示聚合统计结果(如图1)。
\n
图1 – Results.aspx视图
\n
在编写New()控制器action时有两种方法。在清单1中,New() action首先将表单数据提交到数据库(使用LINQ to SQL),然后调用RedirectToAction()将用户重定向到Results() action。在清单2中,New() action没有调用RedirectToAction()。而是直接从New() action返回Results.aspx视图。
\n
清单1 – SurveyController.vb
\n
1Public Class SurveyControllerClass SurveyController
2 Inherits System.Web.Mvc.Controller
3
4 Private _db As New SurveyDataContext()
5
6 Function Create()Function Create()
7 Return View()
8 End Function
9
10 Function [()Function [New](ByVal favoriteColor As String)
11
12 ‘ Add new survey results to database
13 Dim newSurvey As New Survey()
14 newSurvey.FavoriteColor = favoriteColor
15 newSurvey.EntryDate = DateTime.Now
16 _db.Surveys.InsertOnSubmit(newSurvey)
17 _db.SubmitChanges()
18
19 ‘ Redirect to Confirm action
20 Return RedirectToAction(“Results”)
21 End Function
22
23 Function Results()Function Results()
24 Return View(_db.Surveys)
25 End Function
26
27End Class
清单2 – Survey2Controller.vb
\n
1Public Class Survey2ControllerClass Survey2Controller
2 Inherits System.Web.Mvc.Controller
3
4 Private _db As New SurveyDataContext()
5
6 Function Create()Function Create()
7 Return View()
8 End Function
9
10 Function [()Function [New](ByVal favoriteColor As String)
11
12 ‘ Add new survey results to database
13 Dim newSurvey As New Survey()
14 newSurvey.FavoriteColor = favoriteColor
15 newSurvey.EntryDate = DateTime.Now
16 _db.Surveys.InsertOnSubmit(newSurvey)
17 _db.SubmitChanges()
18
19 ‘ Return Results view
20 Return View(“Results”, _db.Surveys)
21 End Function
22
23End Class
因此,在提交表单数据后,有两种方式可以显示结果页。既可以返回RedirectToAction(),也可以返回View()。究竟哪种更好一些呢?
\n
当你调用RedirectToAction()时,ASP.NET MVC框架会导致Web浏览器产生一个新的重定向。RedirectToAction()方法向浏览器返回一个302 – Object Moved状态。然后浏览器会获取Results视图。
\n
因此你可能会认为调用RedirectToAction()是一种不好的方式。在调用RedirectToAction()时浏览器会做更多的工作。当浏览器发起新的请求时网络可能会出现错误。实用RedirectToAction()增加了出错的可能性。
\n
然而,有三个很好的原因可以表明RedirectToAction()要优于直接返回一个视图。两个原因是实际的,还有一个哲学上的原因。我们来从实际的原因开始。如果没有做重定向,而用户单击了浏览器的刷新/重新加载按钮,数据库的数据会被提交多于一次。换句话说,如果没有进行重定向,数据库表中可能会出现重复的数据。
\n
现在,很多流行的浏览器会在遇到这种危险情况时向用户发出警告。Microsoft Internet Explorer 7.0提供了如图2所示的警告。因此,相对于过去而言,这种危险情况可能还不是最坏的。
\n
图2 – IE在表单提交后的刷新提出的警告
\n
第二个实际原因与第一个相关。如果你将结果页放在书签/收藏夹中(或通过Email将结果页链接发给朋友),并在之后用书签打开页面,数据操作会在没有提示的情况下发生。这会提交一个没有数据的表单,客户端验证将被忽略,你会得到如图3所示的丑陋页面:
\n
图3 – 使用书签回到结果页
\n
RedirectToAction()优于View()的第三个原因是哲学上的。ASP.NET MVC框架为你的应用程序提供了一个“静态”的界面。不同的URL代表了不同的操作。如果你在New()动作中返回了Results视图,动作和视图之间的这种对应关系就被破坏了。换句话说,在一个“静态”的应用程序中,你看到的视图应该和你在浏览器地址栏中看到的URL地址是对应的。
\n
如果你在提交表单数据后调用了RedirectToAction(),你会在浏览器地址栏中看到Survey/Results这样的地址。如果你在表单提交后调用的是View(),你在浏览器地址栏中看到的地址时Survey/New。由于你看到的是Results页,第一种情形更有意义。浏览器的地址栏应该反映Web应用程序的状态。进行重定向可以保持浏览器和服务器之间的同步。
\n
******** (原著作者的)更新 *********
\n
在Microsoft工作最好的事情就是你周围总是围绕着一群非常聪明的人。在发表了这篇Blog之后,我跑进(以xUnit著称的)Brad Wilson的屋里,他告诉我这个Tip的主题中应用了一个模式。这个模式被称作PRG模式(Post-Redirect-Get模式)。这里是该模式在Wikipedia中的入口:
\n
http://en.wikipedia.org/wiki/Post/Redirect/Get
\n
因此,这篇Tip应该改名叫“在提交表单时使用PRG模式”。
此处下载源代码:http://weblogs.asp.net/blogs/stephenwalther/Downloads/Tip6/Tip6.zip。
来源:http://www.cnblogs.com/AndersLiu/