by

Versioning Settings and Picture Libraries Issues


Can you imagine a news website without any sort of control for the pictures being uploaded to the front page?
Content types (CT) are a big part of any well-planned content management system. In our enterprise we have a dedicated content team who is in control of the CTs for the CMS. They are extremely good at what they do and they really have a good grasp about the business, its processes, documents and metadata. Unfortunately, to deal with legacy systems is the issue and our legacy issue is to unify all the websites and its lists with its correct content types.
Early this week I had to find a way to setup and modify the versioning settings for the lists of our sites. As we can see, this can easily be done via Site Settings option. The issue here is that we have hundreds of sites, not to mention all the Team Sites, across all the enterprise. And possibly thousands of libraries. Meaning: It is impracticable to do this via UI. So, programmatically was the choice.
splist-versioning-control 
And honestly, this choice did not look so hard… at first at least.
The SPList object model exposes to us all the properties necessary do control these options enumerated in the page (as we will see in our code later) but make no mistake, the solution is not as trivial as one might think. The biggest problem is here: Enable Content approval.
Let’s do a short parenthesis here and reflect about this matter, from the business point of view.
And that’s a vital piece of functionality. Imagine a news website, like www.CNN.com or www.BBC.co.uk, possibly with hundreds of employees/contractors  working on the website content. They write news stories, upload pictures etc. As an editor, would you give them any level of access they want?  Of course not. In the ideal model, we must have a group of people responsible to approve the content being displayed to the public (i.e. using the Content Approver role). The last thing an editor wants to see is some crazy text flaming around everyone and displaying unacceptable behaviour (i.e. a text with racist remarks), or a picture that does not reflect the news report, or even worse, a picture that can potentially harm the viewers for being shown in the public.
To make short a long story: A content-based enterprise needs someone to be responsible for content approval.
Now, coming back to our technical venue.
 
splist-versioning-control-2
 
Of course we want to enable content approval. So we go ahead and call:
SPList.EnableModeration = true
And out of the blue during some point of the execution an exception is thrown every time this line is called. That was a surprise for me.
So I went on to MSDN to read about the property and the object and…no clues or answer to be found. I went to see what happened with the other libraries using the same code. In the vast majority of the libraries where I ran that code, they let me update this property, but a few did not. so, what went wrong?
Then after some research and no clear answer, I decided to debug the SharePoint DLL via code reflection. I went to see on MSDN which of the SharePoint DLLs contains the SPList object and as indicated it is the Microsoft.SharePoint.DLL.
 microsoft-sharepoint-assembly
I’ve got the DLL and then compared the signature of my reflected copy against the copy installed in the GAC. Just to make sure we all were talking about the same “story”.
    splist-enable-moderation-2
Note the member signature. There is nothing unusual here. It is a get / set, but let’s take a closed look at the SET method:
splist-enable-moderation-1
Interesting. “if the base template is a picture library then ERROR”.
Regardless of any test or comment. If we are dealing with a picture library, it seems to me that you can not enable content approval for it in SharePoint and immediately an exception is thrown.
IMO, I find this quite odd because in other instances, similar to this case, it is common place to expose another member to validate this test. For example, I would look for something like along the lines SPList.CanEnableContentApproval.
Anyway, moving on, problem found. I am not sure why content approval is not available for picture libraries. Indeed, if you go to the versioning settings for a picture library you won’t even see these options listed.
The solution : As of today, for me the way out of this is to use document libraries to handle the approval process for images. (if you have any other strategies for this matter, please let me know)
Now let’s take a look at the code to handle the full versioning control. Enjoy.
 
    1         /// <summary>
    2         /// Applies the versioning settings to the list.
    3         /// </summary>
    4         /// <param name="selectedList">The selected list.</param>
    5         public void ApplyVersioningSettings(Microsoft.SharePoint.SPList selectedList)
    6         {
    7             // enable content approval for this list
    8             // moderation is not supported for picture library types
    9             if (selectedList.BaseTemplate != SPListTemplateType.PictureLibrary)
   10                 selectedList.EnableModeration = true;
   11 
   12             // enable versioning for this list
   13             selectedList.EnableVersioning = true;
   14 
   15             // set security to only users who can approve and the actual content author
   16             selectedList.DraftVersionVisibility = DraftVisibilityType.Approver;
   17 
   18             //enable minor versions for this list
   19             selectedList.EnableMinorVersions = true;
   20 
   21             //set YES to forced checkin/checkout required
   22             selectedList.ForceCheckout = true;
   23         }
 
