2009-05-15 78 views
4

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

它適用於網址之上,但它有問題,爲以下類型的URL

mywebsite/myController的/ myaction/14-長和漂亮的搜索引擎優化名

是否有可能使它工作?


編輯:

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

似乎是工作

+1

會更簡單的解決方案是像像堆棧溢出一樣的URL,比如mywebsite/mycontroller/mycation/14/long-and-pretty-seo-name嗎? – David 2009-05-15 12:21:41

回答

0

我不認爲路線將區分的,因爲它不會能夠推測其中 「 - 」拆分以指定{id}{seo-name}

如何使用下劃線爲您的SEO名稱?或者您可以使用SEO名稱作爲實際{id}。如果SEO名稱是獨一無二的,這是一個非常可行的選項,您可以將它用作數據庫中該條目的僞主鍵(假設它正在從數據庫中提取某些內容)

另外,利用Phil Haack的route debugger,看看有效和無效。

+2

我不希望seo_name是全局唯一的,所以這是將id字段放在begininning中的原因。 如果它不能區分短劃線,那麼我可以將規則更改爲mycontroller/myaction/{id}/{seo_name},對於我來說沒關係,但我不知道它是否違反任何seo規則/最佳做法 – tomo 2009-05-15 12:36:25

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,它適應了我的需求。在我的情況下,我想用破折號分隔控制器名稱中的單詞,但不能在名稱中創建帶短劃線的動作。

希望這會有所幫助!

+1

當您downvote我的答案這將是很好的解釋爲什麼,所以我知道什麼是錯的。 – Peter 2011-07-25 08:33:02

1

最明顯的做法是使用約束。

因爲你的ID是一個整數,你可以添加一個約束,這將尋找一個整數值:

new { id = @"\d+" } 

,這裏是整個路線:

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

你會認爲這會起作用。但它不起作用。至少,不是爲了我。 – MrSoundless 2013-09-03 12:06:38

1

我的解決方法是定義路由爲:

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

並在HTTP處理程序中使用正則表達式解析id和seoname manualy:

 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; 
0

定義特定的途徑,如:

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

但是這條路必須要註冊之前您的默認路由。