Применение дефисов в структуре URL .NET MVC 4.0 - PullRequest
4 голосов
/ 11 декабря 2011

Я специально ищу способ автоматического переноса действий и представлений CamelCase.То есть я надеюсь, что мне не нужно фактически переименовывать свои представления или добавлять декораторы для каждого ActionResult на сайте.

До сих пор я использовал routes.MapRouteLowercase, как показано здесь .Это хорошо работает для строчной части структуры URL, но не для дефисов.Так что я недавно начал играть с Canonicalize (установить через NuGet), но у него также нет ничего для дефисов.

Я пытался ...

routes.Canonicalize().NoWww().Pattern("([a-z0-9])([A-Z])", "$1-$2").Lowercase().NoTrailingSlash();

Мое регулярное выражение определенно работает так, как я хочу, чтобы правильно реструктурировать URL, но эти URL, конечно, не определены.Файл все еще ChangePassword.cshtml, например, поэтому /account/change-password не собирается указывать на это.

Кстати, я все еще немного заржавел с .NET MVC.Я не пользовался им пару лет, а не начиная с версии 2.0.

Ответы [ 4 ]

3 голосов
/ 03 августа 2013

Я разработал библиотеку NuGet с открытым исходным кодом для этой проблемы, которая неявно преобразует EveryMvc / Url в every-mvc / url.

Прописные URL-адреса проблематичны, потому что пути к файлам cookie чувствительны к регистру, большая часть интернета фактически чувствительна к регистру, а технологии Microsoft рассматривают URL-адреса как регистрозависимые.( Подробнее в моем блоге )

Пакет NuGet: https://www.nuget.org/packages/LowercaseDashedRoute/

Чтобы установить его, просто откройте окно NuGet в Visual Studio, щелкнув правой кнопкой мыши Project ивыберите диспетчер пакетов NuGet и на вкладке «Онлайн» введите «Строчный маршрут со строчными буквами», и он должен появиться.

В качестве альтернативы вы можете запустить этот код в консоли диспетчера пакетов:

Install-Package LowercaseDashedRoute

После этого вы должны открыть App_Start / RouteConfig.cs и закомментировать существующий вызов route.MapRoute (...) и добавить вместо него:

routes.Add(new LowercaseDashedRoute("{controller}/{action}/{id}",
  new RouteValueDictionary(
    new { controller = "Home", action = "Index", id = UrlParameter.Optional }),
    new DashedRouteHandler()
  )
);

Вот и все.Все URL-адреса строчные, пунктирные и неявно преобразуются без каких-либо дополнительных действий.

URL проекта с открытым исходным кодом: https://github.com/AtaS/lowercase-dashed-route

3 голосов
/ 15 декабря 2011

Это может быть немного грязно, но если вы создали пользовательские HttpHandler и RouteHandler , то это должно помешать вам переименовывать все ваши представления и действия.Ваш обработчик может удалить дефис из запрошенного действия, что приведет к изменению «change-password» на changepassword, отображая действие ChangePassword.

Код для краткости сокращен, но есть важные биты.

public void ProcessRequest(HttpContext context)
{
    string controllerId = this.requestContext.RouteData.GetRequiredString("controller");
    string view = this.requestContext.RouteData.GetRequiredString("action");

    view = view.Replace("-", "");
    this.requestContext.RouteData.Values["action"] = view;

    IController controller = null;
    IControllerFactory factory = null;

    try
    {
        factory = ControllerBuilder.Current.GetControllerFactory();
        controller = factory.CreateController(this.requestContext, controllerId);

        if (controller != null)
        {
            controller.Execute(this.requestContext);
        }
    }
    finally
    {
        factory.ReleaseController(controller);
    }
}

Я не знаю, реализовал ли я его наилучшим образом или нет, это просто более или менее принятос первого образца я наткнулся.Я сам протестировал код, так что он отображает правильное действие / представление и должен выполнить свою задачу.

0 голосов
/ 09 октября 2013

Я попробовал решение в принятом ответе выше: используя стратегию URL шаблона Canonicalize Pattern, а затем добавив пользовательский IRouteHandler, который затем возвращает пользовательский IHttpHandler.Это в основном сработало.Вот одна оговорка, которую я нашел:

С типичным {controller}/{action}/{id} маршрутом по умолчанию, контроллером с именем CatalogController и методом действия внутри него:

ActionResult QuickSelect(string id){ /*do some things, access the 'id' parameter*/ }

Я заметил, что запросыв "/ catalog / quick-select / 1234" работал отлично, но запросы к / catalog / quick-select? id = 1234 были 500'ing, потому что как только метод действия был вызван в результате controller.Execute(), idпараметр был нулевым внутри метода действия.

Я не знаю точно, почему это так, но поведение было таким, как если бы MVC не просматривал строку запроса для значений во время привязки модели.Таким образом, что-то в реализации ProcessRequest в принятом ответе приводило к нарушению нормального процесса привязки модели или, по крайней мере, поставщика значения строки запроса.

Это прерыватель сделки, поэтому я взглянул на MVC по умолчаниюIHttpHandler (да, с открытым исходным кодом!): http://aspnetwebstack.codeplex.com/SourceControl/latest#src/System.Web.Mvc/MvcHandler.cs

Я не буду притворяться, что я его уродил целиком, но ясно, что он делает ALOT больше в своей реализации ProcessRequest, чем происходитв принятом ответе.

Итак, если все, что нам действительно нужно сделать, это убрать штрихи из наших входящих данных маршрута, чтобы MVC мог найти наши контроллеры / действия, зачем нам нужно реализовывать вонючий IHttpHandler?Мы не делаем!Просто вырвите штрихи в методе GetHttpHandler из DashedRouteHandler и передайте requestContext из коробки MvcHandler, чтобы он мог использовать свои 252 магические линии, и ваш обработчик маршрута не долженвернуть второй курс IHttpHandler.

tl: dr;- Вот что я сделал:

public class DashedRouteHandler : IRouteHandler
    {
        public IHttpHandler GetHttpHandler(RequestContext requestContext)
        {
            requestContext.RouteData.Values["action"] = requestContext.RouteData.GetRequiredString("action").Replace("-", "");
            requestContext.RouteData.Values["controller"] = requestContext.RouteData.GetRequiredString("controller").Replace("-", "");

            return new MvcHandler(requestContext);
        }
    }
0 голосов
/ 20 декабря 2011

Вы пробовали работать с пакетом перезаписи URL?Я думаю, это в значительной степени то, что вы ищете.

http://www.iis.net/download/urlrewrite

У Гансельмана есть отличный пример. Е:

http://www.hanselman.com/blog/ASPNETMVCAndTheNewIIS7RewriteModule.aspx

Кроме того, почему бы вам не загрузить что-то вроде ReSharper или CodeRush и использовать его для рефакторинга имен Action и Route?Это ДЕЙСТВИТЕЛЬНО просто и очень безопасно.

Было бы хорошо потрачено время и гораздо меньше времени в целом, чтобы исправить ваши соглашения о маршрутизации / именовании действий с часом рефакторинга, чем все часы, которые вы выполняли.Мы уже потратили попытки изменить правила маршрутизации в соответствии с вашими потребностями.

Просто мысль.

...