【问题标题】:URLs with slash in parameter?参数中带有斜杠的 URL?
【发布时间】:2011-09-13 19:07:24
【问题描述】:

问题:

我正在创建一个 wiki 软件,基本上是 wikipedia/mediawiki 的克隆,但在 ASP.NET MVC 中(MVC 是重点,所以不推荐我使用ScrewTurn)。

现在我有一个问题:

我使用此路由映射来路由如下 URL:
http://en.wikipedia.org/wiki/ASP.NET

        routes.MapRoute(
            "Wiki", // Routenname
            //"{controller}/{action}/{id}", // URL mit Parametern
            "wiki/{id}", // URL mit Parametern
            new { controller = "Wiki", action = "dbLookup", id = UrlParameter.Optional } // Parameterstandardwerte
        );

现在我突然想到,可能会有像“AS/400”这样的标题:
http://en.wikipedia.org/wiki/AS/400

顺便说一句,还有这个(标题'Slash'):
http://en.wikipedia.org/wiki//

还有这个:
http://en.wikipedia.org/wiki//dev/null

总的来说,维基百科似乎有一个有趣的标题列表,如下所示: http://en.wikipedia.org/wiki/Wikipedia:Articles_with_slashes_in_title

如何正确地制作类似这条路线的路线?

编辑:
类似的东西:
如果 URL 以 /Wiki/ 开头,并且不以 /wiki/Edit/ 开头 (但不是 /Wiki/Edit) 然后将 URL 的所有其余部分作为 Id 传递。

编辑:
嗯,又是一个问题: 我该如何路由这个:
http://en.wikipedia.org/wiki/C&A

维基百科可以...

编辑:
根据 wikipedia,由于与 wikitext 语法冲突,只有以下字符不能用于页面标题(DISPLAYTITLE 也不支持):

# < > [ ] | { }

http://en.wikipedia.org/wiki/Wikipedia:Naming_conventions_(technical_restrictions)#Forbidden_characters

编辑:
要允许 * 和 &,放

<httpRuntime requestPathInvalidCharacters="" />

进入文件 web.config 中的 部分

(在这里找到:http://www.christophercrooker.com/use-any-characters-you-want-in-your-urls-with-aspnet-4-and-iis

【问题讨论】:

  • 您能否将您的路由参数字符更改为“更常见”的字符,例如问号或逗号...标题中的某些内容无效?
  • ASP.NET MVC 路由不是您唯一的问题。尝试“LPT”、“SQL*plus”、“US$”、“C#”等主题。其中很多会被 IIS 捕获。你最好考虑逃离其中的一些。

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


【解决方案1】:

您可以使用包罗万象的路由将 URL 的 wiki 部分之后的所有内容捕获到 id 令牌中:

routes.MapRoute(
    "Wiki",
    "wiki/{*id}",
     new { controller = "Wiki", action = "DbLookup", id = UrlParameter.Optional }
);

现在,如果您有以下请求:/wiki/AS/400,它将映射到 Wiki 控制器上的以下操作:

public ActionResult DbLookup(string id)
{
    // id will equal AS/400 here
    ...
}

/wiki// 而言,我相信在此请求到达 ASP.NET 管道之前,您会从 Web 服务器收到 400 Bad Request 错误。您可以查看following blog post

【讨论】:

  • 很好,这行得通,但是当我想从这条规则中排除 /wiki/Edit/ArticleTitle 时呢? (但不应例外 /wiki/Edit)
  • @Quandary,我认为你不能用一个包罗万象的规则来豁免。您可以尝试定义另一条路线之前我展示的路线看起来像这样wiki/Edit/{*id}
  • @Darin:好的,效果很好。在 Edit 中,这需要捕获 id isnullorempty 并重定向到 id 为 Edit 的 action action dbLookup。
  • @Darin:如果在编辑操作中,我执行 if (string.IsNullOrEmpty(id)) return RedirectToAction("dbLookup", "Wiki", new { id = "Edit" });然后我进入一个无限循环......为什么?
  • @Quandary,我猜RedirectToAction("dbLookup", "Wiki", new { id = "Edit" }) 再次解析为编辑操作。
【解决方案2】:

@Darin:嗯,这很明显,问题是:为什么?控制器 + action + id 被给出,就好像它再次将所有这些传递给路由...... – Quandary 2011-06-13 17:38:37

Quandry - 也许你已经知道这一点,因为你的问题已经超过一年了,但是当你调用 RedirectToAction 时,你实际上是在向浏览器发送 HTTP 302 响应,这会导致浏览器向指定的操作发出 GET 请求。因此,您看到的是无限循环。

见:Controller.RedirectToAction Method

【讨论】:

【解决方案3】:

在 mvc 中的 Attribute Routing 中,我遇到了同样的问题,在 HttpGet 中的字符串 abc/cde 中存在 /

        [Route("verifytoken/{*token}")]
        [AllowAnonymous]
        [HttpGet]
        public ActionResult VerifyToken(string token)
        {
          //logic here
        }

所以你必须放置*,因为在此之后它将被视为参数

【讨论】:

  • 太棒了。这是最好和最简单的解决方案:)
  • 这似乎适用于一个斜线,但不是连续两个。有什么想法吗?
  • @Usman 如果你有另一条路线是 [Route("verifytoken/{token}/something")] 怎么办?如果有正斜杠,通配符不会与这条路线发生冲突吗?对于这个用例,还有其他方法可以做到这一点吗?
  • 你是英雄!我试图创建一个带有斜线的自定义 url,但没有任何运气,无论我尝试什么,我都得到 /Admin/Customers/Edit?id=1 而不是所需的输出 /Admin/Customers/Edit/1。那个星号成功了!再次感谢
  • 很好的答案。它也适用于 HttpMethodAttribute 。 (.net core 3.1) [HttpGet("verifytoken/{*token}")] 它也适用于多个斜线。例如:localhost:44352/api/verifytoken/1234/12/23/rebase.pdf token = "1234/12/23/rebase.pdf"
【解决方案4】:

仍然可以选择写入文件 Global.asax:

 var uri = Context.Request.Url.ToString();
        if (UriHasRedundantSlashes(uri))
        {
            var correctUri = RemoveRedundantSlashes(uri);
            Response.RedirectPermanent(correctUri);
        }
    }

    private string RemoveRedundantSlashes(string uri)
    {
        const string http = "http://";
        const string https = "https://";
        string prefix = string.Empty;

        if (uri.Contains(http))
        {
            uri = uri.Replace(http, string.Empty);
            prefix = http;
        }
        else if (uri.Contains(https))
        {
            uri = uri.Replace(https, string.Empty);
            prefix = https;
        }

        while (uri.Contains("//"))
        {
            uri = uri.Replace("//", "/");
        }

        if (!string.IsNullOrEmpty(prefix))
        {
            return prefix + uri;
        }
        return uri;
    }

    private bool UriHasRedundantSlashes(string uri)
    {
        const string http = "http://";
        const string https = "https://";

        if (uri.Contains(http))
        {
            uri = uri.Replace(http, string.Empty);
        }
        else if (uri.Contains(https))
        {
            uri = uri.Replace(https, string.Empty);
        }
        return uri.Contains("//");
    }

【讨论】:

    猜你喜欢
    • 2015-09-07
    • 1970-01-01
    • 2011-12-14
    • 2012-04-22
    • 2015-03-06
    • 2012-11-16
    • 2014-10-15
    • 1970-01-01
    相关资源
    最近更新 更多