SharePoint Dragons

Nikander & Margriet on SharePoint

Monthly Archives: April 2012

Best practices regarding row limits in external lists

When working with external lists, a functionality of Business Connectivity Services (BCS), you’ve got to keep an eye on row limits.

Keep in mind two important limits:

  1. The default Max is 2,000 items
  2. The absolute Max is 25,000 items

Please see this link for more information: http://msdn.microsoft.com/en-us/library/hh144965.aspx

You should always define filters (it can be limit/comparison/wildcard filter) so that you can narrow your search and overcome others restrictions regarding a count of rows in the database. Especially when working with high volume of items, there might be cases in which you may have millions of items to pick, the bcs picker will show up to 200 items (this is a SharePoint restriction).

Please take a look at these articles about filter creation:

Also you may implement paging. Please take a look at these articles:

This info was taken from forum discussion: http://social.technet.microsoft.com/Forums/en-US/sharepoint2010general/thread/9dba356c-65f3-49be-a452-6934baee7216

For ongoing work on this topic, check out the latest version of Wiki page http://social.technet.microsoft.com/wiki/contents/articles/9628.sharepoint-2010-best-practice-row-limits-in-external-lists.aspx

An editor part for a visual web part

This is a follow up to blog post https://sharepointdragons.com/2012/04/06/a-web-part-editor-part-containing-a-drop-down-list/ . Here, we’ll create the same thing, but this time for a visual web part. The differences are minor, but still…

First, we’ve created a user control containing a simple label, just so we’ll be able to show something:

<%@ Assembly Name=”$SharePoint.Project.AssemblyFullName$” %>
<%@ Assembly Name=”Microsoft.Web.CommandUI, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c” %>
<%@ Register Tagprefix=”SharePoint” Namespace=”Microsoft.SharePoint.WebControls” Assembly=”Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c” %>
<%@ Register Tagprefix=”Utilities” Namespace=”Microsoft.SharePoint.Utilities” Assembly=”Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c” %>
<%@ Register Tagprefix=”asp” Namespace=”System.Web.UI” Assembly=”System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35″ %>
<%@ Import Namespace=”Microsoft.SharePoint” %>
<%@ Register Tagprefix=”WebPartPages” Namespace=”Microsoft.SharePoint.WebPartPages” Assembly=”Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c” %>
<%@ Control Language=”C#” AutoEventWireup=”true” CodeBehind=”VisualWebPart1UserControl.ascx.cs” Inherits=”VisualWebPartProject1.VisualWebPart1.VisualWebPart1UserControl” %>
<asp:Label ID=”Label1″ runat=”server” Text=”Label”></asp:Label>

The code behind for this user control contains a public string property. All the control does is display the value of this property in the label:

using System;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;

namespace VisualWebPartProject1.VisualWebPart1
{
    public partial class VisualWebPart1UserControl : UserControl
    {
        public string MyLabelText { get; set; }

        protected void Page_Load(object sender, EventArgs e)
        {
            Label1.Text = MyLabelText;
        }
    }
}

The editor part remains exactly as it was:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.WebControls;

namespace VisualWebPartProject1.VisualWebPart1
{
    public class WebPart1EditorPart : EditorPart
    {
        // Reference to the web part that uses this editor part, the parent web part needs to implement the IWebEditable interface to support custom editing controls
        protected VisualWebPart1 ParentWebPart { get; set; }
        protected DropDownList EditorChoices { get; set; }

        /// <summary>
        /// Does editor part init settings
        /// </summary>
        public WebPart1EditorPart()
        {
            Title = “Make a choice – good name here”;
        }

        /// <summary>
        /// Creates the dll
        /// </summary>
        protected override void CreateChildControls()
        {
            EditorChoices = new DropDownList();
            EditorChoices.Items.Add(new ListItem(“AAA”, “1”));
            EditorChoices.Items.Add(new ListItem(“BBB”, “2”));
            EditorChoices.Items.Add(new ListItem(“CCC”, “3”));
            Controls.Add(EditorChoices);

            base.CreateChildControls();
            ChildControlsCreated = true;
        }

        /// <summary>
        /// Reads current value from parent web part and show that in the ddl
        /// </summary>
        public override void SyncChanges()
        {
            EnsureChildControls();
            ParentWebPart = WebPartToEdit as VisualWebPart1;

            if (ParentWebPart != null && WebPartManager.Personalization.Scope == PersonalizationScope.Shared)
            {
                ListItem item = EditorChoices.Items.FindByValue(ParentWebPart.MyEditorPartChoice);
                if (item != null) item.Selected = true;
            }
        }

