Nick Grattan’s SharePoint Blog

About Microsoft SharePoint and some .NET

Archive for the ‘SharePoint Object Model’ Category

Code for Creating New Documents based on a content type and template

without comments

This method “CreateDocument” will create a new document in a SharePoint document library using a content type. It will copy the document template associated with the content type into the new document:

// Creates document in given list (root folder).
// Returns true if the file was created, false if it already
// exists or throws exception for other failure
protected bool CreateDocument( string sFilename,
                string sContentType, string sList)
{
    try
    {
        SPSite site = SPContext.Current.Site;

        using (SPWeb web = site.OpenWeb())
        {
            SPList list = web.Lists[sList];
            // this always uses root folder
            SPFolder folder = web.Folders[sList];
            SPFileCollection fcol = folder.Files;

            // find the template url and open
            string sTemplate =
                list.ContentTypes[sContentType].DocumentTemplateUrl;
            SPFile spf = web.GetFile(sTemplate);
            byte[] binFile = spf.OpenBinary();
            // Url for file to be created
            string destFile = fcol.Folder.Url + “/” + sFilename;

            // create the document and get SPFile/SPItem for
            // new document
            SPFile addedFile = fcol.Add(destFile, binFile, false);
            SPItem newItem = addedFile.Item;
            newItem["ContentType"] = sContentType;
            newItem.Update();
            addedFile.Update();
            return true;
        }
    }
    catch (SPException spEx)
    {
        // file already exists?
        if (spEx.ErrorCode == -2130575257)
            return false;
        else
            throw spEx;
    }
}

This code:

  1. Gets a SPSite for the current site collection, and opens an SPWeb for the site.
  2. Gets a SPList for the given list, and then an SPFolder for the root folder in this list. This code always creates the document in the root folder, but the code can easily be changed to place the document in any folder in the document library.
  3. Gets a SPFileCollection for the documents in the folder.
  4. “DocumentTemplateUrl” is used to return the Url of document template associated with the given content type.
  5. Get an SPFile for the document template in spf and open it for binary access using OpenBinary
  6. Add a new document to the folder through the SPFileCollection referenced by fcol.
  7. Get an SPItem for the new document and set the “ContentType” column to ensure it uses the correct content type (it will default to the first content type in the document library).
  8. Update the item and the added file.
  9. The catch section checks for an -2130575257 error, which indicates the file already exists.

 

Written by Nick Grattan

December 8, 2008 at 10:23 pm

Trimming WebPart Output with SPSecurityTrimmedControl

with one comment

The SPSecurityTrimmedControl can be used in your SharePoint pages and web parts to conditionally display content based on permissions assigned to a user.

Here’s an example of using the control in a web part. The control is declared in Microsoft.SharePoint (in microsoft.sharepoint.dll). First, create an instance:

SPSecurityTrimmedControl stcEditItem= new SPSecurityTrimmedControl();
stcEditItem.Permissions = SPBasePermissions.EditListItems;

Next, specify the output to display only if the current user has the given permissions. In this case

  • Define a literal server control, add some content
  • Add the literal to the SPSecurityTrimmedControl
  • Add the SPSecurityTrimmedControl to the controls collection for the web part:

Literal litEditItem = new Literal();
litEditItem.Text = “My Content”;
stcEditItem.Controls.Add(litEditItem);
this.Controls.Add(stcEditItem);

Finally, you can explicitly render the SPSecurityTrimmedControl control in the web part’s “Render” method:

stcEditItem.RenderControl(writer);

The content “My Content” will only be displayed in the web part if the user has the “EditListItems” permission.

Also, you can programmatically test for permissions on various SharePoint objects, such as SPListItem, using the AllRolesForCurrentUser method:

SPListItem li;

