ASP.NET MVC Маршрут с тире - PullRequest
4 голосов
/ 15 мая 2009

У меня вопрос о маршрутизации ASP.NET MVC.

Я подготовил следующую таблицу маршрутизации, чтобы отобразить такой URL

МойВебСайт / mycontroller / MyAction / 14-longandprettyseoname

к параметрам:

14 => id (целое число)

longandprettyseoname -> seo_name (строка)

    routes.MapRoute(
        "myname",
        "mycontroller/myaction/{id}-{seo_name}", 
        new { controller = "mycontroller", action = "myaction", id = 0, seo_name = (string)null });

    routes.MapRoute(
        "Default",  
        "{controller}/{action}/{id}",
        new { controller = "Home", action = "Index", id = "" });

Это работает для URL выше, но есть проблемы для следующего типа URL

* / 14-давно и некрасиво-сео имя-1020 * МойВебСайт / mycontroller / MyAction

Можно ли заставить его работать?


EDIT:

"mycontroller/myaction/{seo_name}-{id}"

вроде работает

Ответы [ 5 ]

1 голос
/ 09 февраля 2012

Мое решение - определить маршрут как:

routes.MapRoute("myname","mycontroller/myaction/{id}",  
        new { controller = "mycontroller", action = "myaction"}); 

и разбирать id и seoname вручную, используя Regex в обработчике HTTP:

        var routeData = RouteTable.Routes.GetRouteData(new HttpContextWrapper(context));
        var match = System.Text.RegularExpressions.Regex.Match((string)routeData.Values["id"], @"^(?<id>\d+)-(?<seoname>[\S\s]*)$");
        if (!match.Success)
        {
            context.Response.StatusCode = 400;
            context.Response.StatusDescription = "Bad Request";
            return;
        }

        int id = Int32.Parse(match.Groups["id"].Value);
        string seoname = match.Groups["seoname"].Value;
1 голос
/ 04 июля 2011

Самый очевидный способ сделать это - использовать ограничения.

Поскольку ваш идентификатор является целым числом, вы можете добавить ограничение, которое будет искать целочисленное значение:

new { id = @"\d+" }

и вот весь маршрут:

routes.MapRoute("myname","mycontroller/myaction/{id}-{seo_name}", 
        new { controller = "mycontroller", action = "myaction" }, 
        new { id = @"\d+"});
0 голосов
/ 08 мая 2012

Определите определенный маршрут, такой как:

        routes.MapRoute(
            "TandC", // Route controllerName
            "CommonPath/{controller}/Terms-and-Conditions", // URL with parameters
            new { controller = "Home", action = "Terms_and_Conditions" } // Parameter defaults
        );

Но этот маршрут должен быть зарегистрирован ДО вашего маршрута по умолчанию.

0 голосов
/ 29 сентября 2009

Что вы можете сделать, это создать собственную фабрику контроллеров. Таким образом, вы можете иметь собственный код, чтобы решить, какой контроллер нужно вызывать, когда.

public class CustomControllerFactory : IControllerFactory
    {
        #region IControllerFactory Members

        public IController CreateController(RequestContext requestContext, string controllerName)
        {
            if (string.IsNullOrEmpty(controllerName))
                throw new ArgumentNullException("controllerName");

            //string language = requestContext.HttpContext.Request.Headers["Accept-Language"];
            //can be used to translate controller name and get correct controller even when url is in foreign language

            //format controller name
            controllerName = String.Format("MyNamespace.Controllers.{0}Controller",controllerName.Replace("-","_"));

            IController controller = Activator.CreateInstance(Type.GetType(controllerName)) as IController;
            controller.ActionInvoker = new CustomInvoker(); //only when using custominvoker for actionname rewriting
            return controller;
        }

        public void ReleaseController(IController controller)
        {
            if (controller is IDisposable)
                (controller as IDisposable).Dispose();
            else
                controller = null;
        }

        #endregion
    }

Чтобы использовать этот собственный контроллер, вы должны добавить его в ваш global.asax

protected void Application_Start()
        {
            RegisterRoutes(RouteTable.Routes);
            ControllerBuilder.Current.SetControllerFactory(typeof(CustomControllerFactory));
        }

Обратите внимание, что это работает только для контроллера, а не для действий ... Чтобы подключить пользовательскую перезапись действий до их выполнения, используйте этот код:

public class CustomInvoker : ControllerActionInvoker
{
    #region IActionInvoker Members

    public override bool InvokeAction(ControllerContext controllerContext, string actionName)
    {
        return base.InvokeAction(controllerContext, actionName.Replace("-", "_"));
    }

    #endregion
}

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

Надеюсь, это поможет!

0 голосов
/ 15 мая 2009

Я не думаю, что маршрут будет различим, так как он не сможет определить, на каком "-" разделить, чтобы указать {id} и {seo-name}.

Как насчет использования подчеркивания для вашего SEO имени? Или вы можете просто использовать имя SEO в качестве фактического {id}. Если имя SEO является чем-то уникальным, это очень жизнеспособный вариант, который вы можете использовать в качестве псевдо-первичного ключа для этой записи в вашей БД (при условии, что он что-то извлекает из БД)

Кроме того, используйте отладчик маршрута Фила Хаака , чтобы увидеть, что работает, а что нет.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...