How do I make a list item read-only - sharepoint

I have a list (assume an issues list) and there is a workflow associated with it. The workflow can adjust the status column of the item to "Closed". Once an item's status is closed, I want to make it read-only so that noone can edit the item or create another workflow instance for that item.
What's the best way to achieve this?

There are item-level permissions that can be set, so you can override list-level permissions on an item-by-item basis. Adding this functionality into your existing workflow probably makes the most sense, but of course there is nothing out-of-the-box that SharePoint provides you.
Luckily, you can extend SharePoint's workflow by creating your own custom actions. The process for doing this in SP2010 is fundamentally the same as 2007; check out this MSDN tutorial for an overview of the process.
There is also a convenient package of custom activities provided in an open-source product called SPDActivities at CodePlex. Specifically of interest to you is the Grant Permission on Item activity. Even if you opt not to use the whole package, you can examine the source code and see about implementing your own version of it (I did something similar for a past project).
Once you have a workflow action for setting an item's permission level, simply add a step to your existing workflow to set Read permission for the affected audience or group.

Have you looked at SPUtility.js? You could get the value of your status field, and then if it is Closed, make the other fields read only (or hide them). This is done using JavaScript that is added in a content editor web part on your EditForm.aspx.
var myChoiceField = SPUtility.GetSPField('Single Choice Field');
if (myChoiceField.GetValue() == 'Closed') {
SPUtility.GetSPField('Field A').MakeReadOnly();
SPUtility.GetSPField('Field B').MakeReadOnly();
SPUtility.GetSPField('Field C').MakeReadOnly();
// etc..
}
Full disclosure.. this is an open source library I maintain. I've tested it with SharePoint 2007 only, but it may also work with SharePoint 2010 (unfortunately I don't have access to a SharePoint 2010 environment to test).

I would attack it one of two ways:
Once the workflow completes and sets the item to Closed, you can break the permissions inheritance from the parent list and set the list item permissions to read only. You could do this within a custom workflow or as either a Workflow or List Item event receiver.
Have an ItemUpdating List Item event receiver that sets properties.Status = SPEventReceiverStatus.CancelWithError if status is Closed.
Personally, I like the first option better as it fits in with SharePoint's security philosophy of not letting the user attempt what they do not have permissions to do. The following code is an example of setting read only permissions on a list item:
item.BreakRoleInheritance(false);
SPRoleDefinition role = web.RoleDefinitions.GetByType(SPRoleType.Reader);
SPRoleAssignment assignment = new SPRoleAssignment(web.AssociatedVisitorGroup);
assignment.RoleDefinitionBindings.Add(role);
item.RoleAssignments.Add(assignment);

Try creating an Event Receiver and handle the deleting event.

Idea (un-tested): Add a custom content type to the list (this will allow you control to edit as an admin later). Have workflow switch to the custom CT one the item is "closed". Add a read-only view of the item data to your EditForm.aspx, and in Designer add class "hidden" to your read-only view. Then add custom css in a CDWP on the page for class .hidden display:none. Then use JavaScript to add/remove that class based on the CT, so that the read-only view is only visible for the custom CT, while the edit wp is visible for all others.
Or use a custom InfoPath form to switch to read-only view based on status...

Related

SharePoint 2010 - Customizing the rendering and behavior of a List field

