CAML Query and the SharePoint List Views Filtering

I have a list which resembles a Tasks List with an additional column ‘TaskCreated’ – a DateTime column.

I wanted to query the list with the following filters :

  1. Get all the items with status “Not Started”
  2. Get all the items with status “In Progress”
  3. Get all the items with status “Completed” AND the ‘Task Created’ is within the given number of days.
  4. Get all the items with status ‘Deferred” AND the ‘TaskCreated’ is within the given number of days.

I used the following CAML query to fetch the results :

oQuery.Query = String.Format(
“<Where>” +
“<Or>” +
“<Or>” +
“<Eq>” +
“<FieldRef Name=’Status’ />” +
“<Value Type=’Choice’>Not Started</Value>” +
“</Eq>” +
“<Eq>” +
“<FieldRef Name=’Status’ />” +
“<Value Type=’Choice’>In Progress</Value>” +
“</Eq>” +
“</Or>” +
“<Or>” +
“<And>” +
“<Eq>” +
“<FieldRef Name=’Status’ />” +
“<Value Type=’Choice’>Completed</Value>” +
“</Eq>” +
“<Geq>” +
“<FieldRef Name=’TaskCreated’/>” +
“<Value Type=’DateTime’ StorageTZ=’TRUE’>{0}</Value>” +
“</Geq>” +
“</And>” +
“<And>” +
“<Eq>” +
“<FieldRef Name=’Status’ />” +
“<Value Type=’Choice’>Deferred</Value>” +
“</Eq>” +
“<Geq>” +
“<FieldRef Name=’TaskCreated’/>” +
“<Value Type=’DateTime’ StorageTZ=’TRUE’>{1}</Value>” +
“</Geq>” +
“</And>” +
“</Or>” +
“</Or>” +
“</Where>”,
SPUtility.CreateISO8601DateTimeFromSystemDateTime(DateTime.UtcNow.AddDays(Completed)),
SPUtility.CreateISO8601DateTimeFromSystemDateTime(DateTime.UtcNow.AddDays(Failed)));

I was curious to know how SharePoint would have done if I had created a view out of it.

This is how it looks like . Since there are nested operators it is very difficult to relate to the the filters displayed ….If you have a complex view then you are better of by creating a custom view using code and the CAML rather than relying on the view creation UI of SharePoint.

image

The view as seen by Stramit CAML Viewer :

<Query>
<Where>
<Or>
<Or>
<Eq>
<FieldRef Name=”Status” />
<Value Type=”Choice”>Not Started</Value>
</Eq>
<Eq>
<FieldRef Name=”Status” />
<Value Type=”Choice”>In Progress</Value>
</Eq>
</Or>
<Or>
<And>
<Eq>
<FieldRef Name=”Status” />
<Value Type=”Choice”>Completed</Value>
</Eq>
<Geq>
<FieldRef Name=”TaskCreated” />
<Value Type=”DateTime” StorageTZ=”TRUE”>2009-11-16T22:05:59Z</Value>
</Geq>
</And>
<And>
<Eq>
<FieldRef Name=”Status” />
<Value Type=”Choice”>Deferred</Value>
</Eq>
<Geq>
<FieldRef Name=”TaskCreated” />
<Value Type=”DateTime” StorageTZ=”TRUE”>2009-11-16T22:05:59Z</Value>
</Geq>
</And>
</Or>
</Or>
</Where>
</Query>

Advertisements

SharePoint Content Approval – Never ending workflow

The Content Approval feature permits you to create a list or a document library where items or files that are submitted by users are not visible to other site users until the items or the files are approved by a user (such as the site administrator) who belongs to a site group that has the Manage Lists right.

When you add a new item or when you modify an existing item in a list or a document library after you enable content approval for that list or document library, the item is marked as Pending. Pending items are only visible to the user who created or modified the item and to users with the Manage Lists right. Pending items are not visible to users until the item is approved. When an item is approved, it is marked as Approved and is visible to all users. When an item is rejected, it is marked as Rejected, and is returned to the user who created it.

 

Use a workflow to manage content approval for a library

You can use a workflow to manage content approval (also called moderation) in libraries for which content approval is required.

Enabling OOTB Approval workflow for a list:

image

 

image

The Problem : 

In a SharePoint list after you are done with enabling content approval and creating an OOTB approval workflow, you might experience a strange behavior during the approval process.

The workflow can run endlessly. Every time the workflow task is approved, it triggers a Item Updated event which in turn starts another instance of the workflow…So the item remains pending even after the approval ! (After the workflow instance completes another instance is started because of the item updated event triggered by the workflow approval.

This happens in the list. The reason for the difference in behavior is the way the workflow setup is done for the list and document library. We will come to the settings in the library shortly.

The workaround Solution:

The solution is to handle the ItemUpdated event and update the Moderation status programmatically after turning off the event. The code is listed below.

 

class UpdateWorkflowStatus : SPItemEventReceiver
   {

       public override void ItemUpdating(SPItemEventProperties properties)
       {
           EventLog m_EventLog = new EventLog("");
           m_EventLog.Source = "Approval Workflow Status Update";

           try
           {
               base.ItemUpdating(properties);
               if (properties.AfterProperties["_ModerationStatus"] != null && properties.ListItem["_ModerationStatus"] != null)
               {
                   if(properties.AfterProperties["_ModerationStatus"].ToString() != properties.ListItem["_ModerationStatus"].ToString())
                   {
                       this.DisableEventFiring();

                       properties.Status = SPEventReceiverStatus.CancelNoError;
                       properties.ListItem["_ModerationStatus"] = properties.AfterProperties["_ModerationStatus"].ToString();
                       properties.ListItem.Update();

                       this.EnableEventFiring();
                   }
               }
           }
           catch (Exception ex)
           {
               m_EventLog.WriteEntry("Workflow Status Update Event Handler Error : " + ex.Message,EventLogEntryType.Error);
           }


       }

The reason why it won’t happen in a document library is that the way the settings are done. In a document library for the content approval minor and major version has to be enabled. And any edit that happens becomes a minor version and a workflow gets triggered only when the major version is published.

image

image

BUT ! there is a way to reproduce it in document library as well. You should create the workflow first and then enable content approval, you will end up in the same problem that I explained for the list !!!

SharePoint Document Library and List – File Upload

There are different ways you can add documents to a doc library or to list item as an attachment. You could use object model, built-in web service, custom web service that uses object model, or HTTP PUT method.

In this post I will be stepping through them in detail. Let us take the object model approach first. For the sake of simplicity I have created a simple windows forms app that will push documents in to the document library and list

 

Adding documents to a Document Library and updating document attributes :

   1: private void button1_Click(object sender, EventArgs e)

   2:         {

   3:             if (openFileDialog1.ShowDialog() == DialogResult.OK)

   4:             {

   5:                 try

   6:                 {

   7:                     FileStream myStream;

   8:                     string fullName;

   9:                     if ((myStream = (FileStream)openFileDialog1.OpenFile()) != null)

  10:                     {

  11:                         fullName = openFileDialog1.FileName;

  12:                         FileInfo myFileInfo = new FileInfo(fullName);

  13:                         using (myStream)

  14:                         {

  15:                             using (SPSite oSite = new SPSite("http://vslearnmoss/sites/FileUpload"))

  16:                             {

  17:                                 using (SPWeb oWeb = oSite.OpenWeb())

  18:                                 {

  19:                                     SPFolderCollection oFolders = oWeb.GetFolder("MyDocuments").SubFolders;

  20:                                     SPFolder oFolder = oFolders["Folder1"];

  21:                                     SPFileCollection oFileColl = oFolder.Files;

  22:                                     Hashtable oDocAttribs = new Hashtable { { "Field1", "Value1" }, { "Field2", "Value2" } };

  23:                                     SPFile oFile = oFileColl.Add(myFileInfo.Name, myStream, oDocAttribs, true);

  24:                                 }

  25:                             }

  26:  

  27:                         }

  28:                     }

  29:                 }

  30:                 catch (Exception ex)

  31:                 {

  32:                     MessageBox.Show("Error: " + ex.Message);

  33:                 }

  34:             }

  35:  

  36:         }

Adding document attachments to a list item  :

   1: private void button1_Click(object sender, EventArgs e)

   2:         {

   3:             if (openFileDialog1.ShowDialog() == DialogResult.OK)

   4:             {

   5:                 try

   6:                 {                    

   7:                     string fullName;

   8:                     fullName = openFileDialog1.FileName;

   9:                     FileInfo myFileInfo = new FileInfo(fullName);

  10:                     byte[] fileData = System.IO.File.ReadAllBytes(fullName);

  11:  

  12:                     using (SPSite oSite = new SPSite("http://vslearnmoss/sites/FileUpload"))

  13:                     {

  14:                         using (SPWeb oWeb = oSite.OpenWeb())

  15:                         {

  16:                             SPList oList = oWeb.Lists["MyList"];

  17:                             SPQuery oQuery = new SPQuery { Query = "0" };

  18:                             SPListItem oItem = oList.GetItems(oQuery).Add();

  19:                             oItem["Title"] = textBox1.Text;

  20:                             SPAttachmentCollection attachments = oItem.Attachments;

  21:                             attachments.Add(myFileInfo.Name, fileData);

  22:                             oItem.Update();

  23:                         }

  24:                     }

  25:                 }

  26:                 catch (Exception ex)

  27:                 {

  28:                     MessageBox.Show("Error: " + ex.Message);

  29:                 }

  30:  

  31:             }

  32:         }

One thing to note when accessing the list for creating a new list item is to be mindful that when SPList.Items.Add is called it fetches all the items before creating a new item, one way to avoid is to make a blank query that fetches zero results and add a new list item to the collection. [Thanks to Rob Garret]

SPQuery oQuery = new SPQuery { Query = "0" };

SPListItem oItem = oList.GetItems(oQuery).Add();

 

You can look for more info about adding list item efficiently in this article by Rob Garret.

In the next part of this article, I will show you how to utilize web services or HTTP PUT method to push documents into the SharePoint document library.

How to overwrite SharePoint master page using a feature

I ran into a scenario where I had to overwrite an already existing master page using a feature.

In my elements.xml I had an entry for the custom master page like the following

   
   1: <Module Name="OSGMasterPages" Url="_catalogs/masterpage"   Path="MasterPages" RootWebOnly="TRUE">

   2: <File Url="default.master"   Type="GhostableInLibrary" >


I was unable to overwrite then found that the file has an additional attribute to specify what to do if the file already exists.

   
   1: <File   IgnoreIfAlreadyExists = "TRUE" | "FALSE"   

   2:    Name = "Text"   

   3:    NavBarHome = "TRUE" | "FALSE"  

   4:    Path = "Text"   

   5:    Type = "Text"   

   6:    Url = "Text >   

   7: </File>

IgnoreIfAlreadyExists – Optional Boolean. TRUE to provision the view even if the file aready exists at the specified URL; otherwise, FALSE.

I tried both TRUE and FALSE..no luck.

To add more twist to the problem I also got an error

error CS0030: Cannot convert type Microsoft.SharePoint.WebControls.EncodedLiteral’ to ‘System.Web.UI.IAttributeAccessor’

I tried to manually do the master page upload and then changed the site collection master page reference, it worked without any problem. Then I hit google found this site.

Investigated the custom master page and found lot of “_designer” variables which have been added through the SPD. If I remove this variables then the master page applied successfully and the site is alive.

Since this master page was also edited using the SPD i eagerly opened the page and checked..no luck… all the “designer “ variables looks like already commented out.

Note: Got a feedback from an anonymous user that if you go ahead and remove those variables the solution will work ! I am yet to try that

Thanks to the MSDN forums, Later I found that there is no way you can overwrite an existing file that is already provisioned by a feature. It has to be done programmatically !  and btw the IgnoreIfAlreadyExists attribute just lets the feature not error out if it hits that module and the file exists.

Feature event receiver is the right place to manage your provisioning of the updated master page. Following are the steps:

  • Find out if the master page that you want to replace is already checked out.
  • If yes then do a check in.
  • From the feature folder structure query for the master page file.
  • Add this file to the site collection master page gallery
  • Check in the file.
  • publish and approve the file.

The following is the sample code that does the same. This piece of code should be part of the Feature Activated Handler. You can modify the code so that you have the master page name parameterized.

       1: // Here we are trying to overwrite the default.master   

       2: oFile = oCurrentWeb.GetFile("_catalogs/masterpage/default.master");   

       3: oFolder = oCurrentWeb.Lists["Master Page Gallery"].RootFolder;   

       4: // Check In the file   

       5: if (oFile.CheckOutStatus != SPFile.SPCheckOutStatus.None)   

       6: oFile.CheckIn("auto checkin");   

       7: // Check Out the file for edit.   

       8: oFile.CheckOut();   

       9: string directory = oFeature.Definition.RootDirectory;  

      10: directory += @"\masterpages";  

      11: // Get the master page name from the feature properties as defined in the elements.xml  

      12: SPFeatureProperty oPropertyName = properties.Feature.Properties["MasterPageName"]; 

      13:  

      14: // Get the file names from the specified directory matching the feature property value.  

      15: string[] templates = Directory.GetFiles(directory, oPropertyName.Value, System.IO.SearchOption.TopDirectoryOnly);  

      16: // templates should have all the matching file names. In this instance it whould be only one file name.  

      17: string MasterPageFile = templates[0];  

      18: FileInfo fileInfo = new FileInfo(MasterPageFile);  

      19: byte[] byteArr = System.IO.File.ReadAllBytes(MasterPageFile);  

      20: oFolder.Files.Add(fileInfo.Name, byteArr, true);  

      21: oFile.Update();  

      22: oFile.CheckIn("Check in");  

      23: oFile.Publish("Published");  

      24: oFile.Approve("Approved");

If your site collections is referencing this master page then on feature activation the master page gets updated and it gets reflected on the site collection sites which uses this master page.

All about Microsoft Office SharePoint Server Content Type – Part 4

In the part 1 of the article we covered

  • What is a content type
  • How content types work
  • In the part 2 of the article we covered

  • Extending content types
  • Attaching workflows to a content type
  • Attaching event handlers to a content type
  • In the part 3 of the article we will cover

  • How to create a Content Type programmatically using SharePoint object model
  • Significance of Content Type ID
  • Creating Content Types using Visual Studio Extensions for WSS
  • Deployment of Content Types as Features
  • In this part 4 (final part) of the article we will cover

    • Solution Package Editing in VS 2008 / WSP view
    • Adding content type to a list definition

     

    Solution Package Editing in VS 2008 / WSP view:

    Using Visual Studio 2008 and VSeWSS 1.2 you can create SharePoint projects. It also provides a developer friendly WSP view / Solution Package Editing option. Lets run through this option to see how it helps developers to quickly create the WSP and and the Deployment Package.

    Pre Requisites:

    VS 2008

    VSeWSS 1.2

    • Start up your Visual Studio 2008.
    • File->New->Project choose SharePoint under Visual C# project types
    • Select ‘Empty’ project.
    • Right Click the project –>Add->New Item choose SharePoint under Visual C# categories and select ‘Content Type’
    • Give it a name for example ‘MyNewContentType’
    • Choose ‘Item’ as the base content type.
    • Edit the ‘MyNewContentType.xml’ and un comment the Field schema definition (We are going to use the default fields generated for this demo)
    • <?xml version="1.0" encoding="utf-8"?>
      <Elements Id="ca5ae715-cdb6-4454-b581-a5c3b968fc7c"
          xmlns="http://schemas.microsoft.com/sharepoint/">
        <ContentType ID="0x01000cd55cdd7f634cc6aa237f152e1a1875"
                     Name="MyNewContentType"
                     Group="Development"
                     Description="Developing Content Type"
                     Version="0">
          <FieldRefs>
            <FieldRef
              ID="{2986f56e-9b87-426a-b7ee-989758c88533}"
              Name="MyNewContentTypeField" />
          </FieldRefs>
        </ContentType>
        <Field ID="{2986f56e-9b87-426a-b7ee-989758c88533}"
               Type="Text"
               Name="MyNewContentTypeField"
               DisplayName="MyNewContentType Field"
               StaticName="MyNewContentTypeField"
               Hidden="FALSE"
               Required="FALSE"
               Sealed="FALSE" />
      </Elements>
    • In the Solution Explorer window you will find a tab ‘WSP View’

    image

    • Let us look at this TAB and see what we got there. If it does not show the contents hit the ‘Refresh’ button

    image

    • This has the virtual view of the solution package our VSeWSS is putting together for us.
    • Here you can edit the feature.xml and update the name, display properties.
    • This gives more control to the developers and also it provides a easy way to deploy to the local SharePoint box for testing
    • Right Click the project select properties and choose Debug tab. Set the URL to the desired Site Collection where the feature needs to be deployed.

    image

    • Now you can either press F5 or Right Click Project and Select ‘Deploy’ option.
    • This will create the deployment package, deploy the solution and activate the feature for the selected site collection.

    Adding a Content Type to a List Definition:

    In this walk through I am going to create a new List Definition and add the ‘MyDerivedContentType’ that I created earlier (refer to Part – 3)

    • Start up your Visual Studio 2008.
    • File->New->Project choose SharePoint under Visual C# project types
    • Select ‘List Definition’

    image

    • Once selected it will create a project structure similar to the one shown below

    image

    • Open the Schema.xml. Insert the ContentTypeRef node inside the ContentTypes tag

    <ContentTypeRef ID=”0x010044AFF40E174C4F7D89861FF89CEE1D15003824D8E586F44E54AC7049578A0100E5“/>

    <ContentTypes>
      <ContentTypeRef ID="0x01">
        <Folder TargetName="Item"/>
      </ContentTypeRef>
      <ContentTypeRef ID="0x0120"/>
      <ContentTypeRef
        ID="0x010044AFF40E174C4F7D89861FF89CEE1D15003824D8E586F44E54AC7049578A0100E5"/>
    </ContentTypes>
    • The tricky thing is we have to now add all the fields that we want as part of this list instance of the ContentType. If we do not add the fields and update the views we will not get those columns even though it is part of the ContentType. I think it is kept this way in order to have the flexibility of creating an instance of the existing content type with the desired columns.
    • Under the Fields node add all the Fields that are part of the ‘MyDerivedContentType’ including the one in the base content type,
    <Fields>
          <Field ID="{71ED4BE5-B83F-47e4-866E-08D226709522}"
           Name="Project Status"
           Type="Choice"
           DisplayName="Project Status"
           Group="Custom Columns"
           Format="Dropdown">
            <CHOICES>
              <CHOICE>Not Started</CHOICE>
              <CHOICE>In Progress</CHOICE>
              <CHOICE>Completed</CHOICE>
            </CHOICES>
          </Field>
          <Field ID="{5623b931-2e9e-4dc6-81b6-c8a151f37418}"
            Name="Team Member"
            Type="User"
            List='UserInfo'
            UserSelectionMode="1"
                UserSelectionScope="1"
            DisplayName="Team Member"
            Group="Custom Columns"
            SourceID="http://schemas.microsoft.com/sharepoint/v3"
            ShowAddressBookButton="TRUE">
          </Field>
          <Field ID="{9b39033a-4f1c-4a0f-9deb-73fecdbc3b5d}"
            Name="Project Type"
            Type="Choice"
            DisplayName="Project Type"
            Group="Custom Columns"
            Format="Dropdown">
            <CHOICES>
              <CHOICE>Internal</CHOICE>
              <CHOICE>External</CHOICE>
            </CHOICES>
          </Field>
    </Fields>
    • Under the ‘ViewFields’ node add the fields that we want to see in the New and Edit forms.
    <ViewFields>
      <FieldRef Name="LinkTitleNoMenu">
      </FieldRef>
      <FieldRef Name="Project Type">
      </FieldRef>
      <FieldRef Name="Project Status">
      </FieldRef>
      <FieldRef Name="Team Member">
      </FieldRef>
    </ViewFields>
    • Set the debug URL to the site collection you want this list definition to be deployed and press F5 or choose ‘Deploy’ option when you right click the Project in the solution explorer.
    • Once deployed go to the Site Collection. Create a new List and choose your new ‘List Definition1’ instead of the Custom List option.

    image

    • This will create a list with the desired site columns from the content type. If you enable management of Content Types in this list you can see lineage of the columns.

    image

    This concludes the four part series on Content Types.

    Useful Links:

    Part – 1 , Part – 2 , Part – 3 , Part – 4

    All about Microsoft Office SharePoint Server Content Type – Part 3

    In the part 1 of the article we covered

  • What is a content type
  • How content types work
  • In the part 2 of the article we covered

  • Extending content types
  • Attaching workflows to a content type
  • Attaching event handlers to a content type
  • In this part 3 of the article we will cover

  • How to create a Content Type programmatically using SharePoint object model
  • Significance of Content Type ID
  • Creating Content Types using Visual Studio Extensions for WSS
  • Deployment of Content Types as Features
  •  In the part 4 (final part) of the article we will cover

    • Solution Package Editing in VS 2008 / WSP view
    • Adding content type to a list definition

    How to create a Content Type programmatically using SharePoint object model:

  • Lets try and add a content type called “NewSpec” that inherits from another custom content type called “Spec” . Make sure you add the content type to the web before you call the update method of the content type. 
    using (SPSite site = new SPSite("http://vslearnmoss/sites/sitecoll1"))
    {
        using (SPWeb web = site.OpenWeb())
        {
            SPContentType contentType = new SPContentType
             (web.AvailableContentTypes["Spec"],web.ContentTypes, "NewSpec");
            web.ContentTypes.Add(contentType);
            web.Fields.Add("SpecColumn1", SPFieldType.Text, true);
            SPFieldLink fieldLink = new SPFieldLink(web.Fields["SpecColumn1"]);
            contentType.FieldLinks.Add(fieldLink);
            contentType.Update();
        }
    }

     

    Significance of Content Type ID:

    Content type IDs uniquely identify the content type. Content type IDs are designed to be recursive. The content type ID encapsulates that content type’s “lineage”, or the line of parent content types from which the content type inherits. Each content type ID contains the ID of the parent content type, which in turn contains the ID of that content type’s parent, and so on, ultimately back to and including the System content type ID. By parsing the content type ID, you can determine which content types the content type inherits, and how two content types are related.

    Windows SharePoint Services V3 uses this information to determine the relationship between content types, and for push down operations.

    You can construct a valid content type ID using one of two conventions:

    · Parent content type ID + two hexadecimal values

    · Parent content type ID + “00” + hexadecimal GUID

    There is one special case, that of the System content type, which has the content type ID of “0x”. The System content type is the sealed content type from which all other content types ultimately inherit.

    For all other content types, you must use one of the above methods for constructing a valid content type ID.

    Note that if you use the first method, the two hexadecimal values cannot be “00”.

    A content type ID must be unique within a site collection.

    Content type IDs have a maximum length of 512 bytes. Because two hexadecimal characters can fit in each byte, this gives each content type ID an effective maximum length of 1024 characters.

    …more info on Andrew May’s web log

    SPContentType.ID property is a read only property. When you create Content Types programmatically the ID creation is taken care of. If you are creating your content type using features then you will have to define the content types.

     

    Creating Content Types using Visual Studio Extensions for WSS:

    Dev Environment – VS 2008 Professional Edition with VSeWSS 1.2

    • Open Visual Studio, choose File->New->Project
    • Select SharePoint project templates under Visual C#, choose ‘Empty’ project template.

    image

    • Select SharePoint project templates under Visual C#, choose ‘Empty’ project template.
    • Type in your name for the Project and Select the Project Location and click OK
    • After the project structure is created. Right click the project and choose Add-> New Item and select Content Type under SharePoint category.

    image

    • When you add this new item, you will be prompted to choose the Base Content Type. Choose ‘Item’. You can choose other base content types depending upon the need.

    image

    • It will generate an XML file with a dummy field references as well. The file generated follows the Content Type definition schema and Field definition schema.
    • The ContentType ID generated is “0x010044aff40e174c4f7d89861ff89cee1d15”. Here 0x01 denotes ‘Item’ base content type and it is followed by 2 zeros and then the GUID of the new content type 0x010044aff40e174c4f7d89861ff89cee1d15.
    • Let us assume that we want to create 2 site columns. One field of type User and another of type Choice column. Edit the ‘MyBaseContentType.xml’ and include the following.
    • <?xml version="1.0" encoding="utf-8"?>
      <Elements Id="5d7dfb50-7693-4f6f-aa61-0a3cfedca39a"
           xmlns="http://schemas.microsoft.com/sharepoint/">
       
        <Field ID="{5623b931-2e9e-4dc6-81b6-c8a151f37418}"
              Name="Team Member"
              Type="User"
              List='UserInfo'
              UserSelectionMode="1"
                  UserSelectionScope="1"
              DisplayName="Team Member"
              Group="Custom Columns"
              SourceID="http://schemas.microsoft.com/sharepoint/v3"
              ShowAddressBookButton="TRUE">
        </Field>
        <Field ID="{9b39033a-4f1c-4a0f-9deb-73fecdbc3b5d}"
            Name="Project Type"
            Type="Choice"
            DisplayName="Organization"
            Group="Custom Columns"
            Format="Dropdown">
          <CHOICES>
            <CHOICE>Internal</CHOICE>
            <CHOICE>External</CHOICE>
          </CHOICES>
        </Field>
        <ContentType ID="0x010044aff40e174c4f7d89861ff89cee1d15"
                     Name="MyBaseContentType"
                     Group="Development"
                     Description="Developing Content Type"
                     Version="0">
          <FieldRefs>
            <FieldRef ID ="{5623b931-2e9e-4dc6-81b6-c8a151f37418}"
               Name ="Team Member"
               Required="TRUE">
            </FieldRef>
            <FieldRef ID ="{9b39033a-4f1c-4a0f-9deb-73fecdbc3b5d}"
               Name ="Project Type"
               Required="TRUE">
            </FieldRef>
          </FieldRefs>
        </ContentType>
      </Elements>
    • Build the solution. Right Click the Project in the Visual Studio Solution Explorer and Choose ‘Deploy’ option. This Content Type will be packaged as a feature and deployed globally and the feature will be activated.
    • Go To Site Collection->Site Actions->Site Settings->Site Content Types you will see ‘MyBaseContentType’ under the Development as we chose the group name as ‘Development’

    image

    • Go To Site Settings->Site Collection Features you will see the MyBaseContentType feature activated.

    image

    We have now created a new content type and deployed it from the familiar Visual Studio environment. If you want to derive this content type and create a new content type. Follow the below mentioned steps.

    • Create a new Visual Studio project similar to the one described above. Name it as MyDerivedContentType. Choose ‘Item’ as the base content type.
    • Edit the MyDerivedContentType.xml and include field definition for an additional field for representing project status. Refer to the code below.
    <?xml version="1.0" encoding="utf-8"?>
    <Elements Id="84e70bc9-5444-4634-a256-96e0caf8dce6"
           xmlns="http://schemas.microsoft.com/sharepoint/">
      <Field ID="{71ED4BE5-B83F-47e4-866E-08D226709522}"
          Name="Project Status"
          Type="Choice"
          DisplayName="Project Status"
          Group="Custom Columns"
          Format="Dropdown">
        <CHOICES>
          <CHOICE>Not Started</CHOICE>
          <CHOICE>In Progress</CHOICE>
          <CHOICE>Completed</CHOICE>
        </CHOICES>
      </Field>
      <ContentType
          ID="0x010044aff40e174c4f7d89861ff89cee1d15003824d8e586f44e54ac7049578a0100e5"
                   Name="MyDerivedContentType"
                   Group="Development"
                   Description="Developing Content Type"
                   Version="0">
        <FieldRefs>
          <FieldRef ID ="{71ED4BE5-B83F-47e4-866E-08D226709522}"
             Name ="Project Status"
             Required="TRUE">
          </FieldRef>
        </FieldRefs>
      </ContentType>
    </Elements>
    • Update the ContentType ID in the following fashion
      • Item + 00 + BaseContentType + 00 + NewGUID
      • image
    • Add the fields as required. In this example I have added ‘Project Status’ .
    • Build and Deploy the project as explained above.
    • Go To Site Actions->Site Settings->Site Collection Features and Activate the My Derived Content Type Feature.
    • Go to the Site Settings->Site Content Types gallery. You will see the new content type added. image

    Deployment of Content Types as Features:

    Let us go through the steps for creating a WSP file using the MakeCab utility. We will make this as part of the build events and generate the WSP from within Visual Studio environment.

     

    Follow the steps mentioned in Creating Content Types using Visual Studio Extensions for WSS section above for creating a content type project

    I have re used the MyDerivedContentType project.

    • Create a new text file with a name Package.ddf. This will contain the definition for the MakeCab utility. This will include the path for the manifest file, feature.xml and the elements.xml (In our project the element file is named as MyDerivedType.xml)
    ;*** MakeCab Directive file
    ;
    .OPTION Explicit ; Generate errors
    .Set CompressionType=MSZIP
    .Set UniqueFiles=Off
    .Set Cabinet=On
    .Set DiskDirectory1=Package
    .Set CabinetNameTemplate=MyDerivedContentType.cab
    ;
    ; \
    ;**************************************************
     
    manifest.xml
     
    .Set DestinationDir=MyDerivedContentType
    MyDerivedContentType\Feature.xml
    MyDerivedContentType\MyDerivedContentType.xml
    ;
    ;***End
    • Create a new XML file with the name manifest.xml and place it in the project folder. This manifest file will have reference to the Feature manifest(feature.xml) and the Resource (MyDerivedType.xml) location.
    <Solution SolutionId="C8109F9E-6551-4c5b-94CF-E187FEF85712"
          xmlns="http://schemas.microsoft.com/sharepoint/">
     
      <FeatureManifests>
        <FeatureManifest Location="MyDerivedContentType\Feature.xml"/>
      </FeatureManifests>
     
      <Resources>
        <Resource Location ="MyDerivedContentType\MyDerivedContentType.xml"/>
      </Resources>
    </Solution>
    • Create a new XML file and place it in the MyDerivedType folder. The feature.xml will have reference to the elements xml file(MyDerivedType.xml).
    <Feature
        Title="My Derived Content Type Feature"
        Id="850DEEC6-D53D-4aeb-8C60-E4C66CF9FCE4"
        Scope="Site"
        Description="Adds a content type based on the My Base Content type"
        Version="1.0.0.0"
        Hidden="FALSE"
        DefaultResourceFile="core"
        xmlns="http://schemas.microsoft.com/sharepoint/" >
     
      <ElementManifests>
        <!-- Calling Element file to load Custom Column, Webpart and Site Template-->
        <ElementManifest Location="MyDerivedContentType.xml" />
      </ElementManifests>
     
    </Feature>
    • After adding the package.ddf, manifest.xml and the feature.xml the folder structure will look like this

    image

    • Once you are done Right Click the Project and choose properties, Go to Build Events tab and add the following post build commands

    image

    cd "$(ProjectDir)"
    makecab.exe /F Package.ddf
    ren Package\MyDerivedContentType.cab MyDerivedContentType.wsp
    • This command will use the makecab utility after a successful build to create a CAB file as per the package.ddf directive file included. And will rename it to .wsp that can be used for the deployment.
    • In addition it will also create a solution folder which also includes this WSP and the setup.bat to help with the deployment. You can also use STSADM command line utility to ‘ADD’, ‘DEPLOY’ and ‘ACTIVATE’ the feature as required.

    Useful Links:

    Part – 1 , Part – 2 , Part – 3 , Part – 4

    Error : An unhandled exception occurred in the user interface.Exception Information: OSearch

    You might receive this error if you have not qualified the user account with the domain name

    I received this error while I was setting up Search Service on a MOSS machine.

    image

    I fixed it by setting the farm search service account qualified with a domain name.

    image