Roles on Orchard

Topics: Administration
Jun 7, 2011 at 6:21 PM

Hi.

 

I am new to Orchard. I wanted to build a webpage that shows a list of elements. The list shown is based on the user's current role(s). Unfortunately, I've never been able to get the user's current group. I'm able to do it in other page through the model. But in my page, the model is not a role type. Is there another way to get the user's associated role(s) when programming in our own module ?

Coordinator
Jun 7, 2011 at 6:30 PM

Hi and welcome.

WorkContext.CurrentUser.As<UserRolesPart>().Roles gives you a list of strings that represent the roles for the current user.

Jun 7, 2011 at 6:48 PM

I tried that but it gives me an error:

The type or namespace name 'Roles' does not exist in the namespace 'Orchard' (are you missing an assembly reference?)

It gives me the same error when whether i put it in a view file or a controller. I don't understand because I specify the namespace given by my intellisence:

WorkContext.CurrentUser.As<Orchard.Roles.Models.

UserRolesPart>().Roles

 

 
Coordinator
Jun 7, 2011 at 6:56 PM

You are missing an assembly reference, not a using or a fully-qualified name. You can try to add it to the web.config in your theme.

Jun 7, 2011 at 7:02 PM
Edited Jun 7, 2011 at 7:02 PM

You might see those errors in your views in Visual Studio, but when you run the site it will still be fine.

Jun 7, 2011 at 7:13 PM

How do I do that ?

Coordinator
Jun 7, 2011 at 7:27 PM

how do you do what?

Jun 7, 2011 at 7:27 PM

I do all my modifications with Visual Studio but I run the webstie with webmatrix. And it's still not working.

Coordinator
Jun 7, 2011 at 7:29 PM

Then you might want to add the Orchard.Roles assembly to your web.config.

Jun 7, 2011 at 7:33 PM

Adding the assembly reference to the web.config ? I tried but it didn't seem to work. I added this line: 

add namespace="Orchard.Roles.Models"

 

It gives me the same error.

Jun 7, 2011 at 7:33 PM
Edited Jun 7, 2011 at 7:34 PM

I only meant it should work fine from a view (at least, I've seen it working, but it might not be true in all situations); but if it's in your controller then it'll cause a compile-time error so you definitely need a project reference. Although are you just using Orchard.Web.zip instead of a full source enlistment - that could cause dynamic compilation issues because you don't have all the necessary source files.

But there's another way to access the roles, by treating the user as dynamic:

 

dynamic user = WorkContext.CurrentUser;
IEnumerable<string> roles = user.RolesPart.Roles;

That avoids any need for a project reference.

Coordinator
Jun 7, 2011 at 7:38 PM

Adding a namespace is not the same as adding an assembly. Look for the assemblies section, not the namespaces section.

Pete is right that using dynamic is easier. Haven't got used to that one yet.

Jun 7, 2011 at 7:41 PM

It gives me another error:

Microsoft.CSharp.RuntimeBinder.RuntimeBinderException: 'Orchard.Users.Models.UserPart' does not contain a definition for 'RolesPart'.

Coordinator
Jun 7, 2011 at 7:54 PM

Try user.ContentItem.RolesPart.Roles.

Jun 7, 2011 at 7:56 PM

Gave me the same error:

Microsoft.CSharp.RuntimeBinder.RuntimeBinderException: 'Orchard.ContentManagement.ContentItem' does not contain a definition for 'RolesPart'

Coordinator
Jun 7, 2011 at 8:36 PM

Right, it's UserRolesPart, not RolesPart :) We're getting there.

Coordinator
Jun 7, 2011 at 8:39 PM

I tried this and it works:

@{
    dynamic user = WorkContext.CurrentUser;
    if (user != null) {
        dynamic userItem = user.ContentItem;
        @String.Join(",", user.UserRolesPart.Roles)
    }
}
Jun 7, 2011 at 8:44 PM

It works ! Thanks a lot for your help !

Jun 8, 2011 at 10:13 AM
bertrandleroy wrote:

Pete is right that using dynamic is easier. Haven't got used to that one yet.

I remember being somewhat dubious about accessing parts dynamically ;)  But since then I've had time to get used to it, and it's a particularly powerful feature when it comes to working around dependencies.

The only limitation is that you can't do this:

dynamic item = Model.ContentItem;
if (item.BodyPart!=null) {
    var text = item.BodyPart.Text;
}

If BodyPart isn't there, an exception will still get thrown. There's no way to dynamically check whether a part exists or not.

You have to do this instead which isn't so convenient:

IContent content = Model.ContentItem;
if (content.ContentItem.Parts.Any(p => p.PartDefinition.Name == "BodyPart")) {
    dynamic item = content;
    var text = item.BodyPart.Text;
}
Actually I should probably raise a workitem for this.

Jun 8, 2011 at 10:53 AM
Edited Jun 8, 2011 at 10:54 AM
randompete wrote:
IContent content = Model.ContentItem;
if (content.ContentItem.Parts.Any(p => p.PartDefinition.Name == "BodyPart")) {
    dynamic item = content;
    var text = item.BodyPart.Text;
}

Using the extension methods in the "Orchard.ContentManagement" namespace, this condition could be simplified to:

 

if (content.Has<BodyPart>()) { /* ... */ }

 

Jun 8, 2011 at 11:15 AM

@hosamaly - the point here was to use dynamic to avoid project dependencies. Has<T> requires a strong reference to T. If you don't have a reference, you need to check by part name.

Coordinator
Jun 8, 2011 at 6:05 PM

Well, I think you can check for Nil, which can be seen as the Clay version of null: it's null for all intents and purposes except that it won't complain about further dereferencing. Concept comes from ruby and other dynamic languages before it if I'm not mistaken.

Jun 8, 2011 at 8:20 PM

It seemed that the exception was getting thrown just from accessing item.SomePart - making it impossible to test for anything. But I'll double check.

Sep 13, 2011 at 12:47 PM
 

Hi,
how I can list all roles, not for current user but all existing roles, in cshtml? I know there is a function named getRoles() in IRoleService but how to use it in cshtml?
Thanks for any help.

Coordinator
Sep 13, 2011 at 9:28 PM

In principle, you should inject that data into a shape from a driver or controller. If you absolutely want to do it from the view, you can get an instance through the WorkContext.

WorkContext.Resolve<IRoleService>().GetRoles()

Sep 14, 2011 at 8:30 AM

Thanks bertrandleroy, if someone needs this, this is complete code that list roles in view:

@using Orchard.Roles.Services;
@using System.Collections;

<fieldset>
    @{
        List<Orchard.Roles.Models.RoleRecord> roles = WorkContext.Resolve<IRoleService>().GetRoles().ToList();
    }
    @foreach(Orchard.Roles.Models.RoleRecord r in roles){
    <label>@r.Name</label>
    }
</fieldset>