See you later

By

by

How to Modify SharePoint List RSS Settings Programmatically

RSS is a great thing. It streamlines easily the communication between a content provider and its readers. RSS nowadays are everywhere. News sites, blogs, content driven sites. By subscribing to a RSS feed you can reach a broader audience by eliminating the need of a computer, just have a mobile with RSS reader capabilities and you are good to go. As a powerful content management tool, of course SharePoint enables RSS syndication for its contents.
Let’s take a look at the UI page where we can configure the RSS feed of a document library:
sharepoint-configure-rss-setting
So, can we customize the RSS features exposed by a SharePoint library programmatically ? The answer is yes, but unfortunately this task is not as straight forward as one might think.
If you look the SPList properties, you will not find anything related to them. If you look at the SPListItems, you will not find anything related to them.
So where are these properties? They are in fact in the RootFolder property of the list. The RootFolder is an object of type SPFolder and sets various properties for the files and contents associated with the list as a collection of items.
And guess where these RSS feeds settings are specified? Yes, in that same collection, exposed as a key-value pair. But even if you try to inspect that with your preferred tool, you won't be able to see it clearly. Not even with SharePoint Manager sometimes. For example, take a look at these 2 RootFolders properties, from 2 different SPLists, being visualized with SharePoint Manager.
spm-sharepoint-manager-splist-rss-2
spm-sharepoint-manager-splist-rss-1
So…You see, the first one does not expose any RSS related property values, but the other one does. That's because the later has  SPListTemplateType.DocumentLibrary as its base type.
Since the SharePoint operations and behaviours rely extremely on the exposed APIs, we would assume these are the kind of stuff you would have access via an API call. I for one was not expecting to modify straight into the property values of a key-value par exposed by a SharePoint collection itself. Yeah, pretty tricky. SharePoint does its own things by its own ways. 
Anyway, these are the things you can modify from our RSS settings screen:

sharepoint-configure-rss-setting2
1) EnableSyndication : internal property, refer to the code below
2) vti_rss_LimitDescriptionLength : Controls if the item content will be exposed complete in the feed of just the first 256 characters.
3) vti_rss_ChannelTitle : name the RSS feed
4) vti_rss_ChannelDescription : Short text to describe the feed
5) vti_rss_ChannelImageUrl : Specifies which image will be displayed when a RSS reader consumes the feed
6) vti_rss_DocumentAsEnclosure : Indicates if will any documents associated with the feed are included as enclosure. ( I assume, becaue I have not tested that to explain better )
7) vti_rss_DocumentAsLink : Indicates if you can expose the documents included in the feed as link direct to the file. Very common for podcast RSS feeds, for example.
8) vti_rss_ItemLimit : Limits how many items are going to be exposed in the feed
9) vti_rss_DayLimit : Limits how many days will the feed content display. This will work combined with the vti_rss_DayLimit; the most restrictive one, wins.







Also there are some more fields that are not exposed by the UI, but still exists in property collection:
vti_rss_DisplayRssIcon : Indicates if the image in the vti_rss_ChannelImageUrl is an icon file. It will be displayed in the navigation bar of web browsers, for example.
vti_rss_DisplayOnQuickLaunch : I did not test that, but I imagine it will add the feed to the quick launch links in the homepage.
After all the settings were done, there is one more catch: Call the Update() method not from the list, but from the RootFolder object.