if (!li.AllRolesForCurrentUser.Contains(web.RoleDefinitions["Approve"]))
{
    …

This web post from Richard Harbridge shows how to use the SPSecurityTrimmedControl in an ASPX page.

Written by Nick Grattan

November 13, 2008 at 1:05 pm

When an SPListItem won’t Update or Change

with 2 comments

Here’s a problem that recently bit me. This code executes a query that returns a single SPListItem and then attempts to change the approved status through the SPListItemCollection:

SPListItemCollection lic = list.GetItems(query);
lic[0].ModerationInformation.Status = SPModerationStatusType.Approved;
lic[0].Update();

Strangely enough, before calling the change to “Status” (second line) the status was “Pending” and *after* the call the status was still “Pending”!

However, assigning to a SPListItem and updating through this object changes the approved status as expected:

SPListItemCollection lic = list.GetItems(query);
SPListItem li = lic[0];
li.ModerationInformation.Status = SPModerationStatusType.Approved;
li.Update();

It seems the SharePoint object model cannot handle repeated calls through the item collection to the same list item object – perhaps it creates a new temporary object each time?

Written by Nick Grattan

November 12, 2008 at 8:27 pm

SharePoint 2007 Custom Fields and “Edit property on server”

with 4 comments

When developing custom fields in SharePoint 2007 you may encounter this warning when adding the field to a document library but not to a list:

“The field type cannot be edited from most client programs and might block the programs from saving documents to this library.”

Cf1

The warning is given because an ASPX control is used for editing the column/property values in SharePoint but this ASPX control cannot be used for editing column values in client applications such as Microsoft Word. When a document is created in Microsoft Word the column is shown with the “Edit property on server” error:

Cf2

To allow the column to be edited in client applications you need to specify a parent type for the field. This parent type is one of the standard field types that a client application can edit. You then specify that the parent type edit mechanism (such as a standard edit box or combo box) can be used by setting the AllowBaseTypeRendering property for the field.

To do this edit the fldtypes_*xml file for the custom field; add the AllowBaseTypeRendering Field element with the value “TRUE” and set the ParentType field element to a standard field type, such as “Number”:

<Field Name=TypeName>RatingField</Field>

<Field Name=ParentType>Number</Field>

<Field Name=SQLType>float</Field>

<Field Name=TypeDisplayName>Rating Field</Field>

<Field Name=TypeShortDescription>Rating Field</Field>

<Field Name=Sortable>TRUE</Field>

<Field Name=AllowBaseTypeRendering>TRUE</Field>

<Field Name=Filterable>TRUE</Field>

The field will now be editable in client applications like Microsoft Word.

Written by Nick Grattan

January 6, 2008 at 2:18 pm

Extract Public Key from Signed Assembly – Method 2

without comments

In this post I show how to extract the public key token from a signed assembly using the “sn” utility.

If the signed assembly is already installed in the GAC you can use the Windows Explorer to find the public key token:

  • Run Windows Explorer.
  • Navigate to the \Windows\assembly folder.

List of assemblies displayes the public key token and if you display the properties for an assembly you can mark and copy the key to the clipboard:

Pk

Written by Nick Grattan

December 17, 2007 at 2:42 pm

Document Libraries: SPList and SPFolder.Delete Differences

without comments

Removing items from a document library can be done in two different ways. Firstly, using SPList.Delete:

int iCount = spList.Items.Count;

for (int i = 0; i < iCount; i++)

{

    spList.Items[0].Delete();

}

This code will delete all the items/documents in all folders, but will leave the folders undeleted. Alternatively, you may write:

int iCount = spFolder.Files.Count;

for (int i = 0; i < iCount; i++)

{

    spFolder.Files[0].Delete();

}

This will delete the items/documents only in the folder represented by ‘spFolder’, and items/documents in other sub-folders will remain. The references to spList and spFolder can be obtained like this:

spList = currentWeb.Lists["MyDocumentLibrary"];

spFolder = currentWeb.Folders["MyDocumentLibrary"];

In this case, spFolder refers to the root folder in the document library.

 

 

 

 

 

 

 

 

Written by Nick Grattan

October 9, 2007 at 11:43 am

SPFolder / SPList: Deleting versus Recycling

without comments

The following code shows how to remove all documents from a folder:

int iCount = spFolder.Files.Count;

for (int i = 0; i < iCount; i++)

{

    spFolder.Files[0].Delete();

}

Deleting documents with this code will delete permanently without using the recycle bin. To move the document to the recycle bin use the following code:

spFolder.Files[0].Recycle();

The SPItem class has a Recycle method as well as a Delete method and can be used in a similar way.

Written by Nick Grattan

October 9, 2007 at 11:13 am

Introducing the SharePoint object model

with 17 comments

As an alternative to programming against the SharePoint web services you can use the SharePoint object model. The object model can be used when the application will run on the server where SharePoint is installed (such as a console or WinForm application) or in assemblies that are run within a site (such as a Web Part).  

This sample shows how to display the sites and sub sites within a site collection as a hierarchy in a tree view control within a WinForm application.

Treeview

First, you will need to create a reference to “SharePoint.dll” assembly in your Visual Studio 2005 project. This is located at:

C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\12\ISAPI\Microsoft.SharePoint.dll

A recursive function nicely solves the problem of loading the site hierachy into a tree view control. The method below is passed the tree node into which the site list will be loaded, and a SPWeb object representing the site whose sub-sites will be loaded:

       private void FillSubWeb(TreeNode tn, SPWeb webSite)

        {

            foreach (SPWeb theWeb in webSite.Webs)

            {

                TreeNode subTN = new TreeNode(theWeb.Name);

                tn.Nodes.Add(subTN);

                FillSubWeb(subTN, theWeb);

            }

        }

This method iterates over the “Webs” collection which returns each sub-site. A new TreeNode object is created with the site name. The node is added to the tree view  control. Lastly, the FillSubWeb method is called recursively, passing the TreeNode and theWeb object to load the sub-sites for the current site.

The following code kicks off the loading of the sites:

           

      SPSite site = new SPSite

           (“http://moss2007:8100/sites/intranet”);

      SPWeb rootWeb = site.AllWebs[0];

 

      TreeNode tn = new TreeNode

            (“http://moss2007:8100/sites/intranet”);

      tvSites.Nodes.Add(tn);

      FillSubWeb(tn, rootWeb);

The code gets a reference to the site collection from the URL, and then obtains a reference to the top-level web (site) for the site collection. A tree node is created and added to the tree view control to represent the site collection, and then the FillSubWeb method is called to start the recursive process.

 

Written by Nick Grattan

August 10, 2007 at 4:01 pm

Extracting Public Key from Signed Assembly

with 2 comments

Once an assembly has been signed you can extract the public key token using the ‘sn’ .NET utility. This is necessary if you need to create a reference to an assembly, for example in the form:

<Field  Name=”FieldTypeClass”> RatingField.RatingField,RatingField, Version=1.0.0.0,Culture=neutral, PublicKeyToken=ef9f3072afebf3b0 </Field>

To do this:

  1. Run a Visual Studio 2005 command prompt (Visual Studio Tool + Visual Studio 2005 Command Prompt from the “Start” menu).
  2. Enter the following command:

sn -Tp ratingfield.dll

Where “ratingfield.dll” is the name of the signed assembly.

Written by Nick Grattan

August 6, 2007 at 2:14 pm

Where have my versions gone?

without comments

Once enabled for a library or list, major and minor versions of documents and items can be kept; the number of which can be specified in the library or list settings:

Versions

The version history for items or documents can be viewed, and old versions can be opened and inspected. But where are these old versions stored?

Version histories are maintained for files and for property (column) values. In the case of a document library both a file and a property history is maintained, but for a list item only a property history is kept. The SharePoint class libraries or web services can be used to programmatically access this information, and also determine the URL where a pervious version of a document is located.

So, on a SharePoint server create a new Visual Studio project and add a reference to the “Microsoft.SharePoint.dll” library. Then add a using statement to “Microsoft.SharePoint.” Assuming you have already a reference to a SPList object representing the list or library you can obain a reference to the collection of previous file versions:

            SPFileVersionCollection theFileVersions = lstItem.File.Versions;

The collection can be iterated, and in this case, the version label and URL are added to a WinForm data grid view control:

            foreach (SPFileVersion liVer in theFileVersions)

            {

               int rowID = dgvVersions.Rows.Add();

               dgvVersions.Rows[rowID].Cells[0].Value = liVer.VersionLabel;

               dgvVersions.Rows[rowID].Cells[1].Value = liVer.Url;

            }

The output will look like the following:

Versions2

You can see from this that the previous versions are stored in a virtual folder called “_vti_history” under the site in which the library is located. The virtual folder “512” represents the version number (taking into account other versioned documents in the site). This URL together with the URL for the site can be used to directly open previous versions.

The SPFileVersion object can also be used to access the contents of the file. In this code, the bytes associated with the version are obtained and then saved to a file:

            byte[] outBytes = liVer.OpenBinary();

            using (BinaryWriter binWriter =

               new BinaryWriter(File.Open(@”C:\Temp\MyFile.xlsx”,

                    FileMode.Create)))

            {

               binWriter.Write(outBytes);

            }

This works well with documents, but the situation is much more complex with pages, content and web parts. Navigating to the URL for pages will result in an HTTP 404 – “file not found”.

Written by Nick Grattan

July 31, 2007 at 3:46 pm