Set Item Permissions
Asked Answered
V

5

13

Folders work:

I now know how to set the permissions of a folder in a library:

public void ChangeItemPermissions()
{
    _SharePoint.ClientContext _ClientContext = new _SharePoint.ClientContext("https://sharepoint.oshirowanen.com/sites/oshirodev/");
    _ClientContext.Credentials = new NetworkCredential("user", "pass", "oshirowanen.com");

    _SharePoint.Principal user = _ClientContext.Web.EnsureUser(@"oshirowanen\tom");

    var _List = _ClientContext.Web.Lists.GetByTitle("Library1");
    var _Item = _List.LoadItemByUrl("/sites/oshirodev/Library1/Folder1");
    var roleDefinition = _ClientContext.Site.RootWeb.RoleDefinitions.GetByType(_SharePoint.RoleType.Reader);
    var roleBindings = new _SharePoint.RoleDefinitionBindingCollection(_ClientContext) { roleDefinition };
    _Item.BreakRoleInheritance(false,true);
    _Item.RoleAssignments.Add(user, roleBindings);

    _ClientContext.ExecuteQuery();
}

File attempt:

I've tried adding the file name to this line:

var _Item = _List.LoadItemByUrl("/sites/oshirodev/Library1/Folder1/File1.docx");

Notice the (/File1.docx) added to the end of the above line.


Error received:

But that just gives an error:

System.NullReferenceException was unhandled
  HResult=-2147467261
  Message=Object reference not set to an instance of an object.
  Source=ItemPermissions
  StackTrace:
       at ItemPermissions.Form1.ChangeItemPermissions() in c:\Users\Oshirowanen\Documents\Visual Studio 2013\Projects\ItemPermissions\ItemPermissions\Form1.cs:line 46
       at ItemPermissions.Form1.button1_Click(Object sender, EventArgs e) in c:\Users\Oshirowanen\Documents\Visual Studio 2013\Projects\ItemPermissions\ItemPermissions\Form1.cs:line 345
       at System.Windows.Forms.Control.OnClick(EventArgs e)
       at System.Windows.Forms.Button.OnClick(EventArgs e)
       at System.Windows.Forms.Button.OnMouseUp(MouseEventArgs mevent)
       at System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons button, Int32 clicks)
       at System.Windows.Forms.Control.WndProc(Message& m)
       at System.Windows.Forms.ButtonBase.WndProc(Message& m)
       at System.Windows.Forms.Button.WndProc(Message& m)
       at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
       at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
       at System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
       at System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg)
       at System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(IntPtr dwComponentID, Int32 reason, Int32 pvLoopData)
       at System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context)
       at System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context)
       at System.Windows.Forms.Application.Run(Form mainForm)
       at ItemPermissions.Program.Main() in c:\Users\Oshirowanen\Documents\Visual Studio 2013\Projects\ItemPermissions\ItemPermissions\Program.cs:line 18
       at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
       at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
       at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
       at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
       at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
       at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
       at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
       at System.Threading.ThreadHelper.ThreadStart()
  InnerException: 

Relevant info:

This is a WinForm app running on a local machine, created with C#, using .NET 4.0. SharePoint version is 2010.


The question:

How do I set the permissions for a specific file? As I already know how to set permissions for a specific folder.

Vagrom answered 23/5, 2017 at 15:2 Comment(0)
G
2

I assume that andresm53 is right about you using the extension method he mentioned.

To get this method to work on files you need to query by FileLeafRef (file name) and make sure that you add FileLeafRef to query ViewFields.

/edit

One more very important thing, limit file query to exact folder with:

query.FolderServerRelativeUrl = System.IO.Path.GetDirectoryName(url).Replace("\\", "/");

Working code below:

void Main()
{
    ClientContext context = new ClientContext("https://sharepoint.oshirowanen.com/sites/oshirodev/");
    context.Credentials = new NetworkCredential("user", "pass", "oshirowanen.com");
    Principal user = context.Web.EnsureUser(@"oshirowanen\tom");
    ChangeItemPermissions(context, "/sites/oshirodev/Library1/Folder1/File1.docx", "Library1", user, RoleType.Reader);
}

// Define other methods and classes here
public static ListItem LoadItemByUrl(List list, string url)
{
    var context = list.Context;
    string ext = System.IO.Path.GetExtension(url);

    var query = new CamlQuery();
    if (string.IsNullOrEmpty(ext))
        query.ViewXml = String.Format("<View><RowLimit>1</RowLimit><Query><Where><Eq><FieldRef Name='FileRef'/><Value> Type='Url'>{0}</Value></Eq></Where></Query></View>", url);
    else
    {
        query.ViewXml = String.Format("<View><ViewFields><FieldRef Name=\"FileLeafRef\" /></ViewFields><Query><Where><Eq><FieldRef Name=\"FileLeafRef\" /><Value Type=\"Text\">{0}</Value></Eq></Where></Query><RowLimit>1</RowLimit></View>", System.IO.Path.GetFileName(url));
        query.FolderServerRelativeUrl = System.IO.Path.GetDirectoryName(url).Replace("\\", "/");
    }

    var items = list.GetItems(query);
    context.Load(items);
    context.ExecuteQuery();
    return items.Count > 0 ? items[0] : null;
}

