(开始之前:我知道this和this。我想找到一个更简洁的解决方案 - 如果可能的话 - 更具体的问题)
我正在重写MVC中的旧Webforms应用程序。像往常一样,不应该破坏永久链接。
我正在使用标准的{controller}/{action}/{id}
路线。旧版路径通常为SomePage.aspx?ID=xxx
,我有一个特殊情况,其中Foo.aspx
是Bar
的列表(新网址: /栏或 /栏/索引)和
Foo.aspx?ID=xxx
是Bar
详细信息(新网址: / Bar / View / xxx )
一种可能的解决方法是在默认MapRoute
之前添加以下内容:
routes.MapRoute("Bar View", "Foo.aspx",
new { controller = "Bar", action = "View" });
然后在BarController中定义相应的动作:
public ActionResult View(int? id)
{
if (id == null)
return RedirectToAction("Index");
return View();
}
这有两个问题:
我可以手动映射遗留URL(我不需要通用解决方案,只有大约8页)
这是一个新项目,所以我没有任何关系。
答案 0 :(得分:3)
我能够根据Dangerous' idea加上基于this answer的约束来解决这个问题。
我的新路线表是:
routes.MapRoute("Bar", "Bar/{action}/{id}",
new
{
controller = "Bar",
action = "Index",
id = UrlParameter.Optional
});
routes.MapRoute("Bar View", "Foo.aspx",
new {controller = "Bar", action = "View"},
new {id = new QueryStringConstraint()});
routes.MapRoute("Bar Index", "Foo.aspx",
new { controller = "Bar", action = "Index" });
routes.MapRoute("Default", /*...*/);
QueryStringConstraint不会更简单:
public class QueryStringConstraint : IRouteConstraint
{
public bool Match(HttpContextBase httpContext, Route route,
string parameterName, RouteValueDictionary values,
RouteDirection routeDirection)
{
return httpContext.Request.QueryString.AllKeys
.Contains(parameterName, StringComparer.InvariantCultureIgnoreCase);
}
}
答案 1 :(得分:2)
我相信如果您指定以下路线:
routes.MapRoute(
null,
"Bar/{action}/{id}",
new { controller = "Bar", action = "View", id = UrlParameter.Optional },
new { action = "Index|Next" } //contrain route from being used by other action (if required)
);
routes.MapRoute(
null,
"Foo.aspx/{id}",
new { controller = "Bar", action = "View", id = UrlParameter.Optional }
);
//specify other routes here for the other legacy routes you have.
然后这应该解决你的第一个问题。如果用户在URL中指定了Foo.aspx,那么它们将被带到View操作。
如果操作链接:
@Html.ActionLink("Click me", "Index", "Bar")
指定然后将使用第一条路线(因为顺序很重要)。
但是,如果指定了Foo.aspx?id=...
,我无法弄明白如何指定Foo.aspx
然后转到其他路线然后转到另一条路线。因此,我会检查动作中的id是否为null。但是,如果你确实发现了这一点,我非常想知道。
希望这有帮助。