In my SharePoint List, I have an "Employee" column that is a User type field. I would like to add some custom Business Logic to the processing of this field.
Currently, when the user adds a row, I check to see if the user is an Employee or a Manager and then change the behavior on this column accordingly. I do this by statically rendering the field in my custom "ListForm Rendering Template", just before my custom ListFieldIterator. I simply use a standard SharePoint FormField (and FormLabel) control. In the markup of the FormField control, I specify the FieldName (Employee) and an event handler for the Load event. In this Load event, I will check to see if the current user is an Employee or Manager (using two different SharePoint groups). If the user is an Employee I set the value of the field to the current user (this part works perfectly). I also want to change the field so it can't be modified. I thought I might be able to just change the ControlMode on the field (in the code of the OnLoad Event Handler) to Display, but for some reason this has no effect. The field still renders with the full, people picker editor. Am I not changing the fields control mode soon enough? Or is this simply not the correct approach? The other logic I want to put in is if the user is a Manager, I would like to allow that user to select the person from a list (SharePoint group) of Employees. It may be easier to just use the people picker and limit the selectable users to that group. (I think I can do this with the SelectionGroup property.) Although, it would be better if I could just provide a dropdownlist of users, which I could possibly do with a hidden dropdownlist that I would show and event handlers that I could use (handle event selectedindexchanged) to pull the value selected and populate the (now hidden) Employee (user) field. Does this approach make sense? Assuming all that will work, the real difficulty I am having is with changing the ControlMode (rendering) on the field (when the user is an employee) to a label or some kind of read only control, which is how that field renders when viewing the row, which is why I think if I can just trick the control into thinking it is in Display mode then it should work perfectly!
I am still learning SharePoint, but I am very proficient in ASP .Net. This is why I would like to keep my customizations in this Custom Rendering Template, using code behind and leverage my existing skill set as much as properly.
Any thoughts, opinions or advice? Does anyone know why I can't get the column to switch the "Control Mode"?
I do not think that I fully understand your scenario. Some code samples could help.
But anyway it sounds like you want some heavy customizations of the user field. In that case you might want to have a look at creating a custom field with all its advantages and disadvantages. Have a look at MSDN: http://msdn.microsoft.com/en-us/library/gg132914.aspx
Another option might be - in case you do not want to re-use this column in many list definitions - that you can get away with your custom rendering template and create a custom create/edit form where you implement the specific edit behaviour for the field (plain ASP.NET with some SharePoint controls). Here is a nice walk-through on how to grab a custom edit form from SharePoint designer: http://community.bamboosolutions.com/blogs/sharepoint-2010/archive/2011/05/12/sharepoint-2010-cookbook-how-to-create-a-customized-list-edit-form-for-development-in-visual-studio-2010.aspx
I hope this helps. Kr., Bernd.

How to restrict SharePoint WSS3 users to edit only fields that are in their dedicated views

I have a list with the fields: Title, Client, Project, Description.
There is a view for analysts with the fields visible: Title, Project, Description.
All is fine so far as the analysts work with their views and not with the lists. But when they need to modify the records clicking on Edit, they see and able to modify the 'Client' field too.
How to prevent 'Client' field to be available for editing by the group? is there a way in WSS or I need to look for 3rd party list components?
All fields have a set of properties that determine their visibility in forms, such as "ShowInNewForm", "ShowInEditForm", and "ShowInDisplayForm". There's also some for the file dialog, the list settings page, and a few other places, but that's getting past it. Short answer, yes, you can make the field not show up in the edit form with WSS without needing any 3rd party components.
If you need a field that cannot be seen in the Edit Form by anyone (that is, no one should be able to have it in their form), then you need to modify "ShowInEditForm" to be true. This can't be modified directly through the SharePoint UI, but it is extremely simple using the object model.
If you need certain people to edit it at some point through the SharePoint UI, then you'll instead have to create a custom edit form. That's a bit more complex, so I'll hold off on providing that instruction unless you state you need to go down that route (or someone else passes by this answer and requests it). Nevertheless, it is fully possible with WSS 3.0.
EDIT
If you know already know how to insert inline C# code into an ASPX page, you can perform this very simply using SharePoint Designer. First, follow the instructions from this article, especially make sure you don't delete the default list form web part. Now, in the custom list form you added, make it include every field which anyone will be capable of editing. The last step is to make the form hide those fields for certain people. Let's default them to Visible=false, and flip this switch if the user is allowed them. You can do this either by checking if the current user is part of specified groups, or by checking if the user has a certain permission level only held by people of those groups. You'll basically write some code like the following, I'll use checking for a specified group as the example.
using (SPWeb web = this.Web)
{
SPUser currUser = web.CurrentUser;
string[] listOfGroups = { "Group1Name", "Group2Name", "Group3Name" };
foreach (string groupName in listOfGroups)
{
if (currUser.Groups.Contains(groupName))
{
//Repeat this for each Control, refer to them by their ID. For example, this is for a control with the ID txtTitle.
txtTitle.Visible = true;
}
}
}
If you don't know inline code, you'll have to write a custom ASPX page with a code-behind. Copy EditForm.aspx into a new file - you should do this after setting up a Custom List Form as per the article. You could also build a new ASPX page from scratch, but make sure you include all of the necessary Content placeholders for SharePoint pages. Now, the page currently inherits from Microsoft.SharePoint.WebPartPages.WebPartPage. We need to create custom code that inherits from that class, and change the page to inherit that new custom code instead. In the custom code, override one of the OnLoad or OnInit methods, and include your check for the user's permissions there as detailed earlier. Compile the code, deploy it to your SharePoint server, and it should be functional.
If you want to set fields hidden or display them in new form or edit form page of the list...
Go to the list settings.
In Advanced Settings, enable "Allow management of content types"
By doing so, you will get a List name Link on the List Setting Page.
Open the link and select the fields that you want to hide or uhide using add or remove option.
After saving this, again disable "Allow management of content types" in Advanced Setting...
Thats it :)))

