URL с косой чертой в параметре? - PullRequest
62 голосов
/ 13 июня 2011

Вопрос:

Я создаю программное обеспечение вики, в основном клон 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

Как правильно сделать маршруты, подобные этому маршруту?

Edit: Что-то вроде:Если URL начинается с / Wiki /, и если он не начинается с / Wiki / Edit / (но не / Wiki / Edit), тогда передайте все остальные URL как Id.

Изменить: Хм, просто еще одна проблема: как я могу маршрутизировать этот:http://en.wikipedia.org/wiki/C&A

Википедия может ...

Редактировать: Согласно википедии, из-за столкновений с синтаксисом викитекста, в заголовках страниц нельзя использовать только следующие символы (и они не поддерживаются DISPLAYTITLE):

# < > [ ] | { }

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

Edit: Чтобы разрешить * и &, поместите

<httpRuntime requestPathInvalidCharacters="" />

в разделв файле web.config

(находится здесь: http://www.christophercrooker.com/use-any-characters-you-want-in-your-urls-with-aspnet-4-and-iis)

Ответы [ 4 ]

89 голосов
/ 13 июня 2011

Вы можете использовать универсальный маршрут для захвата всего, что следует за частью wiki URL-адреса, в маркер 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//, я полагаю, что вы получите ошибку 400 Bad Request от веб-сервера еще до того, как этот запрос достигнет конвейера ASP.NET. Вы можете оформить следующую запись в блоге .

13 голосов
/ 13 февраля 2017

в Attribute Routing в MVC у меня была та же проблема, с / в строке abc/cde в HttpGet

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

, поэтому вы должны поместить *, потому что после этого эторассматривается как параметр

5 голосов
/ 23 июня 2012

@ Дарин: Ну, это очевидно, вопрос: почему? контроллер + action + id даны, как будто все это снова передается в маршрутизацию ... - Quandary 13 июня '11 в 17: 38

Quandry - возможно, вы уже поняли это, поскольку вашему вопросу уже более года, но когда вы вызываете RedirectToAction, вы на самом деле отправляете ответ HTTP 302 в браузер, который заставляет браузер сделать запрос GET для указанного действия. Следовательно, бесконечный цикл, который вы видите.

См .: Метод Controller.RedirectToAction

0 голосов
/ 20 марта 2017

Еще как вариант напишите в файле 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("//");
    }
...