        /// <summary>
        /// Applies change in editor part ddl to the parent web part
        /// </summary>
        /// <returns></returns>
        public override bool ApplyChanges()
        {
            try
            {
                EnsureChildControls();
                ParentWebPart = WebPartToEdit as VisualWebPart1;

                if (ParentWebPart != null && WebPartManager.Personalization.Scope == PersonalizationScope.Shared)
                {
                    ParentWebPart.MyEditorPartChoice = EditorChoices.SelectedValue;
                }

                // The operation was succesful
                return true;
            }
            catch
            {
                // Because an error has occurred, the SyncChanges() method won’t be invoked.
                return false;
            }
        }
    }
}

The web part (ours is called VisualWebPart1.cs) that is responsible for loading the user control is a little different from what it was. Now, it has to cast the user control to our specific type and set our custom string property to the value that was retrieved from our editor part:

Control control = Page.LoadControl(_ascxPath);

var myVisualControl = control as VisualWebPart1UserControl;
if (MyEditorPartChoice == null)
myVisualControl.MyLabelText = “Make a choice first”;
else
myVisualControl.MyLabelText = “The value from the editor part choice: ” + MyEditorPartChoice;

Controls.Add(control);

The complete code for VisualWebPart1.cs looks like this:

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

namespace VisualWebPartProject1.VisualWebPart1
{
    [ToolboxItemAttribute(false)]
    public class VisualWebPart1 : WebPart, IWebEditable
    {
        // Visual Studio might automatically update this path when you change the Visual Web Part project item.
        private const string _ascxPath = @”~/_CONTROLTEMPLATES/VisualWebPartProject1/VisualWebPart1/VisualWebPart1UserControl.ascx”;

        protected override void CreateChildControls()
        {
            Control control = Page.LoadControl(_ascxPath);

            var myVisualControl = control as VisualWebPart1UserControl;
            if (MyEditorPartChoice == null)
                myVisualControl.MyLabelText = “Make a choice first”;
            else
                myVisualControl.MyLabelText = “The value from the editor part choice: ” + MyEditorPartChoice;

            Controls.Add(control);
        }

        /// <summary>
        /// Contains the value of the choice in the editor part drop down list
        ///
        /// Set the Personalizable attribute to true,
        /// to allow for personalization of tabs by users.
        /// This causes  this property to be shown in the web part tool pane and lets SharePoint take care of the storage/retrieval of this property in the SharePoint content database.
        /// </summary>
        [Personalizable(true)]
        public string MyEditorPartChoice { get; set; }

        /// <summary>
        /// Creates custom editor parts here and assigns a unique id to each part
        /// </summary>
        /// <returns>All custom editor parts used by this web part</returns>
        EditorPartCollection IWebEditable.CreateEditorParts()
        {
            var editors = new List<EditorPart>();
            var editorPart = new WebPart1EditorPart();
            editorPart.ID = ID + “_editorPart”;
            editors.Add(editorPart);

            return new EditorPartCollection(editors);
        }

        /// <summary>
        /// Returns parent web part to editor part
        /// </summary>
        object IWebEditable.WebBrowsableObject
        {
            get { return this; }
        }

    }
}

SharePoint Bloggers to follow

Interesting post containing a list of SharePoint Bloggers Mark Miller thinks you should follow because they frequently provide content of high value: https://www.nothingbutsharepoint.com/sites/eusp/Pages/20-SharePoint-Blogs-to-Follow.aspx Of course, we whole heartedly agree being listed here Smile, although to avoid people getting the wrong idea (especially people considering to hire us! please note the shameless plug for our consulting business) we should add that we really are developers/architects, not IT Pros.

Moving your taxonomy to a production environment

If you’re planning to move your taxonomy to a production environment in SPS 2010, consider using the Bulk TermSet Importer-Exporter: http://termsetimporter.codeplex.com/releases/view/48669#ReviewsAnchor

WinForm SharePoint list item editing tool

A free tool for doing mass upload and bulk edit in SharePoint: http://splistitemeditor.codeplex.com/releases/view/35050 We’ll have to give it a test spin, but it might be interesting to consider if you need this kind of functionality.

Gotcha for validating the textfield of the SharePoint DateTime control