Now, the code to set them:

    1         public void ApplyRSSSettings(Microsoft.SharePoint.SPList selectedList)
    2         {
    3             // display RSS for this list
    4             selectedList.EnableSyndication = true;
    5 
    6             // set NO to truncate RSS multiline text to 256 chars
    7             selectedList.RootFolder.Properties["vti_rss_LimitDescriptionLength"] = 0;
    8 
    9             // set NO to include file enclosures
   10             selectedList.RootFolder.Properties["vti_rss_DocumentAsEnclosure"] = 0;
   11 
   12             // set YES to link rss to files
   13             selectedList.RootFolder.Properties["vti_rss_DocumentAsLink"] = 1;
   14 
   15            
   16 
   17             // set RSS maximum items to 25
   18             selectedList.RootFolder.Properties["vti_rss_ItemLimit "] = 25;
   19 
   20             // set RSS maximum days to 7
   21             selectedList.RootFolder.Properties["vti_rss_DayLimit"] = 7;
   22 
   23             // commit the changes to the list
   24             selectedList.RootFolder.Update();
   25         }

See you later

By

by

How to apply custom permissions to a list in SharePoint

In Windows SharePoint Services, all the lists are assigned inherited permissions from the container site by default. So how can we programmatically change these permissions to our own?
First we must understand how WSS controls access to its objects.
sharepoint-splist-Untitled
The access model for websites, lists, document libraries, picture libraries, task lists, workflows etc follows a role-based membership model. One might even say that's quite expected since WSS extends the capabilities of the ASP.NET as an application itself and .NET has a very flexible role-membership model framework. 
In this role-membership system, SharePoint users are assigned to specific roles, specifying what kind of access he/she will have (full access, read-only, write-access etc).
You can do this just like SQL Server, where groups are created and then users are included in these groups. The next step is to go to the Sharepoint object (a list, for example) and assign permissions to that group; but SharePoint extends this model one step further by creating role assignments.
sharepoint-splist-Untitled5   sharepoint-splist-Untitled4
A Role assignment is an object that binds roles and groups/users. This role assignment object can then be grouped in collections and that's where sharepoint do the trick: All the list objects in WSS implement a collection os role assignments which makes this approach the best and most scalable way to set permissions. Such a model can even be extended to apply to specific permissions to specific list items within the list. Even websites implement a collection of role assignments.
sharepoint-splist-Untitled3
Can you create a role assignment for a specific user without specifying the role?
Yes, we can. The user will be listed in the collection for the object but he won't have access to the object. So it's really pointless doing this.
Can we cascade permissions across lists?
Yes, we can. Not only across lists but all the objects. By default SharePoint will let you inherit the object's parent permissions. This behaviour, by the way, can also be modified programmatically as we will see later.
Can we assign specific permissions for just a group of items within a list?
Yes. And the process is very similar to the one we are going to demonstrate here.
What is the highest group on a SharePoint site collection? Is there such a super group?
yes, it is called cross-site group. It is an OTB functionality and by default has 3 sub-groups: Owners, members and visitors. Owners are the site administrators, members are the people who can have write-access to the site, visitors are the guests and can only read information.
sharepoint-splist-custom-permissions-1
So, any given user only becomes an effective SharePoint user once it is assigned to a role. You can take a look at the base permissions querying Microsoft.SharePoint.SPBasePermissions.
Now...In our case, we will remove all the predefined permissions for a given task list and set our own permissions. Only the people who are site administrators will have access to it.
sharepoint-splist-Untitled2
First thing is to break the inheritance to the list. That will untie the link between the list and its parent's permissions. The immediate effect you will notice on this command is that the UI will change accordingly.
sharepoint-splist-custom-permissions-0
NOtice how the menu in the UI get updated. You won’t see the tab refferring to the parent’s permissions anymore, instead you will be presented with an option to edit the permissions by user and a new option to revert the operation, which is to inherit again the permissions of parent.
 sharepoint-splist-custom-permissions-00.jpg
