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

Posted

技术标签:

【中文标题】使用和不使用查询字符串路由遗留请求【英文标题】:Routing legacy requests with and without querystring 【发布时间】:2012-02-28 02:15:25 【问题描述】:

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

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

我正在使用标准的controller/action/id 路由。旧路径通常是SomePage.aspx?ID=xxx,我有一个特殊情况,Foo.aspxBar 的列表(新 URL:/Bar/Bar/Index ) 和 Foo.aspx?ID=xxxBar 详细信息(新 URL:/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 页)

这是一个新项目,所以我不依赖任何东西。

【问题讨论】:

【参考方案1】:

我相信如果您指定以下路线:

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 在操作中是否为空。但是,如果你真的发现了这一点,我非常想知道。

希望这会有所帮助。

【讨论】:

【参考方案2】:

我能够基于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);
    

【讨论】:

Diego 很好的答案,但你不知道如何拒绝网址“Bar/View/3”而不是“Bar/View?id=3”? @DenisAgarev 我不明白你的问题。 抱歉不清楚,我在问题上犯了错误)))我​​的意思是有一种方法只允许查询字符串 URL 像“Bar/View?id=3”,因为在你的解决方案 URL 中像“酒吧/视图/任何东西”也将被允许用于相同的路线。 一切皆有可能。但这将是一个不同的问题

以上是关于使用和不使用查询字符串路由遗留请求的主要内容,如果未能解决你的问题,请参考以下文章

使用查询字符串在新服务器上重定向的角度路由

如何在我的所有请求查询字符串中包含 JSON webtoken

当foreign_key为字符串时遗留数据的rails关联

Express起步 - 路由基础 - 请求对象request - 响应对象response - 增删改查API案例

Laravel 路由:使用 URL 查询字符串时如何路由?

play使用起来