views:

52

answers:

1

Pages have Roles. Users have Roles. A user may only view a page if he and it share one or more roles.

This works:

Dim Allow As Boolean = False
CurrentPage.Roles.Load()
For Each r As Role In CurrentPage.Roles
    r.Users.Load()
    For Each u As User In r.Users
        If u.Id = CurrentUser.Id Then
            Allow = True
            Exit For
        End If
    Next
    If Allow Then
        Exit For
    End If
Next

I don't want to have to use nested loops if I can instead do it in fewer lines of code with LINQ or a lambda expression.

This always returns False:

Dim Allow As Boolean = (CurrentPage.Roles.ToList.Intersect(CurrentUser.Roles.ToList).Count > 0)

I think it fails because Roles are EntityObjects.

How can I make it compare only the Role Id values to determine equality?

+2  A: 

You would either have to use the second parameter of the Intersect method to supply your own custom IEqualityComparer or you could try this. It looks kinda funny, but it makes sense once you get the hang of it.

If CurrentPage.Roles.Any(Function(Role) Role.Users.Any(Function(User) User.Id = CurrentUser.Id)) Then
    'User has role
End If

Although this might not work if you have to in fact load your users in each iteration. If you are loading from EntityFramework, I would recommend you eager load them something like this:

CurrentPage.Roles.Include("Users").Any(...

Or I've also created my own EnsureLoaded() extension which returns the object something like this:

If CurrentPage.Roles.Any(Function(a) a.Users.EnsureLoaded().Any(Function(b) b.Id = CurrentUser.Id)) Then

But if you are hitting the db each page request, then make sure you check profiler and make sure you are only executing one query and not one query for each role.

Kevin Lewis