public void ChangeItemPermissions(ClientContext context, string url, string listName, Principal user, RoleType type)
{    
    var list = context.Web.Lists.GetByTitle(listName);
    var item = LoadItemByUrl(list, url);
    var roleDefinition = context.Site.RootWeb.RoleDefinitions.GetByType(type);
    var roleBindings = new RoleDefinitionBindingCollection(context) { roleDefinition };
    item.BreakRoleInheritance(false, true);
    item.RoleAssignments.Add(user, roleBindings);
    context.ExecuteQuery();
}
Graduation answered 26/5, 2017 at 20:23 Comment(1)
Added further bounty just for this answer as I was unable to accept an answer last week due to unexpectedly not having access to a computer. This answer works great. Thanks for the help!Vagrom
P
4

I reviewed the 2010 CSOM documentation, and the method you are using LoadItemByUrl doesn't exist. Is that an extension you wrote, perhaps this one? If so then the problem must be in that extension, probably in the CAML query.

As a reference, this 2010 CSOM code worked ok against a SharePoint 2010 lab. Note that it uses GetItemByID:

        ClientContext _ClientContext = new ClientContext("http://team/sites/Team1/");
        _ClientContext.Credentials = new NetworkCredential("administrator", "*****", "corp");
        Principal user = _ClientContext.Web.EnsureUser(@"corp\administrator");
        var _List = _ClientContext.Web.Lists.GetByTitle("Shared Documents");
        var _Item = _List.GetItemById(23);
        var roleDefinition = _ClientContext.Site.RootWeb.RoleDefinitions.GetByType(RoleType.Reader);
        var roleBindings = new RoleDefinitionBindingCollection(_ClientContext) { roleDefinition };
        _Item.BreakRoleInheritance(false, true);
        _Item.RoleAssignments.Add(user, roleBindings);
        _ClientContext.ExecuteQuery();
Puggree answered 26/5, 2017 at 17:20 Comment(1)
Unfortunately, I had no access to a computer last week due to unforeseen circumstances. How do I specify the file instead instead of an GetItemById?Vagrom
G
2

I assume that andresm53 is right about you using the extension method he mentioned.

To get this method to work on files you need to query by FileLeafRef (file name) and make sure that you add FileLeafRef to query ViewFields.

/edit

One more very important thing, limit file query to exact folder with:

query.FolderServerRelativeUrl = System.IO.Path.GetDirectoryName(url).Replace("\\", "/");

Working code below:

void Main()
{
    ClientContext context = new ClientContext("https://sharepoint.oshirowanen.com/sites/oshirodev/");
    context.Credentials = new NetworkCredential("user", "pass", "oshirowanen.com");
    Principal user = context.Web.EnsureUser(@"oshirowanen\tom");
    ChangeItemPermissions(context, "/sites/oshirodev/Library1/Folder1/File1.docx", "Library1", user, RoleType.Reader);
}

// Define other methods and classes here
public static ListItem LoadItemByUrl(List list, string url)
{
    var context = list.Context;
    string ext = System.IO.Path.GetExtension(url);

    var query = new CamlQuery();
    if (string.IsNullOrEmpty(ext))
        query.ViewXml = String.Format("<View><RowLimit>1</RowLimit><Query><Where><Eq><FieldRef Name='FileRef'/><Value> Type='Url'>{0}</Value></Eq></Where></Query></View>", url);
    else
    {
        query.ViewXml = String.Format("<View><ViewFields><FieldRef Name=\"FileLeafRef\" /></ViewFields><Query><Where><Eq><FieldRef Name=\"FileLeafRef\" /><Value Type=\"Text\">{0}</Value></Eq></Where></Query><RowLimit>1</RowLimit></View>", System.IO.Path.GetFileName(url));
        query.FolderServerRelativeUrl = System.IO.Path.GetDirectoryName(url).Replace("\\", "/");
    }

    var items = list.GetItems(query);
    context.Load(items);
    context.ExecuteQuery();
    return items.Count > 0 ? items[0] : null;
}

public void ChangeItemPermissions(ClientContext context, string url, string listName, Principal user, RoleType type)
{    
    var list = context.Web.Lists.GetByTitle(listName);
    var item = LoadItemByUrl(list, url);
    var roleDefinition = context.Site.RootWeb.RoleDefinitions.GetByType(type);
    var roleBindings = new RoleDefinitionBindingCollection(context) { roleDefinition };
    item.BreakRoleInheritance(false, true);
    item.RoleAssignments.Add(user, roleBindings);
    context.ExecuteQuery();
}
Graduation answered 26/5, 2017 at 20:23 Comment(1)
Added further bounty just for this answer as I was unable to accept an answer last week due to unexpectedly not having access to a computer. This answer works great. Thanks for the help!Vagrom
B
1

You aren't loading anything in your context. You need to Load your context with "queries" to execute, if you execute withou loading, it doesn't do anything. This may need some slight changes, but the concept is correct.

var _List = _ClientContext.Web.Lists.GetByTitle("Library1");
var _Item = _List.LoadItemByUrl("/sites/oshirodev/Library1/Folder1");
_ClientContext.Load(_Item);
_ClientContenxt.ExecuteQuery(); 

var roleDefinition = _ClientContext.Site.RootWeb.RoleDefinitions.GetByType(_SharePoint.RoleType.Reader);
_ClientContext.Load(roleDefinition);
_ClientContenxt.ExecuteQuery();

var roleBindings = new _SharePoint.RoleDefinitionBindingCollection(_ClientContext) { roleDefinition };
_Item.BreakRoleInheritance(false,true);
_Item.RoleAssignments.Add(user, roleBindings);

_ClientContext.Load(_Item);
_ClientContext.ExecuteQuery();
Baird answered 23/5, 2017 at 16:30 Comment(3)
I've just tried that, but I still get the same error message, if I include File1.docx.Vagrom
does this help? morgantechspace.com/2016/04/…Puggree
@andresm53, I have attempted that code before, but i think it's for a newer version of sharepoint. It gives me 2 errors cannot convert lambda pxpression and does not contain a definition for SiteUsers. I am using SharePoint 2010.Vagrom
L
0

Try this.

 static void Main()
        {
            string siteUrl = "Your site url";
            ClientContext clientContext = new ClientContext(siteUrl);

            var list = clientContext.Web.Lists.GetByTitle("JZhu");
            var items = list.GetItems(CamlQuery.CreateAllItemsQuery());
            clientContext.Load(items);
            clientContext.ExecuteQuery();

            clientContext.Load(clientContext.Web.SiteGroups);
            clientContext.ExecuteQuery();

            GroupCollection oSiteCollectionGroups= clientContext.Web.SiteGroups;
            foreach (Group grp in oSiteCollectionGroups)
            {
                Console.WriteLine(grp.Title);
                if (grp.Title == "My group")
                {
                    oGroup=gpr;
                    break;
                }
            }

            foreach (var item in items)
            {
                var folder = GetListItemFolder(item); //get Folder
                Console.WriteLine(folder.Name);
                if (folder.Name=="Folder 1" || folder.Name=="Folder 2")
                {
                    item.BreakRoleInheritance(false);
                    RoleDefinitionBindingCollection collRoleDefinitionBinding = new RoleDefinitionBindingCollection(clientContext);

                    //set role type
                    collRoleDefinitionBinding.Add(clientContext.Web.RoleDefinitions.GetByType(RoleType.Reader));
                    //oGroup - your group
                    item.RoleAssignments.Add(oGroup, collRoleDefinitionBinding);

                    clientContext.ExecuteQuery();
                }
            }
        }

        private static Folder GetListItemFolder(ListItem listItem)
        {
            var folderUrl = (string)listItem["FileDirRef"];
            var parentFolder = listItem.ParentList.ParentWeb.GetFolderByServerRelativeUrl(folderUrl);
            listItem.Context.Load(parentFolder);
            listItem.Context.ExecuteQuery();
            return parentFolder;
        }
Lawman answered 29/5, 2017 at 10:16 Comment(0)
S
0

I guess your problem is related to the path you're using:

 _Item = _List.LoadItemByUrl("/sites/oshirodev/Library1/Folder1/File1.docx");

Try this

 Uri filename = new Uri(@"http://server//oshirodev/Library1/Folder1/File1.docx");

 string server = filename.AbsoluteUri.Replace(filename.AbsolutePath, "");

 Microsoft.SharePoint.Client.ClientContext clientContext = new Microsoft.SharePoint.Client.ClientContext(server);

_ClientContext.Credentials = new NetworkCredential("user", "pass", "oshirowanen.com");

_SharePoint.Principal user = _ClientContext.Web.EnsureUser(@"oshirowanen\tom");

var roleDefinition = _ClientContext.Site.RootWeb.RoleDefinitions.GetByType(_SharePoint.RoleType.Reader);
var roleBindings = new _SharePoint.RoleDefinitionBindingCollection(_ClientContext) { roleDefinition };
_Item.BreakRoleInheritance(false,true);
_Item.RoleAssignments.Add(user, roleBindings);

_ClientContext.ExecuteQuery();
Scuba answered 31/5, 2017 at 12:31 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.