Dev Team Assemble

Evil beware!
Add to Technorati Favorites

Archive

Category: Development

One thing I always seem to forget when moving from one db system to the other (not using DB2 all that often) is how to select the TOP n rows from a query.

In MS SQL Server this is expressed as SELECT TOP n * FROM [table] ...

the equivilent in DB2 is SELECT * FROM [table] FETCH FIRST n ROWS ONLY

Technorati Tags: ,

One of the things I was working on today was trying to get an actual image from the library was that initially I was expecting to get a PublishingImage.  All the samples on MSDN and the ones strewn about the web refer to using the ImageFieldValue and getting it from a field in the SPListItem.  Like outlined on MSDN :

  // Retrieve the current value from an SPListItem with a
  // column of the ImageField type with the name imageFieldName
  ImageFieldValue currentFieldValue =
        listItemWithImageField[imageFieldName] as ImageFieldValue;

The problem is this only works for images that are in a list, like the PublishingRollupImage of a page that links to an image in the Site Collection Images library.  The actual images in the library are stored as documents (Referenced using SPFile) so in order utilize them I need to extract the information out and create an image tag for it...like so:

 
     ImageFieldValue imageValue = new ImageFieldValue(
          string.Format("<img src=\"{0}\" alt=\"{1}\" />",
          file.Url, file.Title == null ? string.Empty : file.Title));
 

Now that I had the ImageFieldValue it was easy to work with. I could manipulate many aspects of the image using this object and then save it for rendering using ToString(). Funny thing is for my purposes (ImageGallery xml generation) I didn't even end up needing this code after all...frustrating but a good learning experience.

Props to Phanat Chan as he did the initial development on this.

Technorati Tags: , ,

So I got this error the other day when putting together a dev site collection usign varations:

An error was encountered performing this operation. You may re-try the operation, and you may need to clean up the half-created data first before re-trying. If the problem persists, please contact your system administrator

This was actually a fairly easy fix for me.  I simply had to enable the publishing features in my site.  Which is funny...because they should have been on but I must have overlooked that.  :)

Technorati Tags: , , , ,

I came across this problem recently. Its a little strange and only happened once I changed my base webpart class to inherit from Microsoft.SharePoint.WebPartPages.WebPart. There seems to be two fixes for this problem that I implemented:

  • remove the XMlNamespace from class declaration
  • Use a .dwp file instead of a .webpart file in your feature folder

Technorati Tags: , ,

For the last little bit I have been working on learning how to package up all site infrastructure into a single feature.  All of this is pretty straight forward and I didn't really have any issues.....UNTIL  I tried to get lookup columns working.

Using CAML

I did some reading on the subject and apparently you can do all of this using CAML alone.  I came across a post from Josh Gaffery supporting this claim, but I simply could not get this working...so i gave up after spinning my wheels on it for longer than I wanted to.  Josh's approach is to use the list URL as opposed to the GUID that links the column to the source list and he has put up an update explaining it further.  Nonetheless....didn't work for me.

Using Feature Receiver

I knew that at this point I would have to take the feature reciever approach and modify the fields in place or create them.  I found two sources that both take different approachs to this problem.

  • Chris O'Brien has put together the a project on CodePlex that will create the lookup columns at activation time.  This actully sounds like a pretty good approach but unfortunately it didn't work for me.  I dont know if there is something wrong with my environment but I encountered a few errors doing this...things like the fields not rendering on the page layouts and getting the "The local device name is already in use. (Exception from HRESULT: 0x80070055)" error.
  • Waldek Mastykarz has a great post on creating the columns via code here.

Basically I took a hybrid approach to doing this by mixing the two approaches mentioned above.  I created a custom XML file that I deploy into the layouts directory and then use a feature reciever to read the xml content and create lookup columns based on this.  I also added a deactiving event to remove the fields when the feature is deactivated.  Heres the feature reciever code:

public override void FeatureActivated(SPFeatureReceiverProperties properties)
        {
            using (SPSite site = properties.Feature.Parent as SPSite)
            {
                string contentTypes = null;
                string listName = null;
                string fieldName = null;
                string groupName = null;
                string staticName = null;
                string lookupFieldName = "Title";
                bool mult = false;
                bool required = false;
                string filePath = properties.Feature.Properties[
                   "ColumnDefinitionPath"].Value;
 
                XmlTextReader xReader = new XmlTextReader(
                  HttpContext.Current.Server.MapPath(@"~\_layouts\" + filePath));
                while (xReader.Read())
                {
                    if (xReader.LocalName == "Field")
                    {
                        #region Get values from attributes
                        if (xReader.MoveToAttribute("List"))
                        {
                            listName = xReader.Value;
                            xReader.MoveToElement();
                        }
                        if (xReader.MoveToAttribute("Name"))
                        {
                            fieldName = xReader.Value;
                            xReader.MoveToElement();
                        }
                        if (xReader.MoveToAttribute("StaticName"))
                        {
                            staticName = xReader.Value;
                            xReader.MoveToElement();
                        }
                        if (xReader.MoveToAttribute("Group"))
                        {
                            groupName = xReader.Value;
                            xReader.MoveToElement();
                        }
                        if (xReader.MoveToAttribute("LookUpField"))
                        {
                            lookupFieldName = xReader.Value;
                            xReader.MoveToElement();
                        }
                        if (xReader.MoveToAttribute("ExistInContentTypes"))
                        {
                            contentTypes = xReader.Value;
                            xReader.MoveToElement();
                        }
                        if (xReader.MoveToAttribute("Mult"))
                        {
                            bool.TryParse(xReader.Value, out mult);
                            xReader.MoveToElement();
                        }
                        if (xReader.MoveToAttribute("Required"))
                        {
                            bool.TryParse(xReader.Value, out required);
                            xReader.MoveToElement();
                        }
 
                        #endregion
 
                        SPFieldLookup lookup = CreateLookupField(
                          fieldName, groupName, required, mult, site.RootWeb,
                          site.RootWeb.Lists[listName], lookupFieldName, staticName);
                        if (contentTypes != null)
                            foreach (string s in contentTypes.Split(','))
                            {
                                LinkFieldToContentType(s.Trim(), (SPField)lookup);
                            }
                    }
                }
 
                xReader.Close();
 
            }
        }
 
        public static SPFieldLookup CreateLookupField(
          string fieldName, string group, bool required, bool allowMultipleValues,
          SPWeb w, SPList lookupList, string lookupField, string staticName)
        {
            w.Fields.AddLookup(fieldName, lookupList.ID,
               lookupList.ParentWeb.ID, required);
            SPFieldLookup lookup = (SPFieldLookup)w.Fields[fieldName];
            lookup.AllowMultipleValues = allowMultipleValues;
            lookup.LookupField = lookupField;
            lookup.StaticName = staticName;
            lookup.Group = group;
            lookup.Update(true);
            return lookup;
        }
 
        public static void LinkFieldToContentType(string contentType, SPField field)
        {
            using (SPSite site = SPContext.Current.Web.Site as SPSite)
            {
                SPContentType ct = site.RootWeb.ContentTypes[contentType];
                ct.FieldLinks.Add(new SPFieldLink(field));
                ct.Update(true); // will update children
            }
        }

As you can read from the above code the xml file would need to have a node like below for each lookup column:

 
<Field
         Type="Lookup"
         List="Access Type"
         Name="AccessTypeColumn"
         StaticName="Access_x0020_Type"
         Group="Infrastructure"
         ExistInContentTypes="THIS IS A COMMA DELIMITED LIST OF CONTENT NAMES"
         LookUpField="Title"
         Mult="TRUE"
         Required="FALSE"
        />
 

The Final Project

So here are all the pieces of my infrastructure project. Notice the placement of the lookupfields xml file...this is because the layouts directory is setup as a virtual directory for every sharepoint site and we can read files from there without a permissions problem.

12/TEMPLATES/FEATURES/myfeature/lists.xml this contains the source lists for the lookup fields
12/TEMPLATES/FEATURES/myfeature/contenttypes.xml this contains the content type definitions MINUS the lookup fields
12/TEMPLATES/FEATURES/myfeature/sitecolumns.xml this contains all the other fields included in the content types
12/TEMPLATES/FEATURES/myfeature/feature.xml the feature def
12/TEMPLATES/LAYOUTS/myfeature/lookupfields.xml this contains all the lookup fields that need to be provisioned

Hopefully this helps anyone who's been having problems getting this going. And a big thanks to Waldek, Chris and Josh for their posts.

Technorati Tags: , , , ,

I started getting this error recently on my development box after I started using WSP Builder.  I really like this program but I was a little put off by this error.  Obvisouly it is recycling  the worker process or something along those lines (too lazy to look it up).  I am fine with it when it comes back online after a few seconds but I was having instances where it was hanging there...stuck in 503 limbo. 

Turns out the problem is the application pool is stuck in a stopped state and the fix is simply enough to restart it.

Technorati Tags: , , ,

Sometimes when I am working with SharePoint I really feel like I got it.  You now that feeling you get when you know exactly what you are doing and have no problems implementing it...then there are times when I really just want to smash something.  And it really doesn't matter what...it could be anything!  This is the feeling I got in the last couple of days working with custom field types in SharePoint.

It seems there are lots of blogs and articles out there talking about how to do it, but from what I could see (and to be fair I did not read them all so if you know of some good posts that would be great) it felt like most of the time I was only getting half the story.  I just finished putting together a very basic Custom Field Type that will display a multi line textbox in edit/new mode and simply display the value in a literal control in display mode.  In the grand scheme of things I am building a base XML Field Type to use for a series of additional Custom field types so essentially I want to store a string (yes I could use the XmlDocument)...but alas thats a story for another day.

So a bit of a primer, or rehash so I don't forget, when developing custom field types there are many pieces to it....not all of them required.  Here is a list of the items and what they do:

  • Field Type class - this class acts as the controller and hooks the rendering control, field type xml definition and the value class together.  It also provides validation at the field level via the GetValidatedString() method of the SPField object
  • Field Control class - this is the rendering engine and gives you the power to display your control in any manner you wish as well as perform validation on the data being saved via the UI.
  • Field Value class - allows for custom logic to be put around mutiple column fields and different data structures that will be storing data for your field type.
  • .ascx file in CONTROLTEMPLATES directory - this supplies rendering markup via a user control and hooks into the field control class
  • fldtypes_* - this file that gets installed into the 12/TEMPLATES/XML directory and contains the information that SharePoint requires in order to load your field type into the system.  Such as the assembly to use, the parent type and other information.  This is required if the type is going to be applied to content types and become a field on a list.

So for my requirements I only needed the field type, the field control and the fldtypes_xxx.xml file.  Lets look at the field type class I built

public class XmlFieldType : SPField
   {
        public XmlFieldType(SPFieldCollection fields, string fieldName) : base(fields, fieldName) { }
        public XmlFieldType(SPFieldCollection fields, string fieldName, string displayName) : base(fields, fieldName, displayName) { }
 
        public override BaseFieldControl FieldRenderingControl
        {
            get
            {
                BaseFieldControl fldControl = new XmlFieldControl();
                fldControl.FieldName = InternalName;
                return fldControl;
            }
        }
 
        public override object GetFieldValue(string value)
        {
            if (string.IsNullOrEmpty(value))
                return null;
            return value;
        }
 
        public override Type FieldValueType
        {
            get { return typeof(string); }
        }
 
        public override string DefaultValue
        {
            get
            {
                XmlDocument doc = new XmlDocument();
                doc.LoadXml(this.SchemaXml);
                XmlNode nodeInFieldSchema = doc.SelectSingleNode("Field/Default");
                if (nodeInFieldSchema != null)
                    return nodeInFieldSchema.InnerXml;
                return null;
            }
            set { base.DefaultValue = value; }
        }
 
        public override string GetValidatedString(object value)
        {
            base.GetValidatedString(value);
            if (value == null)
            {
                if (this.Required) throw new SPFieldValidationException("Invalid value for required field.");
                return string.Empty;
            }
            else
            {
                return value.ToString();
            }
        }
}

Lets review

  • The two constructors are required...don't even bother
  • FieldRenderingControl() method tells the field type which control to use
  • GetFieldValue() method returns the value of the field....if we were using a custom type you would cast that to the appropriate type here
  • FieldValueType() - get the type of the Value class
  • DefautValue() - this gets the default value from the field if one is defined
  • GetValidatedString() - perform field level validation

The Field Control Class is fairly simple as well:

public class XmlFieldControl : BaseFieldControl
{
        protected Literal _values;
        protected TextBox _editor;
 
        protected override void OnInit(EventArgs e)
        {
            base.OnInit(e);
            EnsureChildControls();
        }
 
        protected override void CreateChildControls()
        {
 
            if (this.Field == null || this.ControlMode == SPControlMode.Invalid)
                return;
 
            Controls.Clear();
            base.CreateChildControls();
            _editor = new TextBox();
            _editor.TextMode = TextBoxMode.MultiLine;
            _editor.Height = new Unit(300);
            _editor.Width = new Unit(500);
            Controls.Add(_editor);
 
            if (ControlMode == SPControlMode.Display)
            {
                _values = new Literal();
                _values.Text = Convert.ToString(ItemFieldValue);
                Controls.Add(_values);
            }
        }
 
        protected override void Render(HtmlTextWriter output)
        {
 
            EnsureChildControls();
            if (ControlMode == SPControlMode.Display)
            {
                if (_values != null)
                    _values.RenderControl(output);
            }
            else
            {
                if (_editor != null)
                    _editor.RenderControl(output);
            }
        }
 
        public virtual string Text
        {
            get
            {
                this.EnsureChildControls();
                if (this._editor == null)
                {
                    return null;
                }
                return this._editor.Text;
            }
 
            set
            {
                this.EnsureChildControls();
                if (this._editor != null)
                {
                    this._editor.Text = value;
                }
            }
        }
 
        public override object Value
        {
            get
            { return this.Text; }
            set
            {
                if (base.Field != null)
                {
                    this.Text = base.Field.GetFieldValueForEdit(value);
                    base.Value = (string)value;
                    base.UpdateFieldValueInItem();
                }
            }
        }
    }

Lets take a look at what this class is doing:

  • OnInit() - come on, do I have to explain?
  • CreateChildControls() - initialize your controls and add to the Controls collection
  • Render() - writes the controls to the HtmlTextWriter
  • Text - This sets/gets the value in the controls
  • Value - this sets the value in the Text property and notice the base.UpdateFieldValueInItem(); statement...this oushes the value from Value to ItemFieldValue and allows you to access this value in display mode because Value returns null (which i did not find the documentation on M$ thank you very much).

So that leaves the last piece of the pie for my simple implementation the fldtypes file:

&lt;FieldTypes&gt;
&lt;FieldType&gt;
&lt;Field Name="TypeName"&gt;XmlFieldType&lt;/Field&gt;
&lt;Field Name="ParentType"&gt;&lt;/Field&gt;
&lt;Field Name="InternalType"&gt;Note&lt;/Field&gt;
&lt;Field Name="SQLType"&gt;ntext&lt;/Field&gt;
&lt;Field Name="TypeDisplayName"&gt;Xml Field&lt;/Field&gt;
&lt;Field Name="TypeShortDescription"&gt;Xml controls&lt;/Field&gt;
&lt;Field Name="UserCreatable"&gt;TRUE&lt;/Field&gt;
&lt;Field Name="ShowOnListCreate"&gt;TRUE&lt;/Field&gt;
&lt;Field Name="Sortable"&gt;FALSE&lt;/Field&gt;
&lt;Field Name="AllowBaseTypeRendering"&gt;FALSE&lt;/Field&gt;
&lt;Field Name="Filterable"&gt;FALSE&lt;/Field&gt;
&lt;Field Name="FieldTypeClass"&gt;Website.CustomFields.XmlFieldType, Website.CustomFields, Version=1.0.0.0, Culture=neutral, PublicKeyToken=346fcdd567259ee6&lt;/Field&gt;
&lt;RenderPattern Name="HeaderPattern"&gt;
&lt;Property Select="DisplayName" HTMLEncode="TRUE"/&gt;
&lt;/RenderPattern&gt;
&lt;RenderPattern Name="DisplayPattern"&gt;
&lt;Column/&gt;
&lt;/RenderPattern&gt;
&lt;/FieldType&gt;
&lt;/FieldTypes&gt;

So there you have it.  All I need to do in order to inherit from this is to remove the rendering (which i dont need anyway  as this is going to be a base type) and it should be good to go.  Those three pieces of code can be installed into your SharePoint environment and should help you get started to understanding custom field types.

Don't forget to add the SafeControl entry, Adjust your trust level and move the .dll into your bin folder as well.

Download the code here

Resources I found useful:

  • I did work through the example in Andrew Connell's book (Professional SP 2007 WCM development) and that worked fine and he actually does a great job of explaining most of whats going on here.
  • MSDN...where else
  • Charlie Holland has a pretty good article series on this stuff but unfortunately I couldn't get it working.  I also wanted a simple bare bones implementation.
Sometimes when I am working with SharePoint I really feel like I got it.  You now that feeling you get when you know exactly what you are doing and have no problems implementing it...then there are times when I really just want to smash something.  And it really doesn't matter what...it could be anything!  This is the feeling I got in the last couple of days working with custom field types in SharePoint.  It seems there are lots of blogs and articles out there talking about how to do it, but from what I could see (and to be fair I did not read them all so if you know of some good posts that would be great) it felt like most of the time I was only getting half the story.  I just finished putting together a very basic Custom Field Type that will display a multiline textbox in edit/new mode and simply display the value in a literal control in display mode.  In the grand scheme of things I am building a base XML Field Type to use for a series of additional Custom field types so essentially I want to store a string (yes I could use the XmlDocument)...but alas thats a story for another day.

So a bit of a primer, or rehash so I don't forget, when developing custom field types there are many pieces to it....not all of them required.  Here is a lit of the items and what they do:

* Field Type class - this class acts as the controller and hooks the rendering control, field type xml definition and the value class together.  It also provides validation at the field level via the GetValidatedString() method of the SPField object
* Field Control class - this is the rendering engine and gives you the power to display your control in any manner you wish as well as perform validation on the data being saved via the UI.
* Field Value class - allows for custom logic to be put around mutiple column fields and different data structures that will be storing data for your field type.
* .ascx file in CONTROLTEMPALTES directory - this supplies rendering markup via a usercontrol and hooks into the field control class
* fldtypes_* - this file that gets installed into the 12/TEMPLATES/XML directory and contrains the information that SharePoint requires in order to load your field type into the system.  Such as the assembly to use, the parent type and other information.  This is required if the type is going to be applied to content types and become a field on a list.

So for my requirements I only needed the field type, the field control and the fldtypes_xxx.xml file.  Lets look at the field type class I built

public class XmlFieldType : SPField
{
public XmlFieldType(SPFieldCollection fields, string fieldName) : base(fields, fieldName) { }
public XmlFieldType(SPFieldCollection fields, string fieldName, string displayName) : base(fields, fieldName, displayName) { }
 
public override BaseFieldControl FieldRenderingControl
{
get
{
BaseFieldControl fldControl = new XmlFieldControl();
fldControl.FieldName = InternalName;
return fldControl;
}
}
 
public override object GetFieldValue(string value)
{
if (string.IsNullOrEmpty(value))
return null;
return value;
}
 
public override Type FieldValueType
{
get { return typeof(string); }
}
 
public override string DefaultValue
{
get
{
XmlDocument doc = new XmlDocument();
doc.LoadXml(this.SchemaXml);
XmlNode nodeInFieldSchema = doc.SelectSingleNode("Field/Default");
if (nodeInFieldSchema != null)
return nodeInFieldSchema.InnerXml;
return null;
}
set { base.DefaultValue = value; }
}
 
public override string GetValidatedString(object value)
{
base.GetValidatedString(value);
if (value == null)
{
if (this.Required) throw new SPFieldValidationException("Invalid value for required field.");
return string.Empty;
}
else
{
return value.ToString();
}
}
}

Lets review

* The two constructors are required
* FieldRenderingControl() method tells the field type which control to use
* GetFieldValue() method returns the value of the field....if we were using a custom type you would cast that to the appropriate type here
* FieldValueType() - get the type of the Value class
* DefautValue() - this gets the default value from the field if one is defined
* GetValidatedString() - perform field level validation

The Field Control Class is fairly simple as well:

public class XmlFieldControl : BaseFieldControl
{
protected Literal _values;
protected TextBox _editor;
 
protected override void OnInit(EventArgs e)
{
base.OnInit(e);
EnsureChildControls();
}
 
protected override void CreateChildControls()
{
 
if (this.Field == null || this.ControlMode == SPControlMode.Invalid)
return;
 
Controls.Clear();
base.CreateChildControls();
_editor = new TextBox();
_editor.TextMode = TextBoxMode.MultiLine;
_editor.Height = new Unit(300);
_editor.Width = new Unit(500);
Controls.Add(_editor);
 
if (ControlMode == SPControlMode.Display)
{
_values = new Literal();
_values.Text = Convert.ToString(ItemFieldValue);
Controls.Add(_values);
}
}
 
protected override void Render(HtmlTextWriter output)
{
 
EnsureChildControls();
if (ControlMode == SPControlMode.Display)
{
if (_values != null)
_values.RenderControl(output);
}
else
{
if (_editor != null)
_editor.RenderControl(output);
}
}
 
public virtual string Text
{
get
{
this.EnsureChildControls();
if (this._editor == null)
{
return null;
}
return this._editor.Text;
}
 
set
{
this.EnsureChildControls();
if (this._editor != null)
{
this._editor.Text = value;
}
}
}
 
public override object Value
{
get
{ return this.Text; }
set
{
if (base.Field != null)
{
this.Text = base.Field.GetFieldValueForEdit(value);
base.Value = (string)value;
base.UpdateFieldValueInItem();
}
}
}
}

sdfsdf

    XmlFieldType
 
    Note
    ntext
    Xml Field
    Xml controls
    TRUE
    TRUE
    FALSE
    FALSE
    FALSE
    Website.CustomFields.XmlFieldType, Website.CustomFields, Version=1.0.0.0, Culture=neutral, PublicKeyToken=346fcdd567259ee6

I did work through the example in Andrew Connell's book (Professional SP 2007 WCM development) and that worked fine and he actually does a great job of explaining most of whats going on here.

http://msdn.microsoft.com/en-us/library/ms446361.aspx

Technorati Tags: , , , ,

Its seems that SharePoint has a knack for surprising me with seriously strange errors sometimes. Usually at the core of the error there is a sound explanation as to why this is happening but nonetheless I am not pleased with the obscurity of them sometimes. Case in point, while working on a Console application that would load FBA (Forms Based Authentication) users into a sharepoint sie collection and then create a site for each one (granting permissions and so on) I came across a very strange error - SPException: SharePoint cannot find the user.

This kind of surprised me at first and I was wondering if somehow my CustomMembershipProvider setup stopped working on my portal site, but that was fine. So after hammering away at it for a while I came across a great article written by Waldek Mastykarz on this exact problem.  After reading through his investigation it makes sense why it doesn't work in a console application but it works under the context of a SharePoint website. Essentially the web application has access to a context object and this has access to the providers node in your web.config file,  BUT the console application does not have this information available.  So when the SharePoint assemblies attempt to access this information they cannot because it does not exist.

The way around this is to create an HttpContext in your application before attempting to run SPWeb.EnsureUser("blah") like so:

if (HttpContext.Current == null) { HttpRequest request = new HttpRequest("", web.Url, ""); HttpContext.Current = new HttpContext(request, new HttpResponse(new StringWriter())); HttpContext.Current.Items["HttpHandlerSPWeb"] = web; }

Then add the system.web/membership/providers node to your app.config file (which you may have to create in the project)..  Mine looks like so:

<system.web> <membership> <providers> <add name="CustomSqlProvider" applicationName="/Portal" connectionStringName="sqlData" type="CustomProviders.CustomSqlMembershipProvider, CustomProviders, Version=1.0.0.0, Culture=neutral, PublicKeyToken=91a4fcd60b73a0e8" /> </providers> </membership> </system.web> <connectionStrings> <add name="sqlData" connectionString="Data Source=sqlpd; Initial Catalog=PUsers; Integrated Security=True; MultipleActiveResultSets=True " providerName="System.Data.SqlClient" /> </connectionStrings>

After adding this information and running a few tests it started to work. In fact it worked really well on my dev box...the only problem was it was a little intermittent on my production machine. Which is funny because the provider on the site itself works just fine all the time but in order to get my console application working (the EnsureUser() portion) the site would require an IIS reset. This is the one MAJOR stumbling block that I have yet to overcome...the only saving grace I have is that I can import the users manually into the system first using the UI and then run my console application that will load the sites and grant permissions to sites based on an external configuration file.

Many thanks to Waldek Mastykarz for all his help on this one so far...I know I will be coming back to this one in the near future but my head hurts a little and I need a beer.

Canadian SharePint event anyone?

Technorati Tags: , , , ,

Inside the Microsoft.SharePoint namespace there is the SPBasePermissions enumeration. It specifies the built-in permissions available in Windows SharePoint Services / MOSS 2007.  This was taken from the MSDN site, but I am posting it here because sometimes they move content around and I can't find it...ha ha you can't fool me Microsoft!!!

Using the enumerations below you can wrap some markup on your page in an SPSecurityTrimmedControl like so:

<Sharepoint:SPSecurityTrimmedControl runat="server" PermissionsString="CreateGroups">

and only allow users with the defined permission to see the contents of the security trimming control.

Member name Description
AddAndCustomizePages Add, change, or delete HTML pages or Web Part Pages, and edit the Web site using a Windows SharePoint Services–compatible editor.
AddDelPrivateWebParts Add or remove personal Web Parts on a Web Part Page.
AddListItems Add items to lists, add documents to document libraries, and add Web discussion comments.
ApplyStyleSheets Apply a style sheet (.css file) to the Web site.
ApplyThemeAndBorder Apply a theme or borders to the entire Web site.
ApproveItems Approve a minor version of a list item or document.
BrowseDirectories Enumerate files and folders in a Web site using Microsoft Office SharePoint Designer 2007 and WebDAV interfaces.
BrowseUserInfo View information about users of the Web site.
CancelCheckout Discard or check in a document which is checked out to another user.
CreateAlerts Create e-mail alerts.
CreateGroups Create a group of users that can be used anywhere within the site collection.
CreateSSCSite Create a Web site using Self-Service Site Creation.
DeleteListItems Delete items from a list, documents from a document library, and Web discussion comments in documents.
DeleteVersions Delete past versions of a list item or document.
EditListItems Edit items in lists, edit documents in document libraries, edit Web discussion comments in documents, and customize Web Part Pages in document libraries.
EditMyUserInfo Allows a user to change his or her user information, such as adding a picture.
EmptyMask Has no permissions on the Web site. Not available through the user interface.
EnumeratePermissions Enumerate permissions on the Web site, list, folder, document, or list item.
FullMask Has all permissions on the Web site. Not available through the user interface.
ManageAlerts Manage alerts for all users of the Web site.
ManageLists Create and delete lists, add or remove columns in a list, and add or remove public views of a list.
ManagePermissions Create and change permission levels on the Web site and assign permissions to users and groups.
ManagePersonalViews Create, change, and delete personal views of lists.
ManageSubwebs Create subsites such as team sites, Meeting Workspace sites, and Document Workspace sites.
ManageWeb Grant the ability to perform all administration tasks for the Web site as well as manage content. Activate, deactivate, or edit properties of Web site scoped Features through the object model or through the user interface (UI). When granted on the root Web site of a site collection, activate, deactivate, or edit properties of site collection scoped Features through the object model. To browse to the Site Collection Features page and activate or deactivate site collection scoped Features through the UI, you must be a site collection administrator.
Open Allow users to open a Web site, list, or folder to access items inside that container.
OpenItems View the source of documents with server-side file handlers.
UpdatePersonalWebParts Update Web Parts to display personalized information.
UseClientIntegration Use features that launch client applications; otherwise, users must work on documents locally and upload changes.
UseRemoteAPIs Use SOAP, WebDAV, or Microsoft Office SharePoint Designer 2007 interfaces to access the Web site.
ViewFormPages View forms, views, and application pages, and enumerate lists.
ViewListItems View items in lists, documents in document libraries, and view Web discussion comments.
ViewPages View pages in a Web site.
ViewUsageData View reports on Web site usage.
ViewVersions View past versions of a list item or document.

Technorati Tags: , , ,

I got the following error the other day (it has been shortened...):

"the web part you attempted to add no longer exists in the closed web parts gallery."

This was a pretty disturbing error...there was no real apparent cause for this problem...nothing in the logs. After messing about with it for a while I figured out that it was a dll version in the GAC that was causing the problem. On my dev box I had an updated version but the version in our prod envs is different.

It would be nice if the server was a little more helpful with its error messages....HTH if you come across it

Technorati Tags: , , , ,