今天说说一个让我,这个很久没有接触Web开发的人混乱了很久的问题,就是什么时候应该使用Http.Get、Http.Post和返回视图的时候什么时候用return View,什么时候要return Redirect。首先声明一下,本人对于Web编程并不精通,下面的一些解释和看法可能有错误,希望各位看到了的话回复一下,纠正本人的错误同时也别误导了其他人。

好了先说一下这个Http.Get和Http.Post。在一个Controller Action方法上面我们可以通过Attribute声明这个Action的一些属性,比如Authorize属性表示这个方法需要登录(权限)验证,ActionName属性可以重定义这个Action的名字(默认是方法名)。还有一个Attribute标识了这个Action可以接受哪种Http Verb的请求,包括Http.Get、Http.Post、Http.Put、Http.Delete和Http.Head。其中最经常使用到的就是Http.Get和Http.Post两个值。

Http.Get一般来说(基本可以把这个定语去掉)是在请求数据的时候使用的,也就是说这个Action操作只会读取数据并显示到页面上,而不会对数据进行任何修改。他的最大特点就是,用户可以通过指向这个Action的URL就可以直接访问到数据,有点RESTful的味道。对应到我们的ASP.NET MVC 1(以下简称MVC)的项目中,Http.Get用于显示内容的Action上面。比如网站的首页一般都是只需要读取数据并显示的,所以Home/Index的Action都会是Http.Get的。

Http.Post则不同,它是通过页面的Form(表单)Post之后所调用的Action。(注:当然可以通过Form的Method参数指定使用Get或者Post Verb提交。)一般来说,Post之后的页面将会对后台数据进行修改,不论是添加、删除或是修改。相对于Get,Post方法是无法直接通过浏览器的URL进行访问的,只有通过特定的网页进行提交才能执行,所以相对于Get,Post的安全性也稍微高些。(注:仍旧可以通过Mock表单来进行伪造的提交,但是MVC为我们提供了一个防范措施。)对应到MVC的项目,对于数据的修改操作则都会通过Post Action进行操作。

在新建一个MVC项目之后,AccountController中就有相似的操作。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
public ActionResult Register()
{
 
    ViewData["PasswordLength"] = MembershipService.MinPasswordLength;
 
    return View();
}
 
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Register(string userName, string email, string password, string confirmPassword)
{
 
    ViewData["PasswordLength"] = MembershipService.MinPasswordLength;
 
    if (ValidateRegistration(userName, email, password, confirmPassword))
    {
        // Attempt to register the user
        MembershipCreateStatus createStatus = MembershipService.CreateUser(userName, password, email);
 
        if (createStatus == MembershipCreateStatus.Success)
        {
            FormsAuth.SignIn(userName, false /* createPersistentCookie */);
            return RedirectToAction("Index", "Home");
        }
        else
        {
            ModelState.AddModelError("_FORM", ErrorCodeToString(createStatus));
        }
    }
 
    // If we got this far, something failed, redisplay form
    return View();
}

上面的代码显示了“注册”逻辑。第一个Action没有显式声明AcceptVerb则表示它接受Http.Get的请求,只是简单的显示一个页面。而第二个Action则声明了Http.Post属性,它会在用户点击了注册页面的Submit按钮提交表单后运行,检查数据正确后将新的用户插入数据库(如果后台使用数据库保存数据的话)然后返回首页(Homt/Index)。

所以对于Http.Get和Http.Post,可以简单的认为,如果这个Action有修改数据的操作则要使用Http.Post,否则就可以使用Http.Get。

在第二个Register函数中,可以看到使用了两种不用的方法来返回视图(View)。一个是return RedirectToAction,注册成功之后返回首页的。另一个是末尾的return View,在注册失败(可能是检查未通过,也可能是添加数据的时候出错)的时候返回当前的注册页面并显示错误信息的。那么问题是,这两种返回试图的方法究竟应该在什么时候调用呢?

对于return View,MVC框架不会发起一个新的Http请求(这一点有待考证),所以在Http.Get Action中使用。而且,在Post方法中当数据修改失败需要返回当前页面并显示错误信息的时候也会使用,这样视图表单中数据的数据将会保留,而且View中的ModelState信息等也都会保留。而对于return Redirect,无论是直接Redirect方法还是RedirectToAction方法,都会重新发起一个Http请求并且清楚所有的表单信息和ModelState信息,一般都是在Post方法中修改数据成功后返回列表页面(或者结果页面)的时候使用。比如上面这个Action,注册成功之后将会通过一个新的Http请求执行Home Contrller的Index Action来显示首页。

