【问题标题】:ASP.NET routing - avoiding clashes between controller/action and vanity/slug urlsASP.NET 路由 - 避免控制器/操作和虚荣/slug url 之间的冲突
【发布时间】:2010-09-28 21:49:39
【问题描述】:

我正在寻找一个很好的解决方案来拥有一个适用于标准 ASP.NET MVC 控制器/操作 URL 的 URL 方案,例如:

/Home/About --> Controller "Home", Action "About"

和虚荣/蛞蝓网址,例如:

/fred/post  --> Controller "Posts", Action "View", User "fred", Post "post"

重要的是,我希望出站 url 生成能够正常工作,以便

Html.ActionLink("View", "Posts", new { User="fred", Post="post" }, null }

给出 /fred/post - 不是 /Posts/View/fred/post

看来,我可以让它适用于入站或出站路由,但不能同时用于两者。或者我可以让它工作,但它很乱而且容易坏。有什么方法、提示和技巧可以让这样的事情干净利落地运行?

【问题讨论】:

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


    【解决方案1】:

    我终于想出了使用路由约束来检查参数是否匹配(或不匹配)控制器名称的解决方案:

    public class ControllerConstraint : IRouteConstraint
    {
        static List<string> ControllerNames = (from t in System.Reflection.Assembly.GetExecutingAssembly().GetTypes()
                                               where typeof(IController).IsAssignableFrom(t) && t.Name.EndsWith("Controller")
                                               select t.Name.Substring(0, t.Name.Length - 10).ToLower()).ToList();
    
        bool m_bIsController;
        public ControllerConstraint(bool IsController)
        {
    
            m_bIsController = IsController;
        }
    
        public bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection)
        {
            if (m_bIsController)
                return ControllerNames.Contains(values[parameterName].ToString().ToLower());
            else
                return !ControllerNames.Contains(values[parameterName].ToString().ToLower());
        }  
    }
    

    这样使用:

    // eg: /myusername
    routes.MapRoute(
        "MemberUrl",
        "{member_urlid}",
        new { controller = "Members", action = "View" },
        new { action="View", member_urlid = new ControllerConstraint(false) }
    );
    
    // eg: /myusername/mypagename
    routes.MapRoute(
        "ItemUrl",
        "{member_urlid}/{item_urlid}",
        new { controller = "Items", action = "View" },
        new { action="View", member_urlid = new ControllerConstraint(false) }
    );
    
    // Normal controller/action routes follow
    

    约束new ControllerConstraint(false) 表示如果参数匹配控制器的名称,则不匹配此路由规则。传递 true 以使约束检查参数是否与控制器名称匹配。

    【讨论】:

    • 好的——但是如果用户使用用户名“About”注册,然后您最终决定在他们注册后需要一个 AboutController。决议如何进行? /about/ 映射到什么?用户?你的新控制器?我想知道如何处理这些根虚 URL,但为了将来的证明,我正在考虑简单地使用 /users/{username} 代替。想法?您可以有一个保留字列表,但以后会有是您从未想过的……对吧?
    猜你喜欢
    • 2013-08-18
    • 2018-02-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-10-09
    相关资源
    最近更新 更多