参数中包含斜线的网址?


67

题:

我正在创建一个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

偶然地,还有一个(标题为“斜线”):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中的<system.web>部分

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


您能否将路由参数字符更改为“更常见”的字符,例如问号或逗号...标题中的某些字符无效?
corlettk 2011年

1
ASP.NET MVC路由不是您唯一的问题。尝试使用“ LPT”,“ SQL * plus”,“ US $”,“ C#”等主题。IIS可能会抓住许多主题。您最好考虑转义其中的一些。
Codo

Answers:


102

您可以使用包罗万象的路线来捕获wikiurl中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错误。您可以查看以下博客文章


很好,那行得通,但是当我想从此规则中免除/ wiki / Edit / ArticleTitle怎么办?(但这不应该过份/ wiki / Edit)
Stefan Steiger

3
@Quandary,我认为您不能采用包罗万象的规则。您可以尝试我展示的路线之前定义另一条路线,如下所示wiki/Edit/{*id}
Darin Dimitrov

@Darin:好的,效果很好。在“编辑”中,这要求捕获id为非空值并重定向到ID为“ Edit”的动作dbLookup。
Stefan Steiger

@Darin:如果在“编辑”操作中,我执行了一个if(string.IsNullOrEmpty(id))return RedirectToAction(“ dbLookup”,“ Wiki”,new {id =“ Edit”}); 然后我进入无限循环...为什么?
Stefan Steiger

@Quandary,我想这RedirectToAction("dbLookup", "Wiki", new { id = "Edit" })再次可以解决“编辑”操作。
Darin Dimitrov

25

Attribute RoutingMVC中我/在字符串abc/cde中有同样的问题HttpGet

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

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


2
太棒了 这是最好,最简单的解决方案:)
Emil,

2
这似乎适用于一个斜杠,但不能连续两个。有什么想法吗?
nixkuroi

@Usman如果您还有另一个路由[Route(“ verifytoken / {token} / something”)],该怎么办?如果存在正斜杠,通配符是否可能与此路由存在冲突?对于此用例,还有另一种方法吗?
Braden Brown

5

@Darin:嗯,这很明显,问题是:为什么?给出了控制器+动作+ ID,就好像将所有这些都传递给了路由一样……– 2011年6月13日,Quadary 17:38

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

请参见:Controller.RedirectToAction方法


Server.Transfer的解决了这个:stackoverflow.com/questions/799511/...
斯特凡·斯泰格尔

-3

仍然可以选择将文件写入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("//");
    }
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.