而且由于return View方法没有发起新的Http请求,如果在Post Action中返回了别的视图,则有可能造成URL和View不匹配的情况。比如我们将上面的return RedirectToAction方法修改为return View("LogOn")来直接返回登录页面,则会看到如下的情形。URL显示的是Account/Register但是现实的页面却是LogOn,这一点和MVC中“一个URL对应唯一的页面”也是不相符合的。在这种情况下,如果用户复制了URL并且发送给别的人,那么他在打开这个URL的时候所看到的页面并不是你现在所看到的。这也损失了MVC的一大优点,就是可以通过URL将你所见到的页面分发给别人。Capture1

而且,如果在这种情形下按了浏览器的刷新按钮(F5),你还会发现浏览器给你提示了一个消息。首先说明一下当按了刷新按钮之后发生了什么。由于我们在Post Action中直接使用return View返回试图,浏览器不会认为这是一个新的Http请求,所提交的表单信息都存在于Http请求里面,所以当刷新本页面的时候,浏览器将会把表单信息再次提交给服务器,实质上是出现了重复提交。而这个消息框是浏览器发现相同的表单被重复请求了两次而特别加上的确认信息,用来防止重复提交的。这个技术不是TCP/IP协议或者HTTP提供的,而是现代浏览器提供的。这种现象也是我们在做MVC的时候应该避免的,而根源就在于使用了错误视图返回方式。正确的做法是通过return Redirect重定向到结果页面,或者显示结果的Action上,然后交由这个页面或Action进行视图展示。这种方法,一些人称之为Web开发的PRG模式(Post – Redirect - Get)。

image

总结一下,Http.Get Verb用于只读取数据并显示的Action上;Http.Post Verb则用于需要对数据库进行修改的Action上。return View方法不会发起新的Http请求,所以只是用户Get Action中用来返回结果,或者Post Action中返回当前页面并显示错误信息。而return Redirect方法将会重定向到一个URL或者Action上面并且会发起新的Http请求,所以只会用于Post Action中数据修改完毕返回结果页面时。

