URL-адреса с косой чертой в параметре?

Вопрос:

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

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

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


person Stefan Steiger    schedule 13.06.2011    source источник
comment
Можете ли вы изменить свой символ параметра маршрутизации на что-то более обычное, например вопросительный знак или запятую ... что-то НЕ является действительным в заголовке?   -  person corlettk    schedule 13.06.2011
comment
Маршрутизация ASP.NET MVC - не единственная проблема. Попробуйте такие темы, как LPT, SQL * plus, US $, C # и т. Д. Многие из них будут обнаружены IIS. Вам лучше подумать о том, чтобы сбежать от некоторых из них.   -  person Codo    schedule 13.06.2011


Ответы (4)


Вы можете использовать общий маршрут для захвата всего, что следует за частью 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. Вы можете проверить следующее сообщение в блоге.

person Darin Dimitrov    schedule 13.06.2011
comment
Хорошо, это работает, но как насчет того, чтобы исключить / wiki / Edit / ArticleTitle из этого правила? (но это не должно выходить за рамки / wiki / Edit) - person Stefan Steiger; 13.06.2011
comment
@Quandary, я не думаю, что вы могли бы исключить это правило общего доступа. Вы можете попробовать определить другой маршрут перед показанным мной, который выглядит так wiki/Edit/{*id}. - person Darin Dimitrov; 13.06.2011
comment
@Darin: Хорошо, отлично работает. В Edit требуется поймать id isnullorempty и перенаправить на action action dbLookup с id как Edit. - person Stefan Steiger; 13.06.2011
comment
@Darin: если в действии Edit, я выполняю if (string.IsNullOrEmpty (id)) return RedirectToAction (dbLookup, Wiki, new {id = Edit}); тогда я вхожу в бесконечный цикл ... почему? - person Stefan Steiger; 13.06.2011
comment
@Quandary, я полагаю, что RedirectToAction("dbLookup", "Wiki", new { id = "Edit" }) снова разрешает действие Edit. - person Darin Dimitrov; 13.06.2011
comment
@Darin: Ну, это очевидно, вопрос: почему? заданы контроллер + действие + идентификатор, это как будто снова передает все это на маршрутизацию ... - person Stefan Steiger; 13.06.2011
comment
@DarinDimitrov: Это похожий случай, не могли бы вы здесь помочь? stackoverflow.com / questions / 24932519 / - person Daniel Peñalba; 24.07.2014
comment
К сожалению, у меня это работает, за исключением случаев, когда перед косой чертой стоит пробел. Пробел после косой черты или где-либо еще подойдет. К сожалению, мне нужно, чтобы он работал даже с пробелом перед косой чертой. - person Dave; 28.11.2018
comment
@Darin есть ли встроенная поддержка для определения маршрутов, где более чем один параметр маршрута может иметь / в своем значении. Я понимаю, что {* ParameterName} может работать только для последнего параметра и не может использоваться для любого промежуточного параметра в маршруте. Если нет встроенной поддержки, каков наиболее чистый подход для поддержки таких URL-адресов, имеющих несколько параметров с /? Заранее спасибо. - person LearningNeverEnds; 04.07.2019

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

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

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

person Usman    schedule 13.02.2017
comment
классно. это лучшее и простое решение :) - person Emil; 10.10.2018
comment
Кажется, это работает для одной косой черты, но не для двух подряд. есть какие-нибудь идеи? - person nixkuroi; 14.11.2019
comment
@Usman А что, если у вас есть другой маршрут, который называется [Route (verifytoken / {token} / something)]? Не будет ли подстановочный знак потенциально конфликтовать с этим маршрутом, если есть косая черта? Есть ли другой способ сделать это для этого варианта использования? - person Braden Brown; 08.06.2020
comment
Ты герой! Я безуспешно пытался создать настраиваемый URL-адрес с косой чертой, независимо от того, что я пробовал, я получал / Admin / Customers / Edit? Id = 1 вместо желаемого вывода / Admin / Customers / Edit / 1. Эта звездочка сделала свое дело! Еще раз спасибо - person Dimitris Thomas; 19.03.2021

@Darin: Ну, это очевидно, вопрос: почему? Контроллер + действие + идентификатор даны, как будто он снова передает все это на маршрутизацию ... - Quandary 13 июн 2011, в 17:38

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

См. Метод Controller.RedirectToAction

person Adam    schedule 22.06.2012
comment
Server.Transfer решает эту проблему: stackoverflow.com/questions/799511/ - person Stefan Steiger; 17.10.2014

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