使用和不使用查询字符串路由旧请求

时间:2012-02-06 15:54:41

标签: asp.net-mvc-3 asp.net-mvc-routing

(开始之前:我知道thisthis。我想找到一个更简洁的解决方案 - 如果可能的话 - 更具体的问题)

我正在重写MVC中的旧Webforms应用程序。像往常一样,不应该破坏永久链接。

我正在使用标准的{controller}/{action}/{id}路线。旧版路径通常为SomePage.aspx?ID=xxx,我有一个特殊情况,其中Foo.aspxBar的列表(新网址: /栏 /栏/索引)和  Foo.aspx?ID=xxxBar详细信息(新网址: / 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();
}

这有两个问题:

  • 现在,如果我创建一个ActionLink,它将使用旧格式
  • 我想在路线上处理这件事;使id可以为空并在控制器中重定向是错误的

我可以手动映射遗留URL(我不需要通用解决方案,只有大约8页)

这是一个新项目,所以我没有任何关系。

2 个答案:

答案 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。但是,如果你确实发现了这一点,我非常想知道。

希望这有帮助。