在实际开发中,可能会遇到Get Action显示的页面有一些逻辑,需要从数据库取,然后通过ViewModel传递给视图显示的情况。不像上面例子里面那么简单的LogOn Action。在对应Post方法失败返回当前页的时候,简单使用return View就不行了,因为这个View是需要一些ViewModel支持的。一个方法是在Post Action里面,return View之前进行和Get方法一样的数据读取操作,然后通过return View(model)来显示视图。或者,可以直接调用Get Action这个函数(注意是调用函数而不是调用Action),这样执行Action函数的数据读取操作然后return View(model)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
[AcceptVerbs(HttpVerbs.Get)]
public ActionResult MyAction()
{
    object viewModel = new object();
    return View(viewModel);
}
 
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult MyAction(object args)
{
    var validationResult = false;
    // some validation code
    // ...
    if (validationResult)
    {
        // update the data
        return RedirectToAction("Index");
    }
    else
    {
        return MyAction();
    }
}
posted @ 2009-09-04 11:46 妖居 阅读(5369) 评论(6) 推荐(1) 编辑
摘要: 自从微软推出了ASP.NET MVC 1.0(此后简称MVC)这个新的网站框架之后,出现了一大批解读MVC的文章。拜读了老赵、AnyTao的一些文章,受益匪浅。本人自然没有这些大牛的实力,也不敢班门弄斧的进行所谓的深度剖析。自己的一个项目目前正在使用MVC,自然会有一些对应的代码和小窍门,于是规整了一下发表出来。一是可以让大家在使用MVC的时候有个捷径,二是自己总结,三是看看大家有什么看法和建议。... 阅读全文
posted @ 2009-09-01 13:45 妖居 阅读(1006) 评论(1) 推荐(0) 编辑
摘要: There are so many reason when we've to migrate our base-end database from MsSql to MySql. But I think the most one is the price. Since MySql is NOT free if you do not use it to develop a software under the GPL, but the cost of using MySql is much lower than MsSql. This is the same situation I've just met. There are many diffrences between MsSql and MySql so we need spend more time to investigate, research and trail migration. 阅读全文
posted @ 2007-09-18 15:40 妖居 阅读(1722) 评论(0) 推荐(0) 编辑
摘要: Windows Workflow Foundation(以下简称WWF)为我们提供了一种定义工作流的方式,依靠Visual Studio Orcas Beta 1(以下简称VS9),可以通过图形界面定义一个业务的工作流程,进而在代码页实现工作流的工作细节。使用工作流的时候只需要简单的启动这个流程就可以了。如果工作流发生了变化,那么只需要修改工作流Project里面的流程或者实现,对于工作流的使用者来说不用修改代码。 阅读全文
posted @ 2007-06-28 11:18 妖居 阅读(3895) 评论(6) 推荐(0) 编辑
摘要: 在Artech的我的WCF之旅(6)文章中向我们介绍了Windows Application在使用Duplex Service的时候,会出现Deadlock。并且Artech还想我们介绍了两种解决办法:使用IsOneWay修饰Service Contract Operator;在Client端使用新的线程调用Service的Method。本文继续考虑这个问题的解决方法,在Service和Clien... 阅读全文
posted @ 2007-06-21 17:13 妖居 阅读(2337) 评论(3) 推荐(0) 编辑
摘要: 1、 将字节数组转化为数值public static int ConvertBytesToInt(byte[] arrByte, int offset){ return BitConverter.ToInt32(arrByte, offset);}2、 将数值转化为字节数组第二个参数设置是不是需要把得到的字节数组反转,因为Windows操作系统中整形的高低位是反转转之后保存的。public sta... 阅读全文
posted @ 2007-06-15 09:40 妖居 阅读(5172) 评论(1) 推荐(0) 编辑
摘要: 发布一个小软件。可以编辑固定长、CSV文件的表格化编辑器。所谓固定长文件,就是由若干固定长度的Record组成的文件,一个Record里面的项目按照字节的位置进行划分。项目内容可以是字符串、数字或二进制数值。CSV文件就不多说了。具体的功能,请访问iMatrixitor发布专用页。由于是个人制作的小软件,所以没有经过全面的测试。同样由于是个人在业余时间制作的小软件,所以未注册的版本屏蔽了保存、打印... 阅读全文
posted @ 2007-06-07 22:51 妖居 阅读(3708) 评论(2) 推荐(0) 编辑
摘要: 面向下一代的Visual Studio,Visual Basic和C#语言都有了相应的改进。其中最为主要的就是LINQ(Language Integrated Query)的引入。简单来说,LINQ就是把查询语言整合到了代码当中,而且将查询的对象从数据库扩展到所有的可迭代的任何数据结构上面。 本文主要翻译了Microsoft .NET LINQ Preview (May 2006)里面的《Getting Started With LINQ in Visual Basic》这篇文章。原文包含15部分,本译文删除掉了前面的“Introduction”以及后面的“Additional samples”两部分。同时加入了译者在翻译的同时发现的一些问题以及自己的一些想法。 本人很少翻译文章,而且LINQ目前来讲算是比较前沿的技术,在很多的名词和句子方面组织的还不够好,有的译法还欠推敲。译注里面的一些观点只是本人学习中的一些想法,只代表个人观点。希望大家多提意见。 阅读全文
posted @ 2007-02-13 16:14 妖居 阅读(2612) 评论(9) 推荐(0) 编辑
摘要: 插件功能给软件的使用者可以扩充软件功能的机会。我们不可能让软件适用于所有人,也不是所有的人都会出资帮助你实现他们的需求。插件功能提供了一个软件的高度可扩充性,允许用户作为软件的二次开发者,继续完善软件的功能。 本文通过模仿Visual Studio .Net Addin的实现方法来实现一个提供插件功能的软件。包括提供插件的软件制作、插件的制作一个相关的技术知识。 阅读全文
posted @ 2007-01-08 17:28 妖居 阅读(3314) 评论(18) 推荐(0) 编辑
摘要: DataGridView虽然好用,但是如果数据量比较大的话就会出现性能的问题。网上提供的一般做法是通过虚拟模式(Virtual Mode)来加速。但是有的时候,可以通过简单的设置来加速DataGridView。(1)使用绑定数据。就是通过加载DataTable然后通过BindingSource来和DataGridView.DataSource进行交互。(2)不要使用AutoSizeColumnsM... 阅读全文
posted @ 2006-12-12 10:47 妖居 阅读(2786) 评论(3) 推荐(0) 编辑
点击右上角即可分享
微信分享提示