質問

How are you supposed to conditionally display menu items based on roles in the Bootstrap Sample project? I was thinking of doing the following

  1. Implement INavigatonRouteFilter - really just implementing the shouldRemove(Route navigationRoutes) method - by getting the default controller/action for the route and seeing if the user is authorized
  2. Call NavigationRoutes.Filters.Add(myAuthorizationFilter) after configuring the NavigationRoutes in App_Start

There are two problems I see with this approach:

  1. I don't actually know how to do the first step unless I add in a bunch of conditional statements to check for Controller's name explicitly
  2. This seems like it could make NavigationRoutes.Filters very hard to deal with once there are a lot of filters or a desire for more modularity later on

I 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 :)

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top