MVC 奇怪的路由行为
MVC weird routing behaviour
我对 MVC 中的某些路由有一个奇怪的问题。这是我的场景:
- 用户访问网站后会出现在首页:
testproject.com:57416/Home
。
- 用户在左侧有一个菜单,菜单项为 "Solutions"。
- 用户按下菜单项 "Solutions",菜单项展开,显示 5 个子项。
- 用户按下子项“Demo”,并重定向到
testproject.com:57416/Solutions/SetLayout?layoutString=page1%7Csize15
- 由于定义了参数
layoutString
,网格 (DevExpress) 知道如何过滤要显示的数据。
- 网格已呈现给用户,他现在可以在网格中导航,操纵布局。
- 用户现在想再次看到干净的 Demo 布局,他按下菜单项 "Solutions" -> 子项“Demo”。
- 在这种情况下未命中操作
ActionResult SetLayout(string layoutString)
,而是命中了操作 ActionResult Index()
,因此未设置布局,因为 layoutString
未作为参数发送
- 用户被重定向到的 url,如下所示:
testproejct.com:57416/Solutions?undefined=undefined
通读起来可能有点乏味,但这是我解释我的场景的最佳方式,因为我以前从未在 MVC 中见过这样的事情。我真的不知道发生了什么,也不知道为什么 ActionResult SetLayout(string layoutString)
第二次没有命中。
我想我应该展示一些代码,以便我们缩小可能性范围。
_Layout.cshtml(有菜单项)
<li class="has-submenu">
<a href ="#" class="navigation-submenu-toggler show-solution-views">Solutions</a>
<ul class="nav sub-menu-list">
<li>
@Html.ActionLink("Demos", "SetLayout", "Solutions", new { layoutString = "page1|size15" }, null)
</li>
</ul>
</li>
ActionResult SetLayout(string layoutString)
public ActionResult SetLayout(string layoutString)
{
Session["Layout"] = layoutString;
return RedirectToAction("Index", "Solutions");
}
ActionResult Index()
public ActionResult Index ()
{
using(var db = new DataBasecontext())
{
var list = db.Solutions.ToList();
return View(list);
}
}
编辑
我发现只有当我在同一个控制器中时才会发生这种情况。持有动作 ActionResult SetLayout(string layoutString)
的控制器是 SolutionsController
。如果我来自,假设 AccountController
一切正常,但从 SolutionsController
更改为 SolutionsController
中的另一个操作不起作用。
想想看,和我的地图路线有关系吗?
routes.MapRoute(
name: "ControllerIdActionId",
url: "{controller}/{id}/{action}/{id2}",
default : new { id2 = UrlParameter.Optional }
);
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
default : new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
routes.MapRoute(
name: "Solutions",
url: "{controller}/{id}/{action}",
default : new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
似乎 layoutString 参数在其第二次触发时缺少参数值,因此将空字符串值插入到 Session 键中(并且 Javascript 与该 Session 相关的函数将空字符串视为未定义)。
public ActionResult SetLayout(String layoutString)
{
// Test if the string is null or empty before filling session key,
// if it is empty one, leave the session key as is
if (!String.IsNullOrEmpty(layoutString)) {
Session["Layout"] = layoutString;
}
return RedirectToAction("Index", "Solutions");
}
也许这不是最好的方法,我只是从 SetLayout 方法的角度来看,用正确的查询字符串填充 Session 键。
在您的操作链接中将第 5 个参数作为 null 传递,如下所示:
@Html.ActionLink("Demos", "SetLayout", "Solutions", new { layoutString = "page1|size15" },null)
我还没有测试过,但可能是问题所在..
我自己解决了这个问题。
我不太确定问题出在哪里,但是将 Html.ActionLink()
更改为 Html.RouteLink()
我能够定义要使用的 MapRoute
。
我用下面的方法解决了MapRoute
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
)
然后我可以像这样使用 Html.RouteLink
:
Html.Routelink("Demos", //Display text
"Default", //The MapRoute to use
new { layoutString = "page1|size15|", //The param (layoutString)
controller = "Solutions", //The controller
action = "SetLayout" }) //The action
我没有更改操作:
public ActionResult SetLayout(string layoutString)
{
Session["Layout"] = layoutString;
return RedirectToAction("Index", "Solutions");
}
我对 MVC 中的某些路由有一个奇怪的问题。这是我的场景:
- 用户访问网站后会出现在首页:
testproject.com:57416/Home
。 - 用户在左侧有一个菜单,菜单项为 "Solutions"。
- 用户按下菜单项 "Solutions",菜单项展开,显示 5 个子项。
- 用户按下子项“Demo”,并重定向到
testproject.com:57416/Solutions/SetLayout?layoutString=page1%7Csize15
- 由于定义了参数
layoutString
,网格 (DevExpress) 知道如何过滤要显示的数据。 - 网格已呈现给用户,他现在可以在网格中导航,操纵布局。
- 用户现在想再次看到干净的 Demo 布局,他按下菜单项 "Solutions" -> 子项“Demo”。
- 在这种情况下未命中操作
ActionResult SetLayout(string layoutString)
,而是命中了操作ActionResult Index()
,因此未设置布局,因为layoutString
未作为参数发送 - 用户被重定向到的 url,如下所示:
testproejct.com:57416/Solutions?undefined=undefined
通读起来可能有点乏味,但这是我解释我的场景的最佳方式,因为我以前从未在 MVC 中见过这样的事情。我真的不知道发生了什么,也不知道为什么 ActionResult SetLayout(string layoutString)
第二次没有命中。
我想我应该展示一些代码,以便我们缩小可能性范围。
_Layout.cshtml(有菜单项)
<li class="has-submenu">
<a href ="#" class="navigation-submenu-toggler show-solution-views">Solutions</a>
<ul class="nav sub-menu-list">
<li>
@Html.ActionLink("Demos", "SetLayout", "Solutions", new { layoutString = "page1|size15" }, null)
</li>
</ul>
</li>
ActionResult SetLayout(string layoutString)
public ActionResult SetLayout(string layoutString)
{
Session["Layout"] = layoutString;
return RedirectToAction("Index", "Solutions");
}
ActionResult Index()
public ActionResult Index ()
{
using(var db = new DataBasecontext())
{
var list = db.Solutions.ToList();
return View(list);
}
}
编辑
我发现只有当我在同一个控制器中时才会发生这种情况。持有动作 ActionResult SetLayout(string layoutString)
的控制器是 SolutionsController
。如果我来自,假设 AccountController
一切正常,但从 SolutionsController
更改为 SolutionsController
中的另一个操作不起作用。
想想看,和我的地图路线有关系吗?
routes.MapRoute(
name: "ControllerIdActionId",
url: "{controller}/{id}/{action}/{id2}",
default : new { id2 = UrlParameter.Optional }
);
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
default : new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
routes.MapRoute(
name: "Solutions",
url: "{controller}/{id}/{action}",
default : new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
似乎 layoutString 参数在其第二次触发时缺少参数值,因此将空字符串值插入到 Session 键中(并且 Javascript 与该 Session 相关的函数将空字符串视为未定义)。
public ActionResult SetLayout(String layoutString)
{
// Test if the string is null or empty before filling session key,
// if it is empty one, leave the session key as is
if (!String.IsNullOrEmpty(layoutString)) {
Session["Layout"] = layoutString;
}
return RedirectToAction("Index", "Solutions");
}
也许这不是最好的方法,我只是从 SetLayout 方法的角度来看,用正确的查询字符串填充 Session 键。
在您的操作链接中将第 5 个参数作为 null 传递,如下所示:
@Html.ActionLink("Demos", "SetLayout", "Solutions", new { layoutString = "page1|size15" },null)
我还没有测试过,但可能是问题所在..
我自己解决了这个问题。
我不太确定问题出在哪里,但是将 Html.ActionLink()
更改为 Html.RouteLink()
我能够定义要使用的 MapRoute
。
我用下面的方法解决了MapRoute
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
)
然后我可以像这样使用 Html.RouteLink
:
Html.Routelink("Demos", //Display text
"Default", //The MapRoute to use
new { layoutString = "page1|size15|", //The param (layoutString)
controller = "Solutions", //The controller
action = "SetLayout" }) //The action
我没有更改操作:
public ActionResult SetLayout(string layoutString)
{
Session["Layout"] = layoutString;
return RedirectToAction("Index", "Solutions");
}