开发者

URLs with slash in parameter?

Question:

I am creating a wiki software, basically a clone of wikipedia/mediawiki, but in ASP.NET MVC (the MVC is the point, so don't recommend me ScrewTurn).

Now I have a question:

I use this route mapping, to route a URL like:

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
        );

Now it just occured to me, that there migh开发者_开发百科t be titles like 'AS/400':

http://en.wikipedia.org/wiki/AS/400

Incidentially, there is also this one (title 'Slash'):

http://en.wikipedia.org/wiki//

And this one:

http://en.wikipedia.org/wiki//dev/null

Overall, Wikipedia seems to have a list of interesting titles like this: http://en.wikipedia.org/wiki/Wikipedia:Articles_with_slashes_in_title

How do I make routes like this route correctly ?

Edit:

Something like:

If the URL starts with /Wiki/, and if it doesn't start with /wiki/Edit/ (but not /Wiki/Edit) then pass all the rest of the URL as Id.

Edit:

Hmm, just another problem: How can I route this one:

http://en.wikipedia.org/wiki/C&A

Wikipedia can...

Edit:

According to wikipedia, due to clashes with wikitext syntax, only the following characters can never be used in page titles (nor are they supported by DISPLAYTITLE):

# < > [ ] | { }

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

Edit:

To allow * and &, put

<httpRuntime requestPathInvalidCharacters="" />

into section <system.web> in file web.config

(Found here: http://www.christophercrooker.com/use-any-characters-you-want-in-your-urls-with-aspnet-4-and-iis)


You could use a catchall route to capture everything that follows the wiki part of the url into the id token:

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

Now if you have the following request: /wiki/AS/400 it will map to the following action on the Wiki controller:

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

As far as /wiki// is concerned I believe you will get a 400 Bad Request error from the web server before this request ever reaches the ASP.NET pipeline. You may checkout the following blog post.


in Attribute Routing in mvc i had the same problem having / in string abc/cde in HttpGet

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

so you have to place * because after this it will be considered as parameter


@Darin: Well, that much is obvious, the question is: Why ? controller + action + id are given, it's like it's passing all these to routing again... – Quandary Jun 13 '11 at 17:38

Quandry - maybe you have already figured this out since your question is over a year old, but when you call RedirectToAction, you are actually sending an HTTP 302 response to the browser, which causes the browser to make a GET request to the specified action. Hence, the infinite loop you are seeing.

See: Controller.RedirectToAction Method


Still as an option write in the file 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("//");
    }
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