2011-04-07 120 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