代码之家  ›  专栏  ›  技术社区  ›  Eric

带有额外一致参数的ASP.NET MVC 2路由(不只是控制器和操作)

  •  3
  • Eric  · 技术社区  · 14 年前

    目前,我有如下网址:

    http://www.example.com/user/create
    http://www.example.com/user/edit/1
    

    但现在,我必须支持多个组织及其用户。我需要这样的东西:

    http://www.example.com/org-name/user/create
    http://www.example.com/org-name/user/edit/1
    

    我很难让路由正常工作,所以我必须在组织名称的开头添加一个令牌,这样路由就不会把它与控制器/操作对混淆。没什么大不了的,但是我的网址现在看起来像这样:

    http://www.example.com/o/org-name/user/create
    http://www.example.com/o/org-name/user/edit/1
    

    那很好。我可以忍受。

    这就是我遇到麻烦的地方:
    当我选择一个组织后生成URL时,它不会持久化组织名称。所以当我在这里的时候:

    http://www.example.com/o/org-name
    

    …我使用url.action(“user”,“create”)生成一个url,它输出:

    /user/create
    

    …而不是我想要的:

    /o/org-name/user/create
    

    这就是我的路线(按顺序)的样子:

            routes.MapRouteLowercase(
                "DefaultOrganization",
                "{token}/{organization}/{controller}/{action}/{id}",
                new { id = UrlParameter.Optional },
                new { token = "o" }
            );
    
            routes.MapRouteLowercase(
                "OrganizationDashboard",
                "{token}/{organization}/{controller}",
                new { controller = "Organization", action = "Dashboard" },
                new { token = "o" }
            );
    
            routes.MapRouteLowercase(
                "DefaultSansOrganization",
                "{controller}/{action}/{id}",
                new { controller = "Core", action="Dashboard", id = UrlParameter.Optional }
            );
    

    这和这个问题类似 ASP.NET MVC Custom Routing Long Custom Route not Clicking in my Head .

    我有种感觉,这最终会变得很明显,但现在是星期五,而且现在不会发生。


    编辑:
    Womp的建议有效,但这是实现自动化的最佳方法吗?

    public static string ActionPrepend(this UrlHelper helper, string actionName, string controllerName)
        {
            string currentUrl = helper.RequestContext.RouteData.Values["url"] as string;
            string actionUrl = string.Empty;
    
            if (currentUrl != null)
            {
                Uri url = new Uri(currentUrl);
    
                if (url.Segments.Length > 2 && url.Segments[1] == "o/")
                    actionUrl = string.Format("{0}{1}{2}{3}", url.Segments[0], url.Segments[1], url.Segments[2],
                        helper.Action(actionName, controllerName));
            }
    
            if(string.IsNullOrEmpty(actionUrl))
                actionUrl = helper.Action(actionName, controllerName);
    
            return actionUrl;
        }
    


    编辑:
    修正了我的工作路线,而不是把它拼凑在一起。最终的解决方案不需要URL中的愚蠢标记。也许这能帮助其他人:

    routes.MapRouteLowercase(
        "Organization",
        "{organization}/{controller}/{action}/{id}",
        new { controller = "Organization", action = "Dashboard", id = UrlParameter.Optional },
        new { organization = @"^(?!User|Account|Report).*$" }
    );
    
    routes.MapRouteLowercase(
        "Default",
        "{controller}/{action}/{id}",
        new { controller = "Core", action = "Dashboard", id = UrlParameter.Optional }
    );
    
    1 回复  |  直到 14 年前
        1
  •  2
  •   womp    14 年前

    操作使用路由值通过查询虚拟路径提供程序并尝试匹配最特定的路由来生成实际的URL。在您使用的表单中,您为控制器和操作提供值,这与大多数简单网站一样深,因此是该方法的方便形式。当url.action查询路由系统时,它只有一个“controller”和一个“action”段匹配。

    如果您为该方法提供它所需的其余路由信息,它将正确匹配您想要的路由,并返回正确的URL。试试这个:

    Url.Action("User", "Create", new { token = "o", organization = "organization" })