How are you supposed to conditionally display menu items based on roles in the Bootstrap Sample project? I was thinking of doing the following
INavigatonRouteFilter
- really just implementing the shouldRemove(Route navigationRoutes)
method - by getting the default controller/action for the route and seeing if the user is authorizedNavigationRoutes.Filters.Add(myAuthorizationFilter)
after configuring the NavigationRoutes
in App_Start
There are two problems I see with this approach:
Controller
's name explicitlyNavigationRoutes.Filters
very hard to deal with once there are a lot of filters or a desire for more modularity later onI don't know that I've explained the problem clearly enough, but basically I want to use what is provided in the Bootstrap sample to implement authorization-based navigation menu display if at all possible. Using INavigationRouteFilter
just seemed like the most natural way to do so.
For those looking for an answer or at least a quick fix. Here's what I've come up with after 5 minutes and I most certainly haven't though about any side effects this may have.
routes.MapNavigationRoute<HomeController>("Index", c => c.Index())
.FilterRoute(() => !WebSecurity.IsAuthenticated);
You can either do all your filtering in your call to FilterRoute() or you can add more extension methods to save you some characters.
I'm thinking of .RequireRole("Adiministrators"); that calls WebSecurity.RequireRoles() in turn (or HttpContext.Current.User.IsInRole()) etc.
public static NavigationRouteBuilder FilterRoute(this NavigationRouteBuilder builder, Func<bool> func)
{
var currentRoute = builder._parent;
NavigationRoutes.Filters.Add(new BootstrapAuthorizationFilter(builder, x =>
{
if (x == currentRoute)
return func();
else
return false;
}));
return builder;
}
and BootstrapAuthorizationFilter is just a class implementing INavigationRouteFilter that calls func() in its ShouldRemove() method
public class BootstrapAuthorizationFilter : INavigationRouteFilter
{
private NavigationRouteBuilder builder;
private Func<NamedRoute, bool> func;
public BootstrapAuthorizationFilter(NavigationRouteBuilder builder, Func<NamedRoute, bool> func)
{
this.builder = builder;
this.func = func;
}
public bool ShouldRemove(Route navigationRoutes)
{
if (navigationRoutes is NamedRoute)
return func(navigationRoutes as NamedRoute);
return false;
}
}
Clearly nothing fancy and I'm not sure if I'd use it in production. But I think is simple enough and works (for the cases I tested). Having said that, I hope the new routing functionality is going to be released soon :)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With