Sunday, 20 May 2012

SharePoint 2010 : Basics of List Instance Element

Back again from a rare complete one day off (no office, no reading, no learning, only cooking)….News is I was one of the many people who got Star Performer Award in my office last week. One more feather in the cap. Sometimes motivation is needed to keep you going.

List Instance :
List instance is one of the easiest SharePoint artifacts to create declaratively (element manifest). So much content available on internet about it. Hence I was thinking not to write about it, but later on I thought my blog should be a single source to learn about all SharePoint artifacts, mostly if it is related to custom development. Hence giving some links to read.


 
  <ListInstance Title="Company Announcements "
                OnQuickLaunch="TRUE"
                TemplateType="104"
                FeatureId="00bfea71-d1ce-42de-9c63-a44004ce0104"
                Url="Lists/Company Announcements"
                Description="This list is used to create and store company announcements">
  </ListInstance>
 

List instance can also have default data.

A new very useful attribute CustomSchema introduced in SharePoint 2010


  <ListInstance FeatureId="{00bfea71-e717-4e80-aa17-d0c71b360101}"
                TemplateType="101"
                Title="Lending Proposals"
                Description=""
                Url="Lending Proposals"
                CustomSchema="Files\Lending Proposals\Schema.xml"
                RootWebOnly="FALSE"
                OnQuickLaunch="TRUE" >
  </ListInstance> 
 

If you don’t have control over schema.xml, then you will need to use ContentTypeBinding element for associating the content type with list instance.

If you are creating external list, then you will need to use DataSource element to specify the details about external LOB system.
e.g


  <ListInstance 
                FeatureId="{00bfea71-9549-43f8-b978-e47e54a10600}" 
                TemplateType="600" 
                Title="Customers" 
                OnQuickLaunch="TRUE"
                Description="This list has existing customers fetched from SQl." 
                Url="Lists/Customers" 
                >
    <DataSource>
      <Property Name="LobSystemInstance" Value="CustomerModel" />
      <Property Name="EntityNamespace" Value="DemoApplication.CustomerModel" />
      <Property Name="Entity" Value="Customer" />
      <Property Name="SpecificFinder" Value="ReadItem" />
    </DataSource>
  </ListInstance>



Points to remember:
  1. ID parameter does not control the GUID of the list instance to be created. It is not even GUID. It could be any string value.
  2. FeatureId – This should be the GUID of feature who created the list template/ list definition used to create list instance. If list instance and list template are contained within same feature, then mentioning FeatureId attribute is not required.
  3. If your site is localized into multiple languages, then you might come across the issue mentioned in the http://blogs.msdn.com/b/manuj/archive/2009/10/08/contenttypebinding-listurl-and-multi-lingual-sites.aspx
  4. Desired List instance can be created in browser and then can be imported in Visual Studio using the technique mentioned in my blog Create List Template/ List Definition - Part 2

I think that’s all…

Fasting…no food no water….good thing is I need not to eat self-cooked food.

Sunday, 13 May 2012

SharePoint 2010: Create Custom Document Set Content Type using VS 2010


Every product evolves and so as SharePoint. In SharePoint 2010, the latest SharePoint version, one of the few remarkable enhancements added to Content Management is Document Set Content type.

One of the problems people facing in MOSS 2007 was there was no provision to group the different documents related to single entity (work product) and perform a collective operation on them like executing some workflows etc. In SharePoint 2010, Document Set content type is introduced to address such business needs.

Document Set content type is a special kind of folder which can store multiple documents. It brings following advantages over the normal folders.

Document Set Vs Folder content type:
1.       When document set is clicked it redirects user to a unique welcome page associated with the document set. Welcome page can be customized in the sense it allows adding new web parts, displaying welcome page fields (metadata) etc apart from displaying the documents within the document set. Normal folders when clicked just display documents within them .
2.       Ability to have Shared Metadata
Documents within the document set can share the metadata between them. Such shared fields can be displayed in welcome page. This is not possible using folders.
3.       Ability to have default documents
Document set can have default documents which will be automatically added to document set when a new document set is created. Folders do not possess such feature.
4.       Versioning:
Apart from the contained documents, Document Set have its own versioning capability.
5.       Workflows
Workflows are richly supported by Document Set. Few new OOB workflow actions are added in SharePoint Designer to support Document Set content type. Folder content type lacks many workflow capabilities and needs some workaround to be implemented. Have a look at http://www.codeproject.com/Articles/30452/SharePoint-Workflows-for-Folder-Content-Type
  
Limitations:

Note:
Strangely, I got an error while creating the document set with localhost in url. Everything worked seamlessly when I used the Default Zone url instead. No intension to troubleshoot it. If you are getting same error, you know the fix now.

