Question
An anonymous user asks, “i want to prevent the user to delete a folder in document Library, if user selects the folder and clicks an delete document icon on ribbon, he is only able to delete the files in the folder not the folder itself. how can i do this?”.
Answer
Preventing users from deleting items in SharePoint is a common issue. The recycle bin in SharePoint 2010 helps prevent the permanent deletion of files, folders, and sites, but you still need administrative assistance sometimes to restore the item. Ideally, the user’s security permissions should be configured to restrict their access so they don’t even have the option to delete. You could break the security inheritance on the folder and change the permissions so that certain users cannot delete the folder, but the files in the folder will inherit the authorization permissions. You could also break the inheritance of each file in the folder, but that would be time consuming and hard to maintain when new files are added. You could probably create a workflow to give each added file the correct permissions, but all the unique permissions would get messy to maintain in the future.
To prevent any item from being deleted in a list or a site I would use an event handler if security permissions will not due. Event handlers are a compiled module of custom managed code that responds when specific SharePoint triggering events take place. In our case, we would want attach our event handler to the list and wait until the list fires an ItemDeleting event. An ItemDeleting event will run your custom code just before it starts deleting the folder. In your code you want to stop SharePoint from executing the rest of the SharePoint deletion code by cancelling the event.
Below are the instructions on how to create an event handler to stop a folder from being deleted:
- Start Microsoft Visual Studio 2010.
- On the File menu, point to New, and then click Project.
- In Project Types, under C#, select Event Receiver.
- In the SharePoint Customization Wizard under What local site do you want to user for debugging?, type the address to the site that contains the document library (ex: http://intranet.contoso.com/hr/).
- In the SharePoint Customization Wizard, choose Deploy as a sandboxed solution. Click Next.
- In the Choose Event Receiver Settings dialog, select List Item Events in the What type of event receiver do you want? dropdown.
- In the What item should be the event source? dropdown, choose Document Library.
- Choose the An item is being deleted option in the Handle the following events list. Click Finish.
- In the EventReceiver1 file that is created, insert the following code in the ItemDeleting method:
public override void ItemDeleting(SPItemEventProperties properties) { //A Try Catch statement to capture any unexpected errors try { //Check to make sure the list item we are looking at is a folder if (properties.ListItem.Folder != null) { //Get folder object SPFolder folder = properties.ListItem.Folder; //Check folder name to make sure we have the correct folder if (folder.Name == "Name of your folder") { //Cancel the delete event with an error message properties.Status = SPEventReceiverStatus.CancelWithError; //Create an error message so the user knows why the folder can't be deleted properties.ErrorMessage = "This folder is restricted from being deleted."; } } } catch (Exception e) { //Create an error message so you know in the event logs what happened and where the error occurred. throw new Exception("Restrict Folder Deletion Event Handler: Exception: [" + e.ToString() + "]."); } }
- In the solution explorer, delete the element.xml file because we do not need it for a single document library.
- In the solution explorer, click on the EventReceiver1 and view the folder properties.
- Under Feature Receiver in the Safe Control Entries properties, click on Collection and then the … button.
- If there not a list item under Members on the Safe Control Entries screen, then click the Add button and then press the OK button to add a safe control entry for your DLL in the web application’s web.config.
- In the solution explorer, right click on the Feature1 and click the Add Event Reciever menu item to create a event receiver cs file for your feature.
- In the Feature1.EventReceiver.cs file that was created, insert the following code in the FeatureActivated and FeatureDeactivating methods:
//Define variables string listName = "YourListName"; string receiverName = "Event Receiver Name"; string assemblyFullName = "EventReceiverProject1, Version=1.0.0.0, Culture=neutral, PublicKeyToken=94de0004b6e3fcc5"; string assemblyClassName = "EventReceiverProject1.EventReceiver1"; int sequenceNumber = 2001; string receiverData = "Data"; public override void FeatureActivated(SPFeatureReceiverProperties properties) { //A Try Catch statement to capture any unexpected errors try { //Get current SharePoint site the feature was activated on using (SPWeb web = (SPWeb)properties.Feature.Parent) { //Get List SPList list = web.Lists[listName]; //Get event handlers for the list SPEventReceiverDefinitionCollection eventReceivers = list.EventReceivers; //Create the event handler definition object SPEventReceiverDefinition eventReceiver = eventReceivers.Add(); //Set event handler properties eventReceiver.Name = receiverName; eventReceiver.Assembly = assemblyFullName; eventReceiver.Class = assemblyClassName; eventReceiver.SequenceNumber = sequenceNumber; eventReceiver.Data = receiverData; eventReceiver.Type = SPEventReceiverType.ItemDeleting; //Create the event handler definition object with data eventReceiver.Update(); //Update List list.Update(); } } catch (Exception e) { //Create an error message so you know in the event logs what happened and where the error occurred. throw new Exception("Event Handler Feature: Exception: [" + e.ToString() + "]."); } } public override void FeatureDeactivating(SPFeatureReceiverProperties properties) { //A Try Catch statement to capture any unexpected errors try { //Get current SharePoint site the feature was deactivated on using (SPWeb web = (SPWeb)properties.Feature.Parent) { //Get List SPList list = web.Lists[listName]; //Get event handlers for the list SPEventReceiverDefinitionCollection eventReceivers = list.EventReceivers; //Define new Guid variable from the eventReceiver ID Guid eventReceiverID = new Guid(); //Search through all the event handlers in the list foreach (SPEventReceiverDefinition eventReceiver in eventReceivers) { //If the event handler matches our event handler name if (eventReceiver.Name == receiverName) { //Save the event handler guid eventReceiverID = eventReceiver.Id; } } //If a guid is found for the event handler if (eventReceiverID != null) { //Get the event handler for the event hander collection of the list SPEventReceiverDefinition eventReceiver = eventReceivers[eventReceiverID]; //Delete the eventReceiver reference eventReceiver.Delete(); //Update the list list.Update(); } } } catch (Exception e) { //Create an error message so you know in the event logs what happened and where the error occurred. throw new Exception("Event Handler Feature: Exception: [" + e.ToString() + "]."); } }
- Now that your event handler will be attached to your list programmatically, press F5 to compile and deploy the solution.
- Navigate to your document library list and select an item in the list. Click the Delete Item button on the Server ribbon.
- Your error message should appear and the folder will not be deleted.
For more information on event handlers visit Events in SharePoint Foundation 2010, Using Event Receivers in SharePoint Foundation 2010 (Part 1 of 2), and Using Event Receivers in SharePoint Foundation 2010 (Part 2 of 2).