Wednesday, December 30, 2009

Notes field is displayed as multi text box

There is one thing about SharePoint that is very fascinating and frustrating.  No matter how much expertise you have gained or since how long you are working with SharePoint.  It always defeats you and makes you feel that there is still a lot to learn.

Today i learnt some thing really tiny and good thing about SharePoint notes field.

We had a requirement wherein we wanted to keep the record of activities that a user is performing against a list item.

We created a site column of type “Note” with “AppendOnly” set to “TRUE”.  I added it to the required content type and then to list schema in order to provision the list with a field named “Activity Notes”.

Till now everything looks good, but guess what,  when i deployed the solution and provisioned a list,  the Notes field was displayed as normal “Multi Line text box”,  on top of that it was behaving the same way and user was able to delete everything.

Where as i expected it to behave like a “Append Only” text box that shows the history of comments, (the way the Comments field behave in issue list).

Accidently i got to know that in order to “notes” field work with “append only” it is mendatory that “Versioning” is enabled in the list.

I updated the list schema to have “VersioningEnabled” set to “TRUE” and everything started working as expected.

Happy Learning….

Sudhir Kesharwani

Wednesday, March 18, 2009

Getting Workflow Association from Content Type of Sharepoint Lists

Recently i have been working on Sharepoint Custom Workflows and Workflow Association with Sharepoint Lists and Content Type within the list. Thought of sharing some of the learnings from my experience.

Once the workflow is associated with Content Type/SPLists, its very common to update Workflow Instances.
As the workflow assembly keep on changing, Whenever you deploy new version of Workflow Assembly/Workflows Solution Package, SharePoint updates the workflow association to restrict new instance of the workflow. Even if the workflow class is not modified.
To over come this we need to get the workflow association object from List/Content type, depending on how we have associated the workflow.
If you want to update workflow association to allow new instances, you need to get a reference of Workflow Association Object and Enable it.
1. Getting Workflow Association Object from Content T(when workflow is associated with content type of Sharepoint List)

private SPWorkflowAssociation GetAnnualApprovalWFAssociation(SPContentType contentType)
{
SPWorkflowAssociation resultWFAssociation= null;
//Loop through all the workflow associations and return the correct one
foreach (SPWorkflowAssociation wfAssociation in contentType.WorkflowAssociations)
{
if(wfAssociation.BaseId == Constants.workflowGuid)
resultWFAssociation= wfAssociation;
}
return resultWFAssociation;
}
}
Note: SPWorkflowAssociations collection class defines two methods that can be used to get the workflow associations
  • GetAssociationByBaseID(wfGUID)
  • GetAssociationByName(name,cultureInfo)

This methods will return value only when the WorkflowAssociations are not restricted to allow new instances. Hence you can not completely trust this methods. This is why i have used a work around which loops through all the workflow associations (including deactive one) and compare the workflow association with Workflow GUID.

2. Getting workflow association with Sharepiont List

> SPList object contains a collection called WorkflowAssociations which is same as content type's workflow association object, so you can replace SPContentType object with SPList object and the above method will work.

Enabling WorkflowAssociation to AllowNewInstance

Once you have reference of SPWorfklowAssociation object, you can just set it's enabled property to true and invoke UpdateWorkflowAssociation(SPWorkflowAssociation) method on Content Type or SPLIst object.

SPWorkflowAssociation wfAssociation = GetWorkflowAssociation(myList);

wfAssociation.Enabled = true

myList.UpdateWorkflowAssociation(wfAssociation);

This action will enable the workflow association.


This is perticularly very useful when you have lots of sites already created in your environment that are using the Workflow, and you re-deploy the workflow assembly. So instead of doing it through sharepoint workflow settings page, you can write a tool that leverages the Sharepoint Object Model and updates the workflow associations for all your existing sites.

Tuesday, March 3, 2009

Iterating through Sharepoint Discussion List Replies

Hi,

Recently i had been working extensively in the integration of sharepoint discussion list and the document library.


I had one requirement where i have to iterate through the replies of a sharepoint discussion thread, i could hardly find any posts related to that.


First of all Sharepoint discussion lists are very different then other sharepoint lists. It is very different becase it stores the data differently. If you look at the settings of discussion list you will find that it contains two content types

1. Discussion Content Type

2. Messages Content Type

If you digg further you will find that discussion content type is derived from sharepoint folder content type and messages content type is derived from item content type.

Each message(reply) in the discussion list contains a field called ParentFolderId. This field is hidden from the new/edit/view forms of discussion list.

This field always contains id of the root folder for this message (e.g. id of the root discussion thread)

so if you want to get a reference of root discussion thread(aka folder), you can use following piece of code(considering that you have reference to the message)

int rootDiscussionThreadId = ListItem["ParentFolderId"].ToString();



So when you start a new discussion, internally sharepiont creates a folder withthe subject of the discussion, moving forward all the replies to the root discussion thread are nothign but items created inside the root discussion thread.

Discussion List

> Discussion - 1

-->Message 1

-->Message 2

> Discussion - 2

-->Message 1
-->Message 2


> Disccusion - 3

-->Message 1
-->Message 2





So if you iterate through all the items in the sharepoint list using he normal SPList.Items property, you will get reference of all the root folders (not the replies.)


Even when you navigate to flatView.aspx for any discussion thread, or any other page related to discussion thread you will always find a query string parameter named rootFolder, this query string parameter holds the unique id of the discussion folder.


Getting Replies of a Discussion


If you are in a situation where you have to loop through replies of a perticular discussion thread, you can use folowing code (assuming that you have obtained parent folder / reference of discussion item)



SPQuery queryText = new SPQuery();
queryText.Query = <>;
queryText.Folder = discussion.Folder;
//IMP: setting the folder will get items from that perticular folder
SPListItemCollection relatedDiscussions = discussion.ParentList.GetItems(queryText);


Please note that since we want to query items from a perticular folder of the discussion list, we are setting the folder property of SPQuery object to the folder that we want to query. Since my discussion is nothign but a folder in the discussion list, i am setting the folder using that discussion object.


When this query is executed, relatedDiscussion collection will contain list of replies for the given discussion folder,