Redirect和RedirectToAction之间的混淆

Twe*_*eZz 13 asp.net-mvc

我正在攻读MS证书(70-515).
我对在网上发现的内容和练习测试中的内容感到困惑.
关于SO的一些问题表明使用RedirectToAction正在向浏览器发送302,从而导致它在地址栏中更改它的url.

但这是一个练习测试的问题:

题:

MVC Home控制器目前只有默认的Index操作.相关代码显示在以下代码示例中.

public ActionResult Index()
{
    ViewData["Message"] = "Hello!";
    return View();
}
Run Code Online (Sandbox Code Playgroud)

您需要创建一个名为FindID的操作,该操作显示作为路径一部分输入的ID参数.如果路径不包含ID参数,则ASP.NET必须处理Index操作而不更改浏览器地址栏中的URL,并且不得抛出异常.您应该使用哪个代码段?

正确答案:

public ActionResult FindID(int? id)
{
    if (!id.HasValue)
        return RedirectToAction("Index");
    ViewData["Message"] = "ID is " + id.ToString();
    return View();
}
Run Code Online (Sandbox Code Playgroud)

说明:

您可以使用ActionResult的RedirectToAction形式使MVC处理动作中的不同操作.MVC放弃当前操作并处理请求,就像路由直接导致您重定向到的操作一样.实质上,这相当于在标准ASP.NET应用程序中调用Server.Transfer.

Redirect ActionResult向浏览器发送"HTTP Error 302 - Found"响应,这会导致浏览器加载指定的URL.这会更改地址栏中显示的地址.

所以:
- RedirectToAction是否保持浏览器中的URL不变?
- 重定向是否更改了浏览器中的URL?
- 练习测试的解释是否正确?据我所知,RedirectToAction不会做302.

Ben*_*ter 10

您可以使用ActionResult的RedirectToAction形式使MVC处理动作中的不同操作.MVC放弃当前操作并处理请求,就像路由直接导致您重定向到的操作一样.实质上,这相当于在标准ASP.NET应用程序中调用Server.Transfer.

这是不正确的.

两者RedirectToRouteResult(RedirectToAction)和RedirectResult执行302重定向,从而导致在浏览器中变更的URL.

要在不更改url的情况下返回Index结果,代码实际上是:

public ActionResult FindID(int? id)
{
    if (!id.HasValue)
        return View("index");
    ViewData["Message"] = "ID is " + id.ToString();
    return View();
}
Run Code Online (Sandbox Code Playgroud)

但是,我不建议采用这种方法.如果我发出请求mysite.com/products/some-product并且some-product不存在,那么我应该通过相关的状态代码通知用户(对搜索引擎也很重要).

如果您的FindID操作的唯一目的是使用id参数执行某些操作,那么它不应该是可空/可选的.这样,如果未指定ID,则不会调用FindID操作.

  • @Ben afaik,返回Index(); 会做什么索引方法,但然后会尝试FindID视图.这不完全正确,因为我们想要返回Index视图.我想你必须做和Index(); 并返回View("Index"); (2认同)
  • @petho很好地发现了.我已经更新了我的答案.重申一下,你应该**使用Redirect方法. (2认同)

Guf*_*ffa 9

RedirectToAction方法的文档告诉我们它确实发送了302响应:

"返回对浏览器的HTTP 302响应,这会导致浏览器向指定的操作发出GET请求."

检查dll中的代码会发现它确实返回了一个RedirectToRouteResult对象,这会导致重定向,因此文档是正确的:

protected internal virtual RedirectToRouteResult RedirectToAction(string actionName, string controllerName, RouteValueDictionary routeValues) {
  RouteValueDictionary routeValueDictionaries;
  if (this.RouteData == null) {
    routeValueDictionaries = RouteValuesHelpers.MergeRouteValues(actionName, controllerName, null, routeValues, true);
  } else {
    routeValueDictionaries = RouteValuesHelpers.MergeRouteValues(actionName, controllerName, this.RouteData.Values, routeValues, true);
  }
  return new RedirectToRouteResult(routeValueDictionaries);
}
Run Code Online (Sandbox Code Playgroud)

测试问题的正确答案是使用不同的视图:

public ActionResult FindID(int? id) {
  if (!id.HasValue) {
    ViewData["Message"] = "Hello!";
    return View("Index");
  }
  ViewData["Message"] = "ID is " + id.ToString();
  return View();
}
Run Code Online (Sandbox Code Playgroud)

这将使用视图Index,而不是无FindID参数调用返回的视图View().