create an eventreceiver for logging changes made by users in lists

I'm working on a SharePoint publishing site and I want to "log" all the changes made by users in a SharePoint list.
Some searches on the web guided me to the EventReceiver.
But my EventReceiver must be generic and attached to all lists in the site collection. The "log list" has several columns like the name of the list in which the event occurred, the name of the modified item, its old value and its new value.
Can someone guides me on how to achieve this?
There's already a provided answer for you on StackOverflow, hurrayy!!
It sounds possible. Create a class that inherits from SPItemEventReceiver and override ItemUpdating. You can use the following code to get the list:
using (SPWeb web = properties.OpenWeb())
{
SPList list = web.Lists[properties.ListId];
}
You can then use list to grab the list's title and URL. Next, compare each DictionaryEntry entry in properties.AfterProperties to the corresponding value in properties.ListItem to get your differences. Then save it to your log list. The trick would be automatically attaching your Event Receiver to each newly created list. Perhaps a timer job would work.
That said...
Before trying any of that, go to your site collection's Site Settings. Under Site Collection Administration, click Site collection audit settings. Under Specify the Document and Item events to audit, check Editing items. Only go with a custom solution if that does not give you what you need.
Would Version history not achieve the same functionality?
You can see what fields were changed by who and when. Though you would have to look at a list by list basis.
You can also access the version history information via the object model if you want to generate reports web part.
Otherwise using Janis Veinbergs link on how to attach a event handler to all lists and Rich Bennema method of getting the values from the updated item in a generic way, though I would use ItemUpdated as you don’t want to change the data that was updated only copy it to another location so there is no need to catch the data before it is submitted to the SharePoint database

How to fire code upon creation of a SharePoint list?

I'm aware of the event receivers on a list for items added etc. However, I have not found a way to fire code upon the creation of a list.
What I'm trying to do is associate a workflow with a list when the list is created (by the user through the UI).
Anyone any ideas?
thanks.
There are a couple of routes you can take...
You can write your own list definition where you have defined the workflow association - That way all lists created based on your list definition, will contain your workflow on default.
Or... depending on your workflow... write an EventReceiver your attach to all lists of the type you wish to attach your workflow to (can easily be achieved tru a feature) and have your event receiver associate the workflow when the first item is added.
or you can associate the workflow to the contenttype used in the list (your own contenttype you attach to your own list definition or a default SharePoint contenttype)
I don't know the rest of your solution, so it's defficult for me to suggest the best solution for you.
What I (almost) always do, is write my own list definition - That way I can avoid problems like this, now or in the future.
With SharePoint 2010 it is now possible to hook into the list creation event by overriding the ListAdded event in the SPListEventReceiver class.
I usually deploy an extra view page which is set to the default view. When the user creates the list he will be sent to the viewpage which contains the setup in code behind. The view page then calls a method ive created, which changes the default view, removes the setup view and change any navigation node pointing to the setup view.
There is probably no perfect answer to this question because there is no list added event receiver (if memory serves me correct).
I don't know if this is the case, but if you really just needed to register an itemadded (or updated, deleted, etc.) event to any new list, I believe you can register the those events at the site (SPWeb) level and they will fire on any new lists created.

Sharepoint - how to set permission level to add item but not view? [closed]