Aim:
Custom Document set content type can be created using Server object model or in declarative manner (element.xml). We will see how to create it using declarative manner step by step in this post. As Document set very different than normal content types, creating it through VS 2020 in declarative fashion  is also very different than that of normal content type.

We will create a custom Loan Proposal content type inheriting from the Document Set content type. This custom Loan Proposal content type will have custom welcome page and one default document.

Detailed Steps:
1.       Ensure Document Set site collection feature is activated.
2.       Create a DocumentSetContentTypeDemo VS 2010 project using Empty SharePoint Project template.
3.       Add a web part to the project. Give the name of the web part as LoanRequestorImageWebPart as shown in figure 1.

Figure 1 : Create LoanRequestorImageWebPart

We will add this web part on the welcome page of the Loan Request content type so that it would display the photo of the requestor.

4.       Copy the below code into the web part so that LoanRequestorImageWebPart.cs will look like this.

using System;
using System.ComponentModel;
using System.Web.UI;
using System.Web.UI.WebControls.WebParts;
using Microsoft.SharePoint;

namespace DocumentSetContentTypeDemo.LoanRequestorImageWebPart
{
    [ToolboxItemAttribute(false)]
    public class LoanRequestorImageWebPart : WebPart
    {
        const string NO_IMAGE_AVAILABLE = "/_layouts/Images/DocumentSetContentTypeDemo/NoImageUploaded.jpg";
        protected override void CreateChildControls()
        {
            if (this.Page.Request["ID"] != null)
            {
                int docSetId = Convert.ToInt32(this.Page.Request["ID"].ToString());
                SPList currentList = SPContext.Current.Web.Lists[new Guid(this.Page.Request["List"].ToString())];
                SPFolder folder = currentList.GetItemById(docSetId).Folder;
                string docSetRootFolder = this.Page.Request["RootFolder"].ToString();
                if (currentList != null)
                {
                    SPQuery qry = new SPQuery();
                    qry.Query = @"<Where>
                                     <Eq>
                                         <FieldRef Name='ContentType' />
                                         <Value Type='Computed'>Image</Value>
                                    </Eq>
                                 </Where>";
                    qry.Folder = folder;
                    SPListItemCollection listItems = currentList.GetItems(qry);
                    if (listItems.Count > 0)
                    {
                        SPListItem imageItem = listItems[0];
                        string name = imageItem["Name"].ToString();
                        string imageUrl = docSetRootFolder +"/" + name;
                        this.Controls.Add(new LiteralControl(string.Format("<img src='{0}' alt='{1}' height='150' width='140' style='padding:8px'/>", imageUrl, name)));
                    }
                    else
                    {
                        this.Controls.Add(new LiteralControl(string.Format("<img src='{0}' height='150' width='140' style='padding:8px'/>", NO_IMAGE_AVAILABLE)));
                    }
                }
            }
            else
            {
                this.Controls.Add(new LiteralControl(string.Format("<img src='{0}' height='150' width='140' style='padding:8px'/>", NO_IMAGE_AVAILABLE)));
            }
        }
    }
}


5.       Add an Image mapped folder to the project. Add the following image to the mapped folder.

Figure 2: No photo image
This image will be used when there is no loan requestor photo uploaded.

6.       Deploy the DocumentSetContentTypeDemo project.
7.       Create Following site Columns through browser

Site Column
Type
Required
Description
Group
Any other details
Loan Amount
Currency
Yes
Enter the loan amount required.
SharePoint 2010 Custom Development
Currency Format : Rs. (India)
Loan Reason
Single line of text
Yes
Enter the reason for which loan is required.
SharePoint 2010 Custom Development

Loan Type
Choice
Yes
Select the loan type.
SharePoint 2010 Custom Development
Choices:
Educational Loan
Personal Loan
Furniture Loan
Home Loan
Age
Number
Yes

SharePoint 2010 Custom Development

Contact Number
Single line of text
Yes

SharePoint 2010 Custom Development

Current Salary
Number
Yes

SharePoint 2010 Custom Development

Job Experience
Number
Yes
No. of years
SharePoint 2010 Custom Development

Occupation
Single line of text
Yes

SharePoint 2010 Custom Development

Sex
Choice
Yes

SharePoint 2010 Custom Development
Choices:
Male
Female


8.       Create following content types through browser
a.       Loan Application Form

Figure 3 : Loan Application Form content type

b.      Requestor Credit Details

Figure 4 : Requestor Credit Document content type

c.       Loan Proposal
Create a Loan application form document as shown in figure 5. We will use this document as Default document for Loan Proposal document set content type.

Figure 5 : Loan Application Form content

Then create a Loan Proposal content type as shown in figure 6.

Figure 6 : Loan Proposal Content type

Click on Document Set settings link shown in Red in figure 6 and make the configurations as shown in below figures.

