ASP.NET MVC Route with dash

时间:2009-05-15 12:19:03

标签: asp.net-mvc

我有ASP.NET MVC路由问题。

我准备了以下路由表来映射这样的URL

  

mywebsite / myController的/ myaction / 14-longandprettyseoname

参数:

  

14 => id(整数)

     

longandprettyseoname - > seo_name(string)

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

它适用于上面的网址,但它有以下类型的网址

的问题
  

mywebsite / myController的/ myaction / 14长和相当-SEO-名称

这有可能使它有效吗?


修改

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

似乎正在运作

5 个答案:

答案 0 :(得分:1)

最明显的方法是使用约束。

由于您的id是一个整数,您可以添加一个约束来查找整数值:

new { id = @"\d+" }

这是整个路线:

routes.MapRoute("myname","mycontroller/myaction/{id}-{seo_name}", 
        new { controller = "mycontroller", action = "myaction" }, 
        new { id = @"\d+"});

答案 1 :(得分:1)

我的解决方案是将路线定义为:

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

并在HTTP处理程序中使用Regex解析id和seoname:

        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;

答案 2 :(得分:0)

我不认为该路线是可区分的,因为它无法确定要分割哪个“ - ”以指定{id}{seo-name}

如何使用下划线作为您的SEO名称?或者您可以使用SEO名称作为实际{id}。如果SEO名称是唯一的,那么这是一个非常可行的选项,您可以将其用作数据库中该条目的伪主键(假设它从数据库中提取内容)

另外,利用Phil Haack的route debugger来查看哪些有效且无效。

答案 3 :(得分:0)

您可以做的是创建自定义控制器工厂。这样,您就可以使用自定义代码来决定何时需要调用哪个控制器。

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
    }

要使用此自定义controllerfactory,您应将其添加到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
}

我从this blog获得了大部分代码,并根据我的需要进行了调整。在我的情况下,我希望破折号在我的控制器名称中分隔单词,但是你不能在名称中创建带破折号的动作。

希望这有帮助!

答案 4 :(得分:0)

定义特定路线,例如:

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

但是这条路线必须在之前注册您的默认路线。