Correct Url for different routes / controller namespaces

Sep 4, 2009 at 9:05 PM

Hi,

I'm wondering how I can get the code to generate correct Urls for nodes that do not use their parent's controller, and where their controller sits in a sub-namespace.

For example:

<mvcSiteMapNode title="Accounting" controller="Accounting">
            <mvcSiteMapNode title="Invoices" controller="Invoices" action="List" />
            <mvcSiteMapNode title="New Invoice" controller="Invoices" action="Create"/>
            <mvcSiteMapNode title="Invoice Details" controller="Invoices" action="Details"
                            isDynamic="true" dynamicParameters="id" visibility="InSiteMapPathOnly" />
</mvcSiteMapNode>

Here, Accounting is in the namespace Project.Web.Controllers but Invoices is in the namespace Project.Web.Controllers.Accounting. Also, there is a new map route created for "Accounting/{controller}/{action}/{id}

For some reason, the Url for the Invoicing subnodes point to /Invoices/List or /Invoices/Create, etc. rather than the correct /Accounting/Invoices/List, etc.

Note that I am using a similar "Submenu" extension as mentioned by another person back in May 2009.

I'd appreciate the help. Thanks.

Coordinator
Sep 7, 2009 at 6:09 AM

Can you post our route table as well? If you are using areas, add the area to the mvcSiteMapNode as well.

Sep 7, 2009 at 3:54 PM

I'm using S#arp Architecture as the framework for my project.

How do I add an area to the mvcSiteMapNode???

My routing is as follows:

routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.IgnoreRoute("{*favicon}", new { favicon = @"(.*/)?favicon.ico(/.*)?" });
routes.CreateArea("Accounting", "Project.Web.Controllers.Accounting",
    routes.MapRoute(null, "Accounting/{controller}/{action}", new { action = "Index" }),
    routes.MapRoute(null, "Accounting/{controller}/{action}/{id}"));
routes.MapRoute("Default", "{controller}/{action}/{id}", new { controller = "Home", action = "Index", id = "" });

CreateArea is an extension method in the S#arp Architecture codebase as follows:

/// <summary>
/// An extension method to facilitate the registration of area routes.  Described by Steve Sanderson
/// at http://blog.codeville.net/2008/11/05/app-areas-in-aspnet-mvc-take-2/
/// </summary>
public static void CreateArea(this RouteCollection routes, string areaName, string controllersNamespace, params Route[] routeEntries) {
    foreach (var route in routeEntries) {
        if (route.Constraints == null) 
            route.Constraints = new RouteValueDictionary();

        if (route.Defaults == null) 
            route.Defaults = new RouteValueDictionary();
        
        if (route.DataTokens == null) 
            route.DataTokens = new RouteValueDictionary();

        route.Constraints.Add("area", areaName);
        route.Defaults.Add("area", areaName);
        route.DataTokens.Add("namespaces", new string[] { controllersNamespace });

        if (!routes.Contains(route)) // To support "new Route()" in addition to "routes.MapRoute()"
            routes.Add(route);
    }
}
Sep 7, 2009 at 4:25 PM
Edited Sep 7, 2009 at 4:42 PM

I was reviewing the documentation for MvcSiteMap and noticed the "area" attribute which I hadn't seen before. I added an area for "Accounting" to the appropriate subnodes, and now the links to my subnodes are generated correctly (i.e., /Accounting/Invoices/List) but as soon as you click a link of that type, the new menu that is generated uses that "area" for all the links in the menu. For example what used to be /Customers is now /Accounting/Customers.

This clearly breaks the menu functionality, and it shouldn't be happening. I tried explicitly adding a blank area to all other nodes in my sitemap, but that simply adds a query parameter to the end of my urls. It works, but it's ugly and nonsensical.

What's going on? What is the solution?

Sep 7, 2009 at 5:27 PM

Please note that I edited my last message because my initial perception that things were working perfectly was incorrect, but a new email does not get sent out when you edit a message.

Could you please continue to help when you get a chance?

Thank you,

- Chris

Coordinator
Sep 8, 2009 at 7:52 AM

Can you post the new sitemap with area configuration in it?

Dec 1, 2009 at 9:50 PM
Edited Dec 1, 2009 at 9:52 PM

I am having the same problems.  When building the sitemap within an area, all Controllers outside of that area fail when created.....

 

 This is from the MvcSiteMapProvider class

<font size="3">

        public IController GetController(RequestContext context, string controllerName)
        {
            if (!controllerCache.ContainsKey(controllerName))
            {
                lock (controllerCache)
                {
                    if (!controllerCache.ContainsKey(controllerName))
                    {
                        IController controller = null;
                        try
                        {
                            controller = ControllerBuilder.Current.GetControllerFactory().CreateController(context, controllerName);
                            controllerCache.Add(controllerName, controller);
                        }
                        catch (Exception ex)
                        {
                            // Fails if page is created from within an area and controllers are located outside of area...
                        }
                        return controller;
                    }
                }
            }
Anybody find a solution for this?

 

</font>

 

Coordinator
Dec 14, 2009 at 4:20 PM

What version of the sitemap provider are you using? (try latest source code version)
What version of MVC are you using? (beta? preview?)
Can you post a small project reproducing this behaviour?