ASP.NET MVC全能路由

时间:2011-07-27 01:07:02

标签: asp.net asp.net-mvc asp.net-mvc-3 asp.net-mvc-routing

我已经在StackOverflow上阅读了一些关于此的线程,但无法使其工作。我在Global.asax的RegisterRoutes末尾有这个。

routes.MapRoute(
            "Profile",
            "{*url}",
            new { controller = "Profile", action = "Index" }
            );

基本上我想要实现的是让mydomain.com/Username指向我的成员个人资料页面。我如何设置我的控制器和RegisterRoutes才能使其正常工作?

目前mydomain.com/somethingthatisnotacontrollername出现404错误。

3 个答案:

答案 0 :(得分:6)

适用于您的案例的解决方案,但不推荐

您的应用程序中有一组预定义的控制器(通常少于10个),因此您可以对控制器名称设置约束,然后将其他所有控制器路由到用户配置文件:

routes.MapRoute(
    "Default",
    "{controller}/{action}/{id}",
    new { controller = "Home", action = "Index", id = UrlParameter.Optional },
    new { controller = "Home|Admin|Reports|..." }
);
routes.MapRoute(
    "Profile",
    "{username}/{action}",
    new { controller = "Profile", action = "Details" }
);

但是,如果某些用户名与您的控制器名称相同,则无法使用。根据经验最终的经验数据,这是一个小的可能性,但它不是0%的机会。当用户名与某个控制器相同时,它自动意味着它将由第一个路由处理,因为约束不会失败。

推荐的解决方案

最好的方法是将URL请求改为:

www.mydomain.com/profile/username

为什么我推荐这样做?因此,这将使其更简单,更清洁,并允许有几个不同的个人资料页面:

  • 详情www.mydomain.com/profile/username
  • 设置www.mydomain.com/profile/username/settings
  • 消息www.mydomain.com/profile/username/messages

在这种情况下,路线定义如下:

routes.MapRoute(
    "Profile",
    "Profile/{username}/{action}",
    new { controller = "Profile", action = "Details" }
);
routes.MapRoute(
    "Default",
    "{controller}/{action}/{id}",
    new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);

答案 1 :(得分:2)

拥有与mydomain.com/Username相匹配的东西并不能真正起作用,因为路由引擎无法区分

mydomain.com/someusername

mydomain.com/controllername

可能可能是什么,如果您的用户名方案具有一组唯一的属性,即9位数的序列,您可以定义一个路由来检查看起来像用户名的内容。

routes.MapRoute("",
        "UserRoute",
        "{username}",
        new { controller = "Profile", action = "Index"},
         new { {"username", @"\d{9}"}}
       );

关键点在于,您需要为路由引擎提供一些方法来区分用户名和标准控制器操作

您可以找到有关约束here

的更多信息

答案 2 :(得分:1)

我的项目有这样的要求。我所做的是创建一个如下所示的路线约束:

public class SeoRouteConstraint : IRouteConstraint
{
    public static HybridDictionary CacheRegex = new HybridDictionary();
    private readonly string _matchPattern = String.Empty;
    private readonly string _mustNotMatchPattern;

    public SeoRouteConstraint(string matchPattern, string mustNotMatchPattern)
    {
        if (!string.IsNullOrEmpty(matchPattern))
        {
            _matchPattern = matchPattern.ToLower();
            if (!CacheRegex.Contains(_matchPattern))
            {
                CacheRegex.Add(_matchPattern, new Regex(_matchPattern));
            }
        }

        if (!string.IsNullOrEmpty(mustNotMatchPattern))
        {
            _mustNotMatchPattern = mustNotMatchPattern.ToLower();
            if (!CacheRegex.Contains(_mustNotMatchPattern))
            {
                CacheRegex.Add(_mustNotMatchPattern, new Regex(_mustNotMatchPattern));
            }
        }
    }

    public bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection)
    {
        var matchReg = string.IsNullOrEmpty(_matchPattern) ? null : (Regex)CacheRegex[_matchPattern];
        var notMatchReg = string.IsNullOrEmpty(_mustNotMatchPattern) ? null : (Regex)CacheRegex[_mustNotMatchPattern];

        var paramValue = values[parameterName].ToString().ToLower();

        return IsMatch(matchReg, paramValue) && !IsMatch(notMatchReg, paramValue);
    }

    private static bool IsMatch(Regex reg, string str)
    {
        return reg == null || reg.IsMatch(str);
    }
}

然后在寄存器路由方法中:

routes.MapRoute("",
    "UserRoute",
    "{username}",
    new { controller = "Profile", action = "Index"},
     new { username = new SeoRouteConstraint(@"\d{9}", GetAllControllersName())}
   );

方法GetAllControllersName将返回项目中由|分隔的所有控制器名称:

private static string _controllerNames;
private static string GetAllControllersName()
{
    if (string.IsNullOrEmpty(_controllerNames))
    {
        var controllerNames = Assembly.GetAssembly(typeof(BaseController)).GetTypes().Where(x => typeof(Controller).IsAssignableFrom(x)).Select(x => x.Name.Replace("Controller", ""));

        _controllerNames = string.Join("|", controllerNames);
    }
    return _controllerNames;
}