If you’re planning to use the SharePoint date time control. a good place to start is the followiing: http://karinebosch.wordpress.com/sharepoint-controls/datetimecontrol-control/ It won’t tell you how to use validation controls in combination with it, and there’s an important gotcha involved. If you want to access the textfield rendered by the SharePoint date time control, you need to set the ControlToValidate property to the name of the control in the following format: [control id]$[control id]Date, for example: MyControl$MyControlDate, like so:

<SharePoint:DateTimeControl runat=”server” ID=”MyControl” DateOnly=”true” ShowWeekNumber=”true” LocaleId=”1043″ IsRequiredField=”true” />
<SharePoint:InputFormCustomValidator runat=”server” ID=”MyCustomValidator” ControlToValidate=”MyControl$MyControlDate”
Display=”Dynamic” SetFocusOnError=”true” OnServerValidate=”ValidateFromDateControl” />

Also see: http://www.greggalipeau.com/2008/06/27/sharepoint-datetimecontrol-validation/

Solving problems with ULS log file generation

If the ULS log files remain empty (0 KB) take the following steps to resolve:

  • Make sure you have enough space in your hardware driver.
  • Check timer and tracing service accounts information, the tracing service must use the account as Local Service.
  • Reset the timer service account password. Restarted the tracing service.
  • Check Diagnostic logging under Central Administration site, you can refer to:http://technet.microsoft.com/en-us/library/ee748656.aspx
  • Check the permissions on /12/logs folder

And these blogs may help you:

http://sharepointlearningcurve.blogspot.com/2010/04/sharepoint-2010-uls-problems-logs-are.html

http://www.eiben.weite-welt.com/2011/08/no-uls-logging-in-sharepoint-2010/

Taken from forum thread: http://social.technet.microsoft.com/Forums/en-US/sharepoint2010general/thread/e327f833-5e43-42d1-a330-f2d16c41106a

Check the following Wiki page for updates: http://social.technet.microsoft.com/wiki/contents/articles/9340.sharepoint-2010-solving-problems-with-uls-log-file-generation.aspx

SharePoint licensing

For some reason, customers always ask us about SharePoint licensing details. Since we’re not MS sales people, we generally don’t know the details. We’re storing this link for future reference: http://sharepoint.microsoft.com/en-us/buy/pages/licensing-details.aspx

Silverlight PowerShell Command Builder

We forgot all about this tool: a Silverlight app that allows you to build PowerShell commands for SharePoint 2010: http://www.microsoft.com/resources/TechNet/en-us/Office/media/WindowsPowerShell/WindowsPowerShellCommandBuilder.html It’s real easy to use and quite cool, although it actually goes against our principles. Trying to build PS cmds this way will actually prevent you from getting to learn PowerShell: not a good thing!

Content type galore

Never one to avoid the well treaden path, and hoping to find new pieces of information along the way or at least presenting a comfortable holistic view of the topic at hand: our new article is about content types. Walk along, if you please?

Creating a content type programmatically

If you create a new custom content type, it always need to inherit from an existing base content type. Programmatically, this means you can retrieve an existing content type, and use that during the creation of your own content type, like so:

using (var site = new SPSite(“http://astro”))
{
    using (var web = site.OpenWeb())
    {
        try
        {
            string ctname = “My CT”;
            SPContentType myCt = web.ContentTypes[ctname];

            // Create a new content type if it doesn’t exist yet.
            if (myCt == null)
            {
                var ctParent = web.ContentTypes[“Item”];
                myCt = new SPContentType(ctParent, web.ContentTypes, ctname);

                // To improve manageability, define a description and group
                myCt.Description = “My test content type”;
                myCt.Group = “Lois and Clark Content Types”;

                // Now add the content type to a target site
                web.ContentTypes.Add(myCt);
            }
        }
        catch (Exception err)
        {
            Console.WriteLine(err.Message);
        }
    }

Or you can retrieve the base content type via the SPBuiltInContentTypeId class that retrieves the content type ids for every built-in content type. It should be a little faster, and it certainly allows for less room when it comes to making typos. It goes like this:

var ctParent = web.ContentTypes[SPBuiltInContentTypeId.Item];

Once added to the content types collection of a SharePoint site, you’re free to modify your custom content type according to your specific needs.  For instance, you can change the display name of the Title field.

var title = myCt.FieldLinks[“Title”];
title.DisplayName = “my custom title”;

Or, you can add new fields based on existing site columns:

// Add new fields that are based on existing site columns:
if (myCt.FieldLinks[“WorkPhone”] == null)
{
    myCt.FieldLinks.Add(new SPFieldLink(web.Fields.GetFieldByInternalName(“WorkPhone”)));
}

Don’t forget to save after you’re done:

// Finally, save changes.
myCt.Update();

This causes the complete code listing to look like this:

using (var site = new SPSite(“http://astro&#8221;))

{
    using (var web = site.OpenWeb())
    {
        try
        {
            string ctname = “My CT”;
            SPContentType myCt = web.ContentTypes[ctname];

            // Create a new content type if it doesn’t exist yet.
            if (myCt == null)
            {
                var ctParent = web.ContentTypes[SPBuiltInContentTypeId.Item];
                myCt = new SPContentType(ctParent, web.ContentTypes, ctname);

                // To improve manageability, define a description and group
                myCt.Description = “My test content type”;
                myCt.Group = “Lois and Clark Content Types”;

                // Now add the content type to a target site
                web.ContentTypes.Add(myCt);
            }

            // Change an existing field
            var title = myCt.FieldLinks[“Title”];
            title.DisplayName = “my custom title”;

            // Add new fields that are based on existing site columns:
            if (myCt.FieldLinks[“WorkPhone”] == null)
            {
                myCt.FieldLinks.Add(new SPFieldLink(web.Fields.GetFieldByInternalName(“WorkPhone”)));
            }

            // Finally, save changes.
            myCt.Update();
        }
        catch (Exception err)
        {
            Console.WriteLine(err.Message);
        }
    }
}

Having that of our chests, let’s forget about creating content types programmatically, and see how to do it declaratively, the CAML way. Wouldn’t you agree that doing something in CAML always feels like you’re doing something “fundamentally SharePointistic”? It feels like talking to your forefathers from the day of yore.

Creating a content type declaratively

Or you can create one declaratively as described at http://msdn.microsoft.com/en-us/library/gg295290.aspx. If you do so, you need to understand the structure of the content type id. It looks like this:

[parent id][00][guid]

Previously, we’ve used the item content type as the base type for our custom content type. As it happens, the item content type is the root of all content types. It’s id is 0x01 and you’ll see it a lot. 00 is just a delimiter between the parent content type id. The guid of your custom content type id needs to be created by yourself. You can use Tools > Create GUID if you’ve installed VC++, or create a simple app that uses the line Guid.NewGuid().ToString(); to do it yourself.

So, in this example:

0x01004edcc88144e24fabab267fd72e667051

Here, you see that we’ve created a content type with the guid 4edcc88144e24fabab267fd72e667051 that inherits from the item content type. As you can imagine, once you get deeper down the inheritance levels, the content type id’s can get quite large. Because of that, you can keep the content type id small by simply adding two hexadecimal digits (but not “00”) at the end. See http://msdn.microsoft.com/en-us/library/aa543822(v=office.12).aspx for more info. If you follow this way a child of content type 0x01004edcc88144e24fabab267fd72e667051 gets the following id:

0x01004edcc88144e24fabab267fd72e66705101

And another becomes:

0x01004edcc88144e24fabab267fd72e66705102

Best practice prescribes that if you inherit a content type from a SharePoint content type or a 3rd party, you should start appending the id with the format “00” and a GUID. After that, if you’re inheriting from your own content types use the minimal form and append two hexadecimal digits.

Please note: We cheated a little here. As far as we know, this is not an officially MS prescribed best practice, it is ours. You should follow it nevertheless :-)!

The aforementioned MSDN article (http://msdn.microsoft.com/en-us/library/gg295290.aspx) describes how to add a choice field. If you follow it, you’ll already be able to verify that the schema for the CAML defined in elements.xml (caml.net.intellisense.xsd) is far from complete and says “The Inherits attribute is not declared.” For now, accept this as a fact of life and hope that it’ll improve in the future. Or don’t, and download CAML.NET IntelliSense: https://sharepointdragons.com/2011/12/13/intellisense-for-caml/, it’ll add IntelliSense-like support when editing CAML files.

If you have followed the MSDN example, take some time to look at the elements.xml file. The choice field was easy to add (uh, copy) but what about the other field types? Next, we’ll discuss how to create each and every one of them.

But if you have written them, I bet you have seen yourself trying various elements in the elements.xml file(s), guessing, and heck even reverse engineering parts of sharepoint that ship with sharepoint.

Here is a quick trick.

You can export the entire list schema as CAML using the following –

http://yoursiteurl/_vti_bin/owssvr.dll?Cmd=ExportList&List=%7YourListGUID%7D

For example, choose List Settings in the browser to obtain your list GUID:

http://astro/_vti_bin/owssvr.dll?Cmd=ExportList&List=%7BD093BFE5%2D282E%2D41E9%2D99A2%2D3CD9AE11A704%7D

This is quite awesome, because it straight off gives you all the Fields, Views, and Content Types involved. The XML can still be quite verbose, so it pays of to check out which of the settings you want to keep or change. From there, you can copy CAML fields in your own elements.xml file.

Anyone who hasn’t read up on the URL protocol for calling owssvr.dll in the WSS SDK is really missing out.

Choice field

A choice field is of type Choice, and allows you to define multiple elements in the <CHOICES> section.

<Field ID=”{30C3D21A-A7C9-410E-A896-82875475F697}” Name=”ReviewStatus” DisplayName=”Review Status” Type =”Choice” >
    <CHOICES>
      <CHOICE>Review Required</CHOICE>
      <CHOICE>Review in Progress</CHOICE>
      <CHOICE>Review Completed</CHOICE>
    </CHOICES>
  </Field>

Please note: You do have to create a new GUID and use that as the id for the field. Again, you could use Tools > Create GUID to do this.

You’ll also have to add a field reference pointing to the field:

<FieldRef ID=”{30C3D21A-A7C9-410E-A896-82875475F697}” Name=”ReviewStatus” DisplayName=”Review Status”  />

Single line of text field

A single line of text has the type Text and has a default max length of 255. Although you’re better off using CAML.NET IntelliSense to remember this stuff for you, we still like to point out that ColName refers to a name in the underlying database structure. If you specify it, the name has to match. If you omit the attribute, the server generates a new non-colliding column name. The RowOrdinal column specifies the database location for the field. So, although both ColName and RowOrdinal columns can be omitted without trouble, it certainly seems more efficient to reuse existing settings.

The field definition and reference look like this:

<Field ID=”{5D956B33-993C-481E-9EBB-FAC949FCE34C}” Name=”MySText” DisplayName=”My custom single line of text” Type=”Text” MaxLength=”255″ ColName=”nvarchar3″ RowOrdinal=”0″ />

<FieldRef ID=”{5D956B33-993C-481E-9EBB-FAC949FCE34C}” Name=”MySText” DisplayName=”My custom single line of text”  />     

Multiline text field

Multiline fields are of type Note. If the RichText attribute is set to true, the field displays rich text formatting. The RichTextMode attribute defines specifics about the rich text settings and is set to FullHtml by default. It corresponds to the SPRichTextMode enumeration (see http://msdn.microsoft.com/en-us/library/microsoft.sharepoint.sprichtextmode.aspx) which has the following members:

  • Compatible, displays plain text, or display rich text with bold, italic, or text alignment. Value = 0.
  • FullHtml, displays enhanced rich text, including pictures, tables, and hyperlinks. Value = 1.
  • HtmlAsXml, displays HTML as XML. Value = 2. This value is not supported by multiline text fields.
  • ThemeHtml, displays HTML with inline style specifications. This value is not supported by multiline text fields.

The IsolateStyles attribute instructs the server to rewrite the HTML (that is generated by the rich text editor) so that it doesn’t conflict with the rendering of the surrounding page. The default value of the NumLines attribute is 6 and corresponds to the number of lines shown in the HTML text area representing the multiline text field. It doesn’t limit the number of lines users are allowed to enter.

The field definition and reference look like this:

<Field ID=”{79557C0C-99AC-4157-A9EC-F98347AD91AB}” Name=”MyMText” DisplayName=”My multiliner” Type=”Note” RichText=”TRUE” RichTextMode=”FullHtml” IsolateStyles=”TRUE” NumLines=”6″ ColName=”ntext2″ RowOrdinal=”0″ />

Yes/No field

The Yes/No field presents a checkbox to the end user and is of type Boolean. The <Default> element allows you to choose the default value for this field.

The field definition and reference look like this:

<Field ID=”{FCFB7503-CF6F-41BF-A3C8-1FC779728148}” Name=”MyYesNo” DisplayName=”MyYesNo field” Type=”Boolean” ColName=”bit1″ RowOrdinal=”0″>
  <Default>1</Default>
</Field>

<FieldRef ID=”{FCFB7503-CF6F-41BF-A3C8-1FC779728148}” Name=”MyYesNo” DisplayName=”MyYesNo field” />

People (or group) picker field

The People picker (which is also used to select groups)  is of type User. It retrieves those users from the UserInfo database table in the SharePoint content database, a fact that is reflected in the List attribute. The ShowField attribute determines which field name gets displayed. If you don’t specify a value here a hyperlinked text from the Title field of the record in the external list is displayed. By default, the value of ImnName is used. The ImnName value doesn’t directly correspond to a column in the UserInfo table, but refers to a “Name with presence” (name including presence awareness symbol), a computed field generated by SharePoint when used. The UserSelectionMode attribute allows you to specify whether you’ll only allow users to pick users, or both users and groups. The UserSelectionScope determines the scope within which you can select users. If it’s value is set to 0, there are no restrictions. If it has a value greater than zero, it’s value refers to the id of a specific SharePoint group, and you’ll only be allowed to select users within that SharePoint group.

The field definition and reference look like this:

<Field ID=”{6BD0C2BC-B5F4-4874-AED5-8AB3AA2CBBC9}” Name=”MyPeople” DisplayName=”My People or group picker” Type=”User” List=”UserInfo” ShowField=”ImnName” UserSelectionMode=”PeopleOnly” UserSelectionScope=”0″ ColName=”int1″ RowOrdinal=”0″ />

<FieldRef ID=”{6BD0C2BC-B5F4-4874-AED5-8AB3AA2CBBC9}” Name=”MyPeople” DisplayName=”My People or group picker” />

Elements.xml

The resulting Elements.xml file containing all the fields that were discussed looks like this:

<?xml version=”1.0″ encoding=”utf-8″?>
<Elements xmlns=”http://schemas.microsoft.com/sharepoint/”>
 
  <Field ID=”{FCFB7503-CF6F-41BF-A3C8-1FC779728148}” Name=”MyYesNo” DisplayName=”MyYesNo field” Type=”Boolean” ColName=”bit1″ RowOrdinal=”0″>
    <Default>1</Default>
  </Field>

  <Field ID=”{79557C0C-99AC-4157-A9EC-F98347AD91AB}” Name=”MyMText” DisplayName=”My multiliner” Type=”Note” RichText=”TRUE” RichTextMode=”FullHtml” IsolateStyles=”TRUE” NumLines=”6″
         ColName=”ntext2″ RowOrdinal=”0″ />

  <Field ID=”{5D956B33-993C-481E-9EBB-FAC949FCE34C}” Name=”MySText” DisplayName=”My custom single line of text” Type=”Text” MaxLength=”255″ ColName=”nvarchar3″ RowOrdinal=”0″ />
 
  <Field ID=”{30C3D21A-A7C9-410E-A896-82875475F697}” Name=”ReviewStatus” DisplayName=”Review Status” Type=”Choice” >
    <CHOICES>
      <CHOICE>Review Required</CHOICE>
      <CHOICE>Review in Progress</CHOICE>
      <CHOICE>Review Completed</CHOICE>
    </CHOICES>
  </Field>

  <Field ID=”{6BD0C2BC-B5F4-4874-AED5-8AB3AA2CBBC9}” Name=”MyPeople” DisplayName=”My People or group picker” Type=”User” List=”UserInfo” ShowField=”ImnName”
         UserSelectionMode=”PeopleOnly” UserSelectionScope=”0″ ColName=”int1″ RowOrdinal=”0″ />

  <!– Parent ContentType: Item (0x01) –>
  <ContentType ID=”0x01004edcc88144e24fabab267fd72e667051″
               Name=”MyContentTypeProject – ContentType1″
               Group=”Custom Content Types”
               Description=”My Content Type”
               Inherits=”TRUE”
               Version=”0″>
    <FieldRefs>
      <FieldRef ID=”{30C3D21A-A7C9-410E-A896-82875475F697}” Name=”ReviewStatus” DisplayName=”Review Status” />
      <FieldRef ID=”{5D956B33-993C-481E-9EBB-FAC949FCE34C}” Name=”MySText” DisplayName=”My custom single line of text” />
      <FieldRef ID=”{79557C0C-99AC-4157-A9EC-F98347AD91AB}” Name=”MyMText” DisplayName=”My multiliner” />
      <FieldRef ID=”{FCFB7503-CF6F-41BF-A3C8-1FC779728148}” Name=”MyYesNo” DisplayName=”MyYesNo field” />
      <FieldRef ID=”{6BD0C2BC-B5F4-4874-AED5-8AB3AA2CBBC9}” Name=”MyPeople” DisplayName=”My People or group picker” />
    </FieldRefs>
  </ContentType>
</Elements>

That’s all folks!