Admin LocalNav Not Working

Topics: Writing modules
Apr 3, 2012 at 9:55 PM
Edited Apr 3, 2012 at 9:58 PM

AdminMenu.cs:

builder.AddImageSet("barbershop")
	.Add(root => root
		.Caption(T("Barber Shop"))
		.Position("1")
		.LinkToFirstChild(false)

		//children
		.Add(child => child
			.Caption(T("Appointments"))
			.Position("1.1")
			.Action("Index", "AppointmentAdmin", new { area = "SDKU.Barbr" }))
		.Add(child => child
			.Caption(T("Barbers"))
			.Position("1.2")
			.Action("Index", "BarberAdmin", new { area = "SDKU.Barbr" })

			//local nav
			.Add(T("Details"), local => local
				.Position("0")
				.Action("Edit", "BarberAdmin", new { id })
				.LocalNav())
			.Add(T("Delete"), local => local
				.Position("0")
				.Action("Delete", "BarberAdmin", new { id })
				.LocalNav())
			.Add(T("Schedule"), local => local
				.Position("1")
				.Action("Index", "BarberScheduleAdmin", new { id })
				.LocalNav()))

		.Add(child => child
			.Caption(T("Customers"))
			.Position("1.3")
			.Action("Index", "CustomerAdmin", new { area = "SDKU.Barbr" }))
		.Add(child => child
			.Caption(T("Settings"))
			.Position("1.4")
			.Action("Index", "SettingsAdmin", new { area = "SDKU.Barbr" })));

When I visit the edit page, the tabs render correctly, and the edit and delete tabs link to the correct location. The Schedule link does not. It links to http://localhost:30320/OrchardLocal/Barbr/BarberScheduleAdmin/Index/2

After some poking around, I found that anything that uses a different controller will not build the correct URL.

Does anyone know how to get around this?

Coordinator
Apr 4, 2012 at 3:12 AM

Those actions are not specifying the area.

Apr 4, 2012 at 3:38 AM
Edited Apr 4, 2012 at 3:42 AM

The following has the same result:

 