Returning to our case. Once we break the relationship to the parent,  we will need remove all the permissions in the list. If we could take a look at the UI during the code execution we would see a list like this.
sharepoint-splist-custom-permissions-2
with absolutely no users with permission to access the list. Note how dangerous this operation can be. If for some reason we left the code at this stage of execution we would compromise the SharePoint's health status and the implications can be very upsetting specially if the list is touched by many users or displayed in other sites.
So the next step is to setup the user we want to give the permission. In our case we want to give access to this list only to people in the administrators group.
Take a minute to see how we perform this.
Remember when we talked about the Roles and the Groups. Well, these are represented by the classes SPRole and SPGroup. So we will at some point need to have that information at hand. We extract the desired role R out of our website roles collection and our group G out of the website group collection.
sharepoint-sprole                 sharepoint-spgroup
There is a special trick here. In order for the group G useful in anyway, we need give a live identity to it. We will use the SPPrincipal object for that. SPPrincipal comes from the SharePoint super-class SPMember and it is the object that represents an user or a group within a website in SharePoint. Any user and any group attached to a site in SharePoint is automatically a SPPrincipal object and he will provide all the role-membership mechanisms for integration with the system.
sharepoint-Untitled
In older versions of Windows SharePoint Services SPRole and SPGroups were used combined and straight to configure the permissions. These objects are now obsolete for that function and the recommended approach is to instantiate a SPRoleAssignment. The SPRoleAssignment will be produced by associating the selected group plus the principal identity. Once you have your SPRoleAssignment setup based on the group, you then add the SPRole to the exposed collection.
The next steps are very direct. We bind the SPRole to the SPRoleAssignment…
sharepoint-sproleassignment 
And we add the SPRoleAssignment to the RoleAssignmentCollection exposed by the SPList.
sharepoint-sproleassignment-collection
We create a SPGroup and SPRoleDefinition objects based upon the existing site groups and roles in our site. The reference to the site can be accessed via the SPList object itself. Since we have that information now in our hands, we can then combine them with a SPRoleAssignment object and then add this assignment to the collection of assignments that belongs to the list. Our method is pretty atomic, and at some point a SPList.Update() call must be made in order to persist the changes we’ve done.
If everything went according to our plan, we should now see a list like this in our UI:
sharepoint-splist-custom-permissions-3

If you want to apply specific permissions to the items of this list, the only additional piece of code you must add is a loop around the SPList items and set the properties in the chosen SPLIstItem object.
Now the code:

   11         private void SetPermissionsForTheList(SPList selectedList)
   12         {
   13             // breaks the inheritance from the parent
   14             selectedList.BreakRoleInheritance(true);
   15 
   16             //removes all the permissions from the list, except for 'site - admins'
   17             while (selectedList.RoleAssignments.Count > 0)
   18                 selectedList.RoleAssignments.Remove(0);
   19 
   20             if (selectedList.RoleAssignments.Count == 0)
   21             {
   22                 // get the defined site admins group
   23                 SPGroupCollection groupCollection = selectedList.ParentWeb.SiteGroups;
   24                 SPGroup group = groupCollection["Site - Admins"];
   25 
   26                 // get the full access role definition
   27                 SPRoleDefinitionCollection roleDefCollection = selectedList.ParentWeb.RoleDefinitions;
   28                 SPRoleDefinition roleDefinition = roleDefCollection [0];
   29 
   30                 // create a role assignment based on the site admin group
   31                 // and bind to the full access role definition
   32                 SPRoleAssignment roleAssignment = new SPRoleAssignment((SPPrincipal)group);
   33 
   34                 roleAssignment.RoleDefinitionBindings.Add(roleDefinition);
   35 
   36                 selectedList.RoleAssignments.Add(roleAssignment);
   37             }
 
As a final note, remember that all this can be accomplished via the interface and by doing this SharePoint will verify and test if any rule isn't being broken during the process. By doing this programmatically you are easily introducing a new level of complexity in the SharePoint ecosystem. Via code, you can set any kind of permissions you want to any given user. PLAN AHEAD. Make sure you are not overwriting permissions that can be conflicting with other areas in the site collection.
See you later.

By