Closed. This question is off-topic. It is not currently accepting answers.
Want to improve this question? Update the question so it's on-topic for Stack Overflow.
Closed 9 years ago.
Improve this question
I want to allow a certain group of users to add items to a list, but not be able to view all items. This is so I can set up a workflow with certain parts of it private. I thought it'd be possible by defining a new permission level in:
http://servername/_layouts/addrole.aspx ('Add a permission level' page)
However, when you select the "add items" list permission, "view items" is automatically ticked also.
Anyone know a solution to this?
As a half-way option you can set up the list to only show items to their owner (Settings > Advanced Settings and then set options for Read Access / Edit Access as "Only their own". This won't preclude a person from seeing all items that were added by them, but there won't be anything viewable outside of this permission (other than by a list owner).
The View Items is a dependent permission for Add Items so not sure if we can add such permissions OOB in sharepoint, have a look here :
(http://office.microsoft.com/en-us/sharepointtechnology/HA101001491033.aspx)
You can have a dirty workaround of creating 2 lists and than adding the code in the item added event of the first list to add item to another list and than remove it from the first list, not sure if this is a good solution . . .
$spweb=Get-SPWeb -Identity "<site url>";
$spRoleDefinition = New-Object Microsoft.SharePoint.SPRoleDefinition;
$spRoleDefinition.Name = "Submit only";
$spRoleDefinition.Description = "Can submit/add forms/files/items into library or list but cannot view/edit them.";
$spRoleDefinition.BasePermissions = "AddListItems, ViewPages, ViewFormPages, Open";
$spweb.RoleDefinitions.Add($spRoleDefinition);
Taken from:
http://sajiviswam.wordpress.com/2011/12/09/add-only-permission-level-in-sharepoint-2010/
I had a similar problem, where didn't want anonymous users seeing contents of list.
The same solution might work for this.
In SharePoint designer (for some reason couldn't edit page on web), open the DispForm.aspx page and on webpart properties, add a target audience (if want no one to see make webpart hidden) DO NOT DELETE WEBPART - doing this breaks your list totally!
Can do the same with AllItems.aspx
Hope this helps.
Use an impersonation step in the workflow.
Out of the box with SharePoint designer I can only think to use a workflow to move any items from a Public "dropbox" list to a secured list.
A user can see and upload items to the public dropbox, but immediately a workflow kicks off that just moves the content to another, identical, secured list. You can decide if you need to allow content overwriting or not.
A hacky workaround, but that without programming that is all SharePoint is. (My company won't let me write code to it yet)
You didn't really specify which kind of list you're using, but if you look in the list settings under "Advanced Settings" you'll probably find an "Item Level Permissions" section. This will let you choose to limit users to reading (or editing) only the items they've submitted. This goes above and beyond any other ACLs set on the list or it's items.
I think use Advanced permission is not accessible since it can not prevent the one who submits from view it, otherwise it is a good solution!
Workflow should, I think, can do the job. Just make sure when an item uploaded the worklow is triggered. Then if you can build a workflow which can set specific permission to the item, all thing should be done.
If you do not get your hand dirty with building workflow then go to 3w.sharepointboost.com when have a sort of plug and play solution called Column View Permission.
I was just working on a quick solution for this, doing research when I found this message.
Besides the SPD workflow, will not work with anonymous users, I was thinking of doing a infopath html form that mails the form to a forms library. You can have one form library as the site to start the form and then have the results stored in a different forms library. Since you can set the form library to accept email from anyone you can prevent people from reading but they can still edit.
Have not tried this but if I run into problems will post comments.
I completely agree with 'Ceesaaxp'. Under Advanced Settings for the list, set Read Access to Only Their Own. I created a Knowledge Management process, whereby I created two lists, one for pending knowledge articles, and one for approved. I modified the 'New Form' page for the Pending list and disabled a drop down box using JavaScript, which was used as the status of the article. This drop down is then set permanently as 'Pending'. I also created a new permission level which allows users to Add items only. I then created a workflow which moves the article into the Approved list when the status drop down box is set to 'Approved'.
I then changed the read only settings in advanced settings of the pending list to only their own, so all knowledge articles are approved before they are published.
#Jomit. Your workaround may work, but it has the racing condition problem. Users may still have a chance to see other items. This may be a no-no depending on your rules.
Regular lists in SharePoint offer this option under Settings/Advanced Settings/Item-Level Permissions. Albeit for some reason this option is missing from the GUI for Document and Form Libraries.
One possible solution is to write a simple program to make these changes using the SharePoint Object Model.
http://msdn.microsoft.com/en-us/library/microsoft.sharepoint.splist.writesecurity.aspx
// Sample code for setting writing and reading security on a form library
class Program
{
static void Main(string[] args)
{
using (SPSite site = new SPSite(args[0]))
{
using (SPWeb web = site.OpenWeb())
{
SPList list = web.Lists[args[1]];
list.WriteSecurity = 2;
list.ReadSecurity = 2;
list.Update();
}
}
}
}

Resources