Allow Content Types:

Figure 7 : Allowed Content Types

Default Content:
Upload the Loan Application form document created as default document using Loan Application Form content type. Once Loan Proposal document set is created, Loan Application Form will be added to the document set automatically. This then can be downloaded and sent to Loan Requestor for filling his/her details.

Figure 8 : Default Document

Shared Fields:

Figure 9 : Shared Fields

Welcome Page Columns:

Figure 10 : Welcome page columns

Welcome Page:
Click on Customize the Welcome Page link. It will redirect you to OOB Document set welcome page. Remove the Image web part and add LoanRequestorImageWebPart web part on welcome page.

9.       Save the site as site template as DocumentSetSiteTemplate using the Save site as template link present in Site Settings page.
10.   Download the DocumentSetSiteTemplate.wsp in local physical file system.
11.   In DocumentSetContentTypeDemo VS 2010 solution, add new project using Import SharePoint Solution Package template as shown below in figure 11.

Figure 11 : Import SharePoint Solution Package project

12.   In SharePoint Customization Wizard, select the DocumentSetSiteTemplate.wsp in Specify the new project source step and click next.
13.   In Select items to import step, select following items and click Finish button. Wizard will show Selection Dependacy Warining. Click on No button.

Content Types:
Loan Application Form
Requestor Credit Details
Loan Proposal

Fields:
Loan Amount
Loan Reason
Loan Type
Age
Contact Number
Current Salary
Job Experience
Occupation
Sex

Modules:
_ctsLoan Proposal_

14.   Copy Modules, Content Types and Fields folder into DocumentSetContentTypeDemo project. Your project will look like this.

Figure 12 : DocumentSetContentTypeDemo project

15.   If you open the Loan Proposal content type, you will see it quite different than normal content types. It will have information about Allowed Content types, shared fields, welcome page fields, Default Documents etc.

<?xml version="1.0" encoding="utf-8"?>
<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
   <ContentType ID="0x0120D52000442F5196B2EA0C489F01F37985515E5B" Name="Loan Proposal" Group="SharePoint 2010 Custom Development" Overwrite="TRUE" ProgId="SharePoint.DocumentSet" PushDownChangedResourceFilesOnly="TRUE" xmlns="http://schemas.microsoft.com/sharepoint/">
      <Folder TargetName="_cts/Loan Proposal" />
      <FieldRefs>
          <FieldRef ID="{8553196d-ec8d-4564-9861-3dbe931050c8}" Name="FileLeafRef" Required="TRUE" Hidden="FALSE" />
          <FieldRef ID="{475c2610-c157-4b91-9e2d-6855031b3538}" Name="FullName" />
          <FieldRef ID="{cbb92da4-fd46-4c7d-af6c-3128c2a5576e}" Name="Description" ShowInNewForm="TRUE" ShowInEditForm="TRUE" />
          <FieldRef ID="{2defb7a6-aca0-43bc-8d73-cbd07e5b7503}" Name="Loan_x0020_Amount" />
          <FieldRef ID="{413b4744-f709-4952-8864-fd38e60bd754}" Name="Loan_x0020_Reason" />
          <FieldRef ID="{7cf8011a-9d47-44f4-a49e-f72d6b038161}" Name="Loan_x0020_Type" />
          <FieldRef ID="{b824e17e-a1b3-426e-aecf-f0184d900485}" Name="ItemChildCount" />
          <FieldRef ID="{fa564e0f-0c70-4ab9-b863-0177e6ddd247}" Name="Title" Required="FALSE" Hidden="TRUE" />
          <FieldRef ID="{c042a256-787d-4a6f-8a8a-cf6ab767f12d}" Name="ContentType" />
          <FieldRef ID="{960ff01f-2b6d-4f1b-9c3f-e19ad8927341}" Name="FolderChildCount" />
      </FieldRefs>
      <XmlDocuments>
          <XmlDocument NamespaceURI="http://schemas.microsoft.com/office/documentsets/welcomepageview">
              <WelcomePageView xmlns="http://schemas.microsoft.com/office/documentsets/welcomepageview" LastModified="1/1/1 0:00:01 AM" />
          </XmlDocument>
          <XmlDocument NamespaceURI="http://schemas.microsoft.com/sharepoint/events">
              <spe:Receivers xmlns:spe="http://schemas.microsoft.com/sharepoint/events">
                   <Receiver>
                        <Name>DocumentSet ItemUpdated</Name>
                        <Synchronization>Synchronous</Synchronization>
                        <Type>10002</Type>
                        <SequenceNumber>100</SequenceNumber>
                        <Assembly>Microsoft.Office.DocumentManagement, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c</Assembly>
                        <Class>Microsoft.Office.DocumentManagement.DocumentSets.DocumentSetEventReceiver</Class>
                        <Data />
                        <Filter />
                   </Receiver>
                   <Receiver>
                        <Name>DocumentSet ItemAdded</Name>
                        <Synchronization>Synchronous</Synchronization>
                        <Type>10001</Type>
                        <SequenceNumber>100</SequenceNumber>
                        <Assembly>Microsoft.Office.DocumentManagement, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c</Assembly>
                        <Class>Microsoft.Office.DocumentManagement.DocumentSets.DocumentSetItemsEventReceiver</Class>
                        <Data />
                        <Filter />
                    </Receiver>
              </spe:Receivers>
          </XmlDocument>
          <XmlDocument NamespaceURI="http://schemas.microsoft.com/office/documentsets/allowedcontenttypes">
              <act:AllowedContentTypes xmlns:act="http://schemas.microsoft.com/office/documentsets/allowedcontenttypes" LastModified="05/12/2012 13:23:22">
                    <AllowedContentType id="0x0101" />
                    <AllowedContentType id="0x0101008CF1CDE6AF3C644E93569474BF0D9DFD" />
                    <AllowedContentType id="0x0101009A5057FEE7BD674EB0C0B448F20F833E" />
                    <AllowedContentType id="0x0101009148F5A04DDD49CBA7127AADA5FB792B00AADE34325A8B49CDA8BB4DB53328F214" />
              </act:AllowedContentTypes>
           </XmlDocument>
           <XmlDocument NamespaceURI="http://schemas.microsoft.com/office/documentsets/sharedfields">
               <sf:SharedFields xmlns:sf="http://schemas.microsoft.com/office/documentsets/sharedfields" LastModified="05/12/2012 13:23:22">
                    <SharedField id="cbb92da4-fd46-4c7d-af6c-3128c2a5576e" />
                    <SharedField id="413b4744-f709-4952-8864-fd38e60bd754" />
                    <SharedField id="475c2610-c157-4b91-9e2d-6855031b3538" />
                    <SharedField id="7cf8011a-9d47-44f4-a49e-f72d6b038161" />
                    <SharedField id="2defb7a6-aca0-43bc-8d73-cbd07e5b7503" />
               </sf:SharedFields>
           </XmlDocument>
           <XmlDocument NamespaceURI="http://schemas.microsoft.com/office/documentsets/defaultdocuments">
               <dd:DefaultDocuments xmlns:dd="http://schemas.microsoft.com/office/documentsets/defaultdocuments" LastModified="05/12/2012 13:23:22" AddSetName="True">
                    <DefaultDocument name="Loan Application Form.docx" idContentType="0x0101008CF1CDE6AF3C644E93569474BF0D9DFD" />
               </dd:DefaultDocuments>
           </XmlDocument>
           <XmlDocument NamespaceURI="http://schemas.microsoft.com/office/documentsets/welcomepagefields">
               <wpf:WelcomePageFields xmlns:wpf="http://schemas.microsoft.com/office/documentsets/welcomepagefields" LastModified="05/12/2012 13:23:22">
                    <WelcomePageField id="475c2610-c157-4b91-9e2d-6855031b3538" />
                    <WelcomePageField id="2defb7a6-aca0-43bc-8d73-cbd07e5b7503" />
                    <WelcomePageField id="413b4744-f709-4952-8864-fd38e60bd754" />
                    <WelcomePageField id="7cf8011a-9d47-44f4-a49e-f72d6b038161" />
               </wpf:WelcomePageFields>
            </XmlDocument>
            <XmlDocument NamespaceURI="http://schemas.microsoft.com/sharepoint/v3/contenttype/forms">
               <FormTemplates xmlns="http://schemas.microsoft.com/sharepoint/v3/contenttype/forms">
                    <Display>ListForm</Display>
                    <Edit>ListForm</Edit>
                    <New>DocSetDisplayForm</New>
               </FormTemplates>
            </XmlDocument>
            <XmlDocument NamespaceURI="http://schemas.microsoft.com/sharepoint/v3/contenttype/forms/url">
               <FormUrls xmlns="http://schemas.microsoft.com/sharepoint/v3/contenttype/forms/url">
                    <New>_layouts/NewDocSet.aspx</New>
               </FormUrls>
            </XmlDocument>
        </XmlDocuments>
    </ContentType>
</Elements>


16.   Create three features WebParts, Content Types and Site Columns. Associate the element manifests with them so that package designer looks like this.

Figure 13 : Package Designer

17.   Deploy the project to another site collection. Check whether Loan Proposal content type is created exactly like that of created through browser.
18.   This is how it looks when a Loan Proposal document set is created. 

Figure 14 : Loan Proposal Document Set in usage

That was easy! Please leave a comment in case of any queries. Source code can be downloaded here.

Tributes to all loving mothers on this Mother’s Day!