.Add(T("Schedule"), local => local
	.Position("1")
	.Action(new RouteValueDictionary 
		{
                    {"id", id},
                    {"area", "SDKU.Barbr"},
                    {"controller", "BarberScheduleAdmin"},
                    {"action", "Index"}
		})
	.LocalNav()

 

Should I be passing the area in differently?

 

Edit: I've also tried this:

.Add(T("Schedule"), local => local
	.Position("1")
	.Action("Index", "BarberScheduleAdmin", new { area = "SDKU.Barbr", Id = id })
	.LocalNav()
 

Coordinator
Apr 4, 2012 at 4:37 AM

Are you sure your controller is active? Are you able to manually reach the "correct" url?

Apr 4, 2012 at 6:16 AM
Edited Apr 4, 2012 at 6:19 AM

Yes, it is active and works correctly when accessed directly. The local nav does not render for that page, though.

The direct url is: http://localhost:30320/OrchardLocal/Admin/BarberShop/Barbers/2/Schedules

Am I in breach of any major protocols by using the route like that?

Edit: Here are my routes:

public IEnumerable<RouteDescriptor> GetRoutes()
{
	return new[]
	{
		//front end
		GetRouteDescriptor("BarberShop/AddAppointment", "Appointment", "Index"),

		//admin
		GetRouteDescriptor("Admin/BarberShop/Appointments", "AppointmentAdmin", "Index"),
		GetRouteDescriptor("Admin/BarberShop/Appointments/Create", "AppointmentAdmin", "Create"),
		GetRouteDescriptor("Admin/BarberShop/Appointments/{ID}/Edit", "AppointmentAdmin", "Edit"),
		GetRouteDescriptor("Admin/BarberShop/Appointments/{ID}/Delete", "AppointmentAdmin", "Delete"),

		GetRouteDescriptor("Admin/BarberShop/Barbers", "BarberAdmin", "Index"),
		GetRouteDescriptor("Admin/BarberShop/Barbers/Create", "BarberAdmin", "Create"),
		GetRouteDescriptor("Admin/BarberShop/Barbers/{ID}/Edit", "BarberAdmin", "Edit"),
		GetRouteDescriptor("Admin/BarberShop/Barbers/{ID}/Delete", "BarberAdmin", "Delete"),

		GetRouteDescriptor("Admin/BarberShop/Barbers/{barberID}/Schedules", "BarberScheduleAdmin", "List"),
		GetRouteDescriptor("Admin/BarberShop/Barbers/{barberID}/Schedules/Create", "BarberScheduleAdmin", "Create"),
		GetRouteDescriptor("Admin/BarberShop/Barbers/{barberID}/Schedules/{scheduleID}/Edit", "BarberScheduleAdmin", "Edit"),
		GetRouteDescriptor("Admin/BarberShop/Barbers/{barberID}/Schedules/{scheduleID}/Delete", "BarberScheduleAdmin", "Delete"),

		GetRouteDescriptor("Admin/BarberShop/Customers", "CustomerAdmin", "Index"),
		GetRouteDescriptor("Admin/BarberShop/Customers/Create", "CustomerAdmin", "Create"),
		GetRouteDescriptor("Admin/BarberShop/Customers/{ID}/Edit", "CustomerAdmin", "Edit"),
		GetRouteDescriptor("Admin/BarberShop/Customers/{ID}/Delete", "CustomerAdmin", "Delete")
	};
}

private RouteDescriptor GetRouteDescriptor(string url, string controller, string action)
{
	return new RouteDescriptor
	{
		Priority = 5,
		Route = new Route(
			url,
			new RouteValueDictionary {
                    {"area", _area},
                    {"controller", controller},
                    {"action", action}
                },
			new RouteValueDictionary(),
			new RouteValueDictionary {
                    {"area", _area}
                },
			new MvcRouteHandler())
	};
}
 

Coordinator
Apr 4, 2012 at 6:29 AM

This looks like it should work. Nothing jumps at me as obviously wrong. I'd next make a very thorough comparison of routes that work with those. Also, you can try to do a Url.Action somewhere and see if you can get what you expect.

Apr 4, 2012 at 6:38 AM
Edited Apr 4, 2012 at 6:39 AM

If I use this on a view served by BarberScheduleAdminController:

<a href="@Url.Action("List", "BarberScheduleAdmin", new { area = "SDKU.Barbr", id = 2 })" title="@T("List")">@T("List")</a>

The URL is correctly rendered.

Anywhere else and it doesn't render the URL correctly. I'll keep poking at it, let me know if you have any epiphanies regarding this routing set up.

Apr 4, 2012 at 6:57 AM

I figured it out. It did not like what I was doing with the routes for the BarberScheduleAdmin controller. It wants the standard route patterns as follows:

GetRouteDescriptor("Admin/BarberShop/Barbers/Schedules", "BarberScheduleAdmin", "List"),
GetRouteDescriptor("Admin/BarberShop/Barbers/Schedules/Create", "BarberScheduleAdmin", "Create"),
GetRouteDescriptor("Admin/BarberShop/Barbers/Schedules/{ID}/Edit", "BarberScheduleAdmin", "Edit"),
GetRouteDescriptor("Admin/BarberShop/Barbers/Schedules/{ID}/Delete", "BarberScheduleAdmin", "Delete"),
Anything else seems to make it sad. I'll just have to pass the barberID in by query parameter instead of part of the URL.

Apr 4, 2012 at 7:08 AM

I forgot to say thanks for the help, bertrandleroy. The internet is +100 more awesome because of you.

Coordinator
Apr 4, 2012 at 7:12 AM

Thanks. That made my day.

Coordinator
Apr 4, 2012 at 7:15 AM

Of course, let's not forget that the Internets are about 1 Googol Awesome, so that's really not that much. Still, thanks for the compliment.