URLs with slash in parameter?

asp.net Mvcasp.net Mvc-Routing

asp.net Mvc Problem Overview


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

asp.net Mvc Solutions


Solution 1 - asp.net Mvc

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.

Solution 2 - asp.net Mvc

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

Solution 3 - asp.net Mvc

> @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

Solution 4 - asp.net Mvc

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("//");
    }

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionStefan SteigerView Question on Stackoverflow
Solution 1 - asp.net MvcDarin DimitrovView Answer on Stackoverflow
Solution 2 - asp.net MvcUsmanView Answer on Stackoverflow
Solution 3 - asp.net MvcAdamView Answer on Stackoverflow
Solution 4 - asp.net Mvcbobparker58View Answer on Stackoverflow