Asp.net mvc MVC路由问题

Asp.net mvc MVC路由问题,asp.net-mvc,asp.net-mvc-3,Asp.net Mvc,Asp.net Mvc 3,我想按如下方式设置路由: /配置文件/编辑->路由到编辑操作 /配置文件/添加->添加操作的路线 /Profile/username->使用参数username路由到索引操作,因为操作用户名不存在 因此,我希望将第二个参数解析为控制器操作,除非不存在具有该名称的控制器;然后它应该路由到默认的索引页面,并使用url部分作为id 可能吗?一切皆有可能。但是,为什么不直接创建/配置您的根目录 如果这是不可能的,您可能需要硬编码您的操作路线。这里有一种方法可以实现这一点: 在Global.asax.cs

我想按如下方式设置路由:

/配置文件/编辑->路由到编辑操作

/配置文件/添加->添加操作的路线

/Profile/username->使用参数username路由到索引操作,因为操作用户名不存在

因此,我希望将第二个参数解析为控制器操作,除非不存在具有该名称的控制器;然后它应该路由到默认的索引页面,并使用url部分作为id


可能吗?

一切皆有可能。但是,为什么不直接创建/配置您的根目录


如果这是不可能的,您可能需要硬编码您的操作路线。

这里有一种方法可以实现这一点:

在Global.asax.cs中将这些路线设置为您的路线:

 routes.MapRoute("UserProfileRoute", "Profile/{username}",
    new { controller = "Profile", action = "Index" });
 routes.MapRoute("DefaultProfileRoute", "Profile/{action}", 
    new { controller = "Profile", action = "SomeDefaultAction" });
这将与预期的/Profile/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;
    }
 }
不过,这有点难看。希望有人知道更好的解决方案


当你的一个用户选择了一个与动作相同的名称时,你也会遇到问题:)

马特的解决方案让你获得了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; 
    } 
} 
然后,正如Matt指出的,在用户创建过程中,您必须强制执行一条规则,即您的ActionName对用户名无效


Councellorben

您可以在路由约束中使用正则表达式,如下所示

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

这将匹配像
/profile/address
/profile/someusername这样的URL,并将忽略
/profile/edit
/profile/add

是的,我考虑过最后一条评论,我将实现一些反射逻辑,以防止用户选择等同于操作的用户名,Facebook也会这样做,我可以通过Facebook.com/username打开我的Facebook个人资料。我的名字不那么危险,但其他人可能更狡猾。我想知道如果他们想在用户已经声明的地址创建文件夹或其他任何东西,他们会怎么做。嗯,是的,有点愚蠢,但我真的没有想到:)我只是想,那会让事情变得容易得多。