Category Archives: C#

SharePoint Limited Access Permission – Careful when using BreakInheritance

This post is for SharePoint Developer or Admin who deals with SharePoint APIs (PowerShell or C#)

I have recently discovered a killing command from SharePoint that could kill your SharePoint Day. At times, you will need to configure a Unique permission to document/file for Content Sharing purposes. Typical feature which your end user will ask is to Share a certain document or folder to only certain group of people. Although it is recommend to Share using SharePoint Group which more manageable when it comes to a big Content management system, sometime you prefer to make a easier way out by just assigning to the Individual Users. (Less group to manage and you CAN Afford to loss the permission when things go wrong… and yes, this post will tell you why and how it goes wrong)

With much user friendly SharePoint “Share With” feature, you could break inheritance, grant new user permission so on and so forth. You can’t stop user from doing it, cause it is so apparent nowadays in SharePoint 2013

break and grant permission

Or you can run PowerShell script to Get the ListItem (or to be precise, SPSecurableObject Base Type object), subsequently execute  $object.BreakInheritance($false) and start adding SPRoleAssignment object.

If you have noticed this API

void ISecurableObject.BreakRoleInheritance(bool copyRoleAssignments)

 

This command allows you to quickly remove all existing RoleAssignment (from inheriting parent object permission) and so you can start adding Custom permission that you desired.

Important! This is Extremely Dangerous. Why? Because if you carefully loop into the $object.RoleAssignments (SPRoleAssignmentCollection) property, you will discover that some role definition bindings are named “Limited Access”. In SharePoint 2010, you can easily notice this definition through the permission setting page whereas in SharePoint 2013, it is hidden by default (which is more scarier cause you didn’t even know its existence).

Why is this Limited Access permission? There are many articles out there telling you why and why. I’m not gonna cover that here.

But if you really intend to so-called Cleanse the messy permission list that you have already added, the advice is Don’t.

Let me give you an example of how this BreakInheritance way of breaking parent permission can cause you problem.

By executing BreakInheritance(False), you are technically removing ALL Role Assignments from this object, which include the Limited Access permission granted automatically by SharePoint. You will usually see a lot of limited access for Document library and Web, cause the children within it are likely to be requested (by user) to have unique custom permission.

reset and break with false

 

For Example

  • Web 1 
    • Document Library A
      • Folder a (Break inheritance)
        • File
      • Folder b 

Assuming you have a “Folder a” with broken inheritance permission for UniqueUserA. Upon granting this unique permission, SharePoint automatically creates a Role Assignment for UniqueUserA with “Limited Access” permission to Web1 because Document Library A is inheriting permission from Web1 and hence it is added into Web1 instead.

Somehow or other, you need to change/script to change the permission for Web 1 object up there (the one with Limited Access), by purging the limited access granted to UniqueUserA. the permission that you granted previously to “Folder a” will be DELETED automatically! Yes, Automatically, seamlessly, without-your-knowingly.

And what is going to happen after that? Your lovely user UniqueUserA will send email you, telling you that he has no permission to access files or folder a. Not to mention if you have many Unique permission granted for sub folders within that document library.

Now, the Task you need to ask yourself is – How to still be able to remove existing permission while preserving the Unique configured child permission.

I came out with a simple PowerShell script that allows me to clear the permission. I think it can be easily translated into C# for code behind implementation.


#############################################################################
# Clearing Permission while keeping Limited Access user - Important #
#############################################################################
function ClearPermission
{
 Param([Microsoft.SharePoint.SPSecurableObject]$obj)

 $roleAssignments = $obj.RoleAssignments;
 $count = $roleAssignments.Count;
 for($i = 0; $i -lt $count ; $i++)
 {
  $roleAssignment = $roleAssignments[$i];
  $bindingCount = $roleAssignment.RoleDefinitionBindings.Count
  $clearCounter = 0;
  for($j = 0; $j -lt $bindingCount ; $j++)
  {
   $roleBinding = $roleAssignment.RoleDefinitionBindings[$clearCounter];
   if($roleBinding.Name -ne "Limited Access")
   {
    $roleAssignment.RoleDefinitionBindings.Remove($clearCounter);
   }
   else
   {
    $clearCounter++;
   }
  }
 }
 $obj.Update();
}

What it simply does is to loop through the Role Assignment Collection and delete only Binding with definition of Limited Access. Note that I do not loop via ForEach loop as when you looping the collection, you cannot delete the object within the collection. You can try and you will end up seeing error.

How to use:


Add-PSSnapin Microsoft.SharePoint.PowerShell

$w = Get-SPWeb https://yoursite

ClearPermission $w;

#add your unique permission here.

#additional code to add role assignement (permission)

$user = $w.EnsureUser("domainX\LoginNameY");

$roleAssignment = New-Object Microsoft.SharePoint.SPRoleAssignment($user);

$roleDefinition = $w.RoleDefinitions["Full Control"]

$roleAssignment.RoleDefinitionBindings.Add($roleDefinition)

$w.Update();

Hope it helps

Change the default settings for newly created SharePoint Document Library

Thought it would be helpful to share this.

As you know, SharePoint Document Library by default, if you just simply create one, are not turned on with Version Control. This could rather prone to human mistake or mis-configuration whenever you need to provision a new document library.

This is how I fulfill this.

Imagine i need to have the version control turn on, and with the following settings

version history limits

What you need to do is to create a custom event receiver with List Added handler

Fire up your Visual Studio, create a SharePoint Farm solution and add your new event receiver

New Event Receiver

Select List Events and tick “A list was added”

Event Receiver Setting

In the ListAdded method, kindly do a checking before the code is firing, the below TemplateId 101 means Document Library


if (properties.List != null && properties.TemplateId == 101 && properties.Web != null)
 {

try
 {
 SPList docList = properties.List;//.Lists[properties.ListId];
 docList.EnableVersioning = true;
 docList.EnableMinorVersions = true;
 docList.MajorVersionLimit = 3;
 docList.MajorWithMinorVersionsLimit = 20;

//this.EventFiringEnabled = false;
 docList.Update();
 }
catch (Exception ex)
 {

//Do something...

}

}

If you do this, you will hit this error when creating a new document library

The security validation for this page is invalid. Click Back in your Web browser, refresh the page, and try your operation again.

This is due to the Synchronisation mode for ListAdded event by default is “Asynchronous”.
You MUST DO the following

Open the Element.xml created via Visual Studio.
Add a “<Synchronization>Synchronous</Synchronization>” node into your receiver xml

<Receiver>
 <Name>SharePointSettingEventReceiverListAdded</Name>
 <Type>ListAdded</Type>
 <Assembly>$SharePoint.Project.AssemblyFullName$</Assembly>
 <Class>MOT.EventReceiver.SharePointSettingEventReceiver.SharePointSettingEventReceiver</Class>
 <SequenceNumber>10000</SequenceNumber>
 <Synchronization>Synchronous</Synchronization>
 </Receiver>
 </Receivers>

Deploy your solution and hooray~

SharePoing Global Navigation for SubSite not showing Parent Sites Nodes

Despite setting the properties “UseShared” for SPWeb object to “True”, it does not show the correct Parent’s Global Navigation nodes.

I have this requirement where the subsites (3rd level, where 1st level being the root web) in second level web (which is also inheriting from root web) needs to display the global navigation nodes.

After trying


mySubSite.Navigation.UseShared = true;

it does not show the actual parent’s global navigation, instead, it shows “[Portal Name]” which redirect to root web’s home page. If you go to “Site Settings” > “Navigation” and click “Save” button, it will subsequently show the correct nodes. Meaning, doing it in UI is fine but doing it programmatically is NOT OKAY!.

After digging into the Microsoft.SharePoint.Publishing.dll. I found this is the workaround.

 Microsoft.SharePoint.Publishing.Navigation.WebNavigationSettings settings = new Microsoft.SharePoint.Publishing.Navigation.WebNavigationSettings(web);
 settings.GlobalNavigation.Source = Microsoft.SharePoint.Publishing.Navigation.StandardNavigationSource.InheritFromParentWeb;
 settings.Update();
<pre>

This will then make the subsite showing the correct one.

Compilation Error CS1061 ‘x.dll’ does not contain a definition for ‘Web’

Faced this problem when trying to run my web application. No error thrown in the Design view and no warning generated. However, hitting F5 gives me this error message which really cracked my head.

CS1061: ‘Telerik.Web.UI.RadComboBox’ does not contain a definition for ‘Web’ and no extension method ‘Web’ accepting a first argument of type ‘Telerik.Web.UI.RadComboBox’ could be found (are you missing a using directive or an assembly reference?)

Looking into the Error highlighted in the screenshot does not help at all. “Web” is not mentioned or used anywhere in my ASPX page.

Googling around and don’t seem to be able to find any solution. Thought it would be good to share the resolution i found after few hours!

Resolution

The solution is plain SIMPLE! Which is to Remove Attribute “Height” away. Holy Cow.

It seem that Telerik RadTextBox does not support “Height” attribute. Instead, you should use Rows or Cols….

[Updated]

Found the source of problem is that i added a RadComboBox with ID=”System“. This is a system reserved keyword. After renaming it to other name. The error is now gone. Height and Width is now working as it is!