SharePoint 2007 - Step by Step Creating Custom List Definition and Custom Content Type using VS 2008 (VSeWSS 1.2)

Project Requirement:

Contoso Inc. is a BPO organization working on Medical Transcription. Information workers listen to the voice recordings and create text files based on those recordings. 3 Text files (test.txt, test2.txt, test3.txt) are given as sample.

IT department of Contoso Inc. has implemented MOSS 2007 for their document management and back office solution. CTO wanted to store the above mentioned text files in special document libraries which will have following mandatory columns “Patient Name”, “Attending Doctor”, “Patient Number” and “Date of Service”.

Once an Information Worker will complete typing the text file, he/she will upload the text file to any of these document libraries and afore mentioned metadata columns will be populated automatically by selecting the necessary values from the text file. Associated values for these columns are stored at the beginning of the text file (see sample).

Solution:

We will create a custom content type including all these fields and will create a custom list definition which will use this custom content type and also have the necessary code to extract the metadata columns from the uploaded text file. Additionally we will add code to make sure that the users upload only text files.

Step1:

Start VS 2008 and select Visual C# > SharePoint. Select List Definition as the project template. Rename the project as ContosoTranscriptDocLib and click OK. In the List Definition Setting dialog box click OK.

Step2:

In the solution explorer delete the ListDefinition1 folder and right click on the project and choose Add>New Item>List Definition and change the name from ListDefinition1 to ContosoTranscriptDocLib. In the List Definition Setting dialog box select document library and select Add with event receiver.

Step3:

Again in the solution explorer right click on the project and choose Add>New Item>Content Type and change the name from ContentType1 to ContosoTranscriptDoc. In the Content Type Setting dialog box select document.

Step4:

In the solution explorer open the ContosoTranscriptDoc.xml file under ContosoTranscriptDoc folder. Add the following few lines within <FieldRefs> </FieldRefs> tags.

<FieldRef ID="{3154C55D-956E-4049-831F-39AFF3AB7787}" Name="Patient" Required="TRUE" ShowInDisplayForm="TRUE" ShowInNewForm="FALSE" ShowInEditForm="TRUE" />

                   <FieldRef ID="{4F294260-B36B-4fd0-A5A8-E2D777E76E73}" Name="Doctor" Required="TRUE" ShowInDisplayForm="TRUE" ShowInNewForm="FALSE" ShowInEditForm="TRUE" />

          <FieldRef ID="{2EE0BFF8-FBEE-4f93-822B-608138CAB1FD}" Name="PNumber" Required="TRUE" ShowInDisplayForm="TRUE" ShowInNewForm="FALSE" ShowInEditForm="TRUE" />

                   <FieldRef ID="{5BF5C5BB-F020-453d-8194-B9553487051A}" Name="ServiceDate" Required="TRUE" ShowInDisplayForm="TRUE" ShowInNewForm="FALSE" ShowInEditForm="TRUE" />

Replace the GUIDs of each FieldRef using Tools>Create Guid menu.

Step5:

Before </Elements> Tag add following few lines:

<Field ID="{3154C55D-956E-4049-831F-39AFF3AB7787}" Type="Text" Name="Patient" DisplayName="Patient Name" Sealed="TRUE" StaticName="Patient">

  </Field>

  <Field ID="{4F294260-B36B-4fd0-A5A8-E2D777E76E73}" Type="Text" Name="Doctor" DisplayName="Attending Doctor" Sealed="TRUE" StaticName="Doctor">

  </Field>

  <Field ID="{2EE0BFF8-FBEE-4f93-822B-608138CAB1FD}" Type="Text" Name="PNumber" DisplayName="Patient Number" Sealed="TRUE" StaticName="PNumber">

  </Field>

  <Field ID="{5BF5C5BB-F020-453d-8194-B9553487051A}" Type="DateTime" Name="ServiceDate" DisplayName="Date of Service" Sealed="TRUE" StaticName="ServiceDate">

  </Field>

Match the GUIDs of each Field with the corresponding FieldRef.

Step 6:

Change the Description attribute of ContentType Tag to "Contoso Transcript Content Type".

Step 7:

Open ListDefinition.xml file under ContosoTranscriptDocLib folder in the solution explorer and change the ListTemplate Tag as followed:

<ListTemplate Name="ContosoTranscriptDocLib"

                DisplayName="Contoso Transcript Document Library"

        Description="Document library to upload text file associated with Medical Transcription"

                BaseType="1"

                Type="101"

                OnQuickLaunch="TRUE"

                SecurityBits="11"

                Sequence="110"

                Image="/_layouts/images/itdl.gif"

                DocumentTemplate="101" />

Step 8:

Open ContosoTranscriptDoc.xml once again and copy the <ContentType ID (copy the content within “”). Open Schema.xml file under ContosoTranscriptDocLib folder and in the <ContentTypeRef ID  Tag replace the content (within “”). Copy the 4 field tags from ContosoTranscriptDoc.xml and paste it under <Fields> tag, before first <Field> tag.

Step 9:

Open ItemEventReceiver.cs file under ContosoTranscriptDocLib folder and add this using statement: using System.IO;. After the default constructor (ContosoTranscriptDocLibItemEventReceiver) add following few lines:

///////////////Custom Code/////////////////

        /// <summary>

        /// String between MR# and DATE

        /// +4 is because "MR#:" itself has the length of 4 characters

        /// </summary>

        /// <param name="str"></param>

        /// <returns></returns>

        private string GetNo(string str)

        {

            int first = str.IndexOf("MR#:") + 4;

            int last = str.LastIndexOf("DATE:");

            string ouput = str.Substring(first, last - first);

            return ouput.Trim();

        }

        /// <summary>

        /// String between DOCTOR and SUBJECTIVE

        /// </summary>

        /// <param name="str"></param>

        /// <returns></returns>

        private string GetDoctor(string str)

        {

            int first = str.IndexOf("DOCTOR:") + 7;

            int last = str.LastIndexOf("SUBJECTIVE:");

            string ouput = str.Substring(first, last - first);

            return ouput.Trim();

        }

        /// <summary>

        /// String between DATE and DOCTOR

        /// </summary>

        /// <param name="str"></param>

        /// <returns></returns>

        private string GetDate(string str)

        {

            int first = str.IndexOf("DATE:") + 5;

            int last = str.LastIndexOf("DOCTOR:");

            string ouput = str.Substring(first, last - first);

            return ouput.Trim();

        }

        /// <summary>

        /// String between NAME and MR

        /// </summary>

        /// <param name="str"></param>

        /// <returns></returns>

        private string GetPatient(string str)

        {

            int first = str.IndexOf("NAME:") + 5;

            int last = str.LastIndexOf("MR#:");

            string ouput = str.Substring(first, last - first);

            return ouput.Trim();

        }

        /// <summary>

        /// Extract the content of the file in a string

        /// </summary>

        /// <param name="itemID"></param>

        /// <param name="siteUrl"></param>

        /// <param name="listTitle"></param>

        /// <returns></returns>

        private string GetContent(int itemID, string siteUrl, string listTitle)

        {

            SPWeb web = new SPSite(siteUrl).OpenWeb();

            SPList list = web.Lists[listTitle];

            SPListItem item = list.GetItemById(itemID);

      TextReader tr = new StreamReader(item.File.OpenBinaryStream());

            string content = tr.ReadToEnd();

            tr.Close();

            return content;

        }

        /////////////Custom Code//////////////////

Step 10:

Uncomment the ItemAdded method and add following lines there:

int itemID = properties.ListItem.ID;

            string siteUrl = properties.WebUrl + "/";

            string listTitle = properties.ListTitle;

            string content = GetContent(itemID, siteUrl, listTitle);

            string patient = GetPatient(content);

            string doctor = GetDoctor(content);

            string serviceDate = GetDate(content);

            string patientNo = GetNo(content);

         properties.ListItem["Patient Name"] = patient;

            properties.ListItem["Attending Doctor"] = doctor;

            properties.ListItem["Patient Number"] = patientNo;

            properties.ListItem["Date of Service"] = DateTime.Parse(serviceDate);

            properties.ListItem.Update();

Step 11:

Uncomment the ItemAdding method and add following lines there:

string extension = properties.AfterUrl.Substring(properties.AfterUrl.LastIndexOf(".") + 1);

            if (extension != "txt")

            {

                properties.Cancel = true;

                properties.ErrorMessage = "Please upload only text files";

            }

Step 12:

Right click on the project in Solution Explorer and select properies. In the properties window go to Debug and in the Start Browser with URL option add the URL of your destination site. Now Build the site and deploy it from the Build menu.

Step 13:

Open the destinantion site and go to Site Actions>Site Settings>Site Content Type. You will find ContosoTranscriptDoc under Development section. Go to Site Actions>Create. You will find Contoso Transcript Document Library under Libraries section. Click on it and create a document libarary called testtranscript. Select None as the document template.

Step 14:

Once the document library is created, upload the first sample (test.txt). Once the file is uploaded, the Edit Item window will open. Fill up the Title field as “test” and click on Check In. Similalrly upload rest of the sample files and in each case you will see the fields “Patient Name”, “Attending Doctor”, “Patient Number” and “Date of Service” are auto populated. Now try to upload any file other than text files and it will show error saying "Please upload only text files".

sample.zip