RedirectToRoute引起了重定向循环

8
public ActionResult Logout()
{
    FormsAuthentication.SignOut();
    return RedirectToRoute("Home");
}

我希望这个操作能将用户重定向到主页,但实际上,出现了一个重定向循环(根据Chrome的显示)。

上述操作属于“admin”区域中的控制器,而“Home”路由是为默认区域定义的 - 我认为这很相关。

以下是路由信息:

routes.MapRoute(
    "Home",
    "{controller}/{action}/{slug}",
    new { controller = "Posts", action = "Index", slug = UrlParameter.Optional },
    new[] { "GoBlog.Controllers" }
);

更新

return语句替换为以下内容,将使操作按预期工作:

return RedirectToRoute("Home", (RouteTable.Routes["Home"] as Route).Defaults);

我想知道为什么会出现这种情况。理想情况下,我可以省略(繁琐的)第二个参数。


无法确定authService.Logout()的作用,但它可能会调用Logout()函数。 - Andrew Ngo
RoutesConfig.cs 中展示你配置的路由。 - haim770
@haim770 感谢您的评论。已完成。 - Caster Troy
你的“Logout”操作在Posts控制器中吗? - Grundy
@usr 我现在就去做。 - Caster Troy
显示剩余7条评论
3个回答

5
这个问题特别针对于调用RedirectToRoute(string)和你的特定路由:
routes.MapRoute(
    "Home",
    "{controller}/{action}/{slug}",
    new { controller = "Posts", action = "Index", slug = UrlParameter.Optional },
    new[] { "GoBlog.Controllers" }
);

您期望的是RedirectToRoute会填充任意路由定义{controller}/{action}/中已定义的默认值:
controller = "Posts", action = "Index"

但是,像所有重定向方法一样,RedirectToRoute 是您的控制器的一部分,并在可能的情况下使用您的当前控制器和操作作为默认值。这是ASP.NET MVC框架的一个“特性”——重用路由来创建新的路由。这种方法很有价值,因为您当前的控制器和操作是您意图的强烈提示。

一个很好的例子是RedirectToAction(string),它假设您当前实例化的控制器是默认的。

与此形成对比的是:

return RedirectToRoute("Home", (RouteTable.Routes["Home"] as Route).Defaults);

与其让框架猜测如何填充模糊的通配符路由,您明确指示框架使用“首页”路由在 RouteTable 中的默认值构建一个路由对象并返回。

3
当您调用 RedirectToRoute(string)时,

此方法使用 RouteCollection.GetVirtualPath方法将传递给routeName的路由名称转换为URL。

其中将null作为RouteValueDictionary参数传递。因此,在这种情况下,这些参数是从当前的RequestContext中获取的,包括controller, action等的值,即您会得到类似以下的URL:
"{controller}/{action}/{slug}"
"Login/Logout/"

并且得到了重定向循环。

当您调用

return RedirectToRoute("Home", (RouteTable.Routes["Home"] as Route).Defaults);

请使用RedirectToRoute(String, RouteValueDictionary)代替RedirectToRoute(string),在RouteCollection.GetVirtualPath方法中为该路由传递默认值。


谢谢。是你的回答和usr的评论的融合给了我解决方案:定义一个更具体的路由。我将在几天内不标记答案地离开这个问题。你的答案似乎是正确的,但它并不是自给自足的,因为它读起来相当糟糕。我想等待看看是否有人可以发布一个更连贯的答案。 - Caster Troy

2
在MVC中,一个普遍的最佳实践是尽量让你的控制器有更多的控制权。你可以使用多个控制器方法,通常应该使用与你正在执行的过程最接近的方法。
  • return View(). 告诉控制器生成并返回指定的HTML,类似于Server.Transfer()。 在匹配HTML与操作或在传递静态HTML时使用,而不关心URL字符串。

  • Return RedirectToAction(). 告诉控制器基于操作构建新的URL字符串。这将解析路由字典以获取操作,并处理默认值。 它作为Response.Redirect(),并将返回一个新生成的URL。 一般来说,这是最常用的重定向。 这也有一个好处,即如果路由字典更改,它也不会改变。

  • return RedirectToRoute(). 类似于RedirectToAction(),但与路由字典相关联。 它将搜索路由字典以获取精确的路由匹配,使用传递的任何路由参数。 它不会查找操作,因此不会构建路由或注入默认值。 当必须处理具有特定非默认值的精确路由时使用。

  • return Redirect(). 此重定向需要完整的URL,并将重定向到新的URL。 通常在重定向到完全不同域的URL时使用。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接