2011-04-07 140 views
2

我想設置路由如下:MVC路由問題

/資料/編輯 - >路線編輯行動

/資料/添加 - >路線添加動作

/資料/用戶名 - >使用參數username輸入索引操作的路由,因爲操作用戶名不存在。

所以我想第二個參數被解析爲控制器動作,除非沒有該名稱的控制器存在;那麼它應該路由到默認的索引頁面並使用url部分作爲id。

可能嗎?

回答

0

馬特的解決方案可以讓你90%的方式。然而,而是採用了路由約束排除操作名稱,使用路由的約束,包括唯一有效的用戶名,比如:

public class MustMatchUserName : IRouteConstraint 
{ 

    private Users _db = new UserEntities(); 

    public MustMatchUserName() 
    { } 

    public bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection) 
    { 
     return _db.Users.FirstOrDefault(x => x.UserName.ToLower() == values[parameterName].ToString().ToLower()) != null; 
    } 
} 

然後,馬特指出,在用戶創建過程中,你必須強制執行規定您的ActionNames對用戶名無效。

counsellorben

0

任何事情都是可能的。但是,爲什麼不直接製作/剖析你的根?

如果這是不可能的,你可能需要硬編碼你的動作的路線。

+0

嗯,是的,有種愚蠢的,但我我真的沒想到:)我可能會這樣做,這會讓事情變得更容易。 – Jasper 2011-04-07 20:34:45

0

這裏是實現這個的一種方法:

請在Global.asax.cs中你這些路線:

routes.MapRoute("UserProfileRoute", "Profile/{username}", 
    new { controller = "Profile", action = "Index" }); 
routes.MapRoute("DefaultProfileRoute", "Profile/{action}", 
    new { controller = "Profile", action = "SomeDefaultAction" }); 

預期這將匹配/資料/ someUsername。但是對於其他所有行爲都會失敗。現在所有的動作名稱都被認爲是用戶名。對此的一個快速解決方案是爲第一條路線添加IRouteConstraint:

routes.MapRoute("UserProfileRoute", "Profile/{username}", 
    new { controller = "Profile", action = "Index" }, 
    new { username = new NotAnActionRouteConstraint() }); 
routes.MapRoute("DefaultProfileRoute", "Profile/{action}", 
    new { controller = "Profile", action = "SomeDefaultAction" }); 

public class NotAnActionRouteConstraint : IRouteConstraint 
{ 
    public bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection) 
    { 
     string value = values[parameterName].ToString(); 

        // it is likely parameterName is not cased correctly, 
        // something that would need to be 
        // addressed in a real implementation 
     return typeof(ProfileController).GetMethod(parameterName, 
         BindingFlags.Public | BindingFlags.Instance) == null; 
    } 
} 

但是,這有點難看。希望有人知道更好的解決方案。

也有問題,當你的用戶挑選一個名稱相同的動作:)

+0

是的,我雖然關於最後的評論,我將實施一些反射邏輯,以防止用戶選擇等同於操作的用戶名。 – Jasper 2011-04-07 20:32:55

+0

順便說一句,Facebook的這些時間都一樣,我可以通過facebook.com/username打開我的Facebook個人資料。對我的名字來說並不那麼殘暴,但其他人可能會更棘手。我想知道如果他們想要在用戶已經聲明的地址上創建文件夾或其他內容,他們會做什麼。 – Jasper 2011-04-07 20:34:01

2

您可以使用正則表達式在你的路由約束,像這樣

routes.MapRoute(
    "UserProfileRoute", 
    "Profile/{username}", 
    new { controller = "Profile", action = "Index" }, 
    new { username = "(?i)(?!edit$|add$)(.*)" }); 

將匹配的URL像/profile/addendum/profile/someusername並忽略/profile/edit/profile/add