SharePoint: Check-Out vs Lock

I had been asked to look at a SharePoint event receiver that wasn’t behaving as it should. After a document had been checked in, it would set a property and update the item. However, we were getting an error:

SPException: The file “[File Name]” is locked for exclusive use by [User]

This was unfortunate – the user was the user who’d just been making changes, and the code was running after the document had been checked in – so what gives? Well, it turns out that the message is right – the file is locked, not checked out, and a lock is not the same as a check-out.
Continue reading “SharePoint: Check-Out vs Lock”

SharePoint: Check-Out vs Lock

Getting levels of the SharePoint Heirarchy and their Exceptions

Something that I have to do time and again is get some element of SharePoint’s heirarchy, such as a site collection, site, list or item. This is pretty typical – that’s why we all use USING to ensure proper disposal of SPSites and SPWebs, right? But what happens if the thing you’re after isn’t there? What exception get’s thrown? Well, this should be pretty clear:

try
{
    //FileNotFoundException if doesn't exist
    using (SPSite site = new SPSite(siteGuid))
    {
        //FileNotFoundException if doesn't exist
        using (SPWeb web = site.OpenWeb(webGuid))
        {
            //SPException if doesn't exist
            SPList list = web.Lists[listGuid];

            //ArgumentException if doesn't exist
            SPListItem item = list.GetItemByUniqueId(itemGuid);
        }
    }
}
catch (System.IO.FileNotFoundException fileEx2)
{
    // Site or Site Collection Not Found
}
catch (SPException spEx2)
{
    // List not found
}
catch (ArgumentException argEx2)
{
    // Item not found
}

Hopefully that might prove useful to someone – and a good reminder for me.

Getting levels of the SharePoint Heirarchy and their Exceptions

Rendering List Fields from other sites

I had a requirement recently to display the fields of a SharePoint item in another SharePoint site. Now, you can do this with things like the Content Query Web Part, or Data View Web Part, but I was doing a few other things, and specifically, I needed to pull the fields to display from a particular View on the list.

This turned out to be quite an interesting problem. All fields use a subclass of BaseFieldControl, and this is what renders the field – so it appeared to be fairly straight forward. As always, though, there was a little kink to it – you need an SPContext for the site the item comes from, and you need to use this as the contexts for the SPField‘s rendering control:

SPContext ctx = SPContext.GetContext(HttpContext.Current, item.ID, relatedList.ID, relatedWeb);

SPView relatedView = list.DefaultView;

foreach (string vf in relatedView.ViewFields)
{
    SPField fld = relatedList.Fields.GetFieldByInternalName(vf);

    HtmlGenericControl titleLabel = new HtmlGenericControl("H3");
    titleLabel.InnerText = fld.Title;
    this.Controls.Add( titleLabel );

    BaseFieldControl ctl = fld.FieldRenderingControl;
    ctl.ControlMode = SPControlMode.Display;
    ctl.ListId = relatedList.ID;
    ctl.ItemId = item.ID;
    ctl.RenderContext = ctx;
    ctl.ItemContext = ctx;
    ctl.FieldName = fld.Title;
    ctl.ID = Guid.NewGuid().ToString();

    this.Controls.Add( ctl );
}

Groovy!

Rendering List Fields from other sites

Bloody Wikis in SharePoint 2007

The other day I blogged about how weird ‘Blog Posts’ are. Well, I’ve also been looking at Wiki pages…

So, first off, as a reminder to myself, Wiki libraries are defined in the ‘WebPageLibrary’ feature. Took a while to track that down.

Second off, calling the SPListItem.Title for a Wiki pages causes an ArgumentException. (Waldek Mastykarz has written about this). Kind of makes sense – the wiki item doesn’t have a title – but I’d prefer it returned the filename (without extension) instead. That would seem a more useful compromise.

Bloody Wikis in SharePoint 2007

Weird ContentType of Blog Posts

Okay, this is weird.

I’m trying to do something with various types of item, including Blog Posts, in SharePoint. Naturally, I’m getting the SPListItem for them, and then the SPListItem.ContentType, so I can check what kind of item is it. The weird thing is, if I try to get a Blog Post, the SPListItem.ContentType is NULL. Continue reading “Weird ContentType of Blog Posts”

Weird ContentType of Blog Posts

Programmatically create documents in Libraries

One thing that it can be useful to do sometimes is create documents in a library, possibly with some metadata. I find that I sometimes end up doing this from a console app, just to put in some example information:

string filePath = ...
string newName = ...
SPList library = ...
using (FileStream fs = new FileStream(filePath,FileMode.Open)){
SPFile file = library.RootFolder.Files.Add( newName ,fs, true );
SPListItem item = file.Item;
item["SomeField"] = "SomeValue";
item.Update();
}

Programmatically create documents in Libraries

Be selective about how you get items from an SPList

Just read an interesting article from Waldek Mastykarz called ‘Performance of various methods to retrieve one list item’. It’s well worth a look – go and read it.

So, the interesting thing I took away from it was just how slow the GetItemById() method was compared to an SPQuery. Why? Wouldn’t it make sense to use and SPQuery within the GetItemById() method?

Well a bit of Reflector digging (again) shows that it does! But it isn’t just a query for the item with that Id – it also specifies that the

SPQuery.ViewAttributes = "Scope="RecursiveAll" ModerationType="Moderator" ";

Hmm. So it’s probably a more complicated query. Depending on your solution, you might not need “RecursiveAll” – I try to avoid folders in lists, preferring views to break down my content.

So, the lesson that I took away was that if you are doing a LOT of getting items from lists, it is worth considering how you want to. There isn’t a right answer, unfortunately, and testing is key. The problem is, there are many factors:

  • Can you use caching?
  • Do you know the list you’re getting items from?
  • Are you getting items from more than one list?
  • Do you have folders?
  • What other parameters might your query have?

It’s difficult to know, hence I think Waldek is right – give it a test so you have some idea!

Be selective about how you get items from an SPList

Interesting Idea for Efficiency – Avoid SPList.Items…

An interesting post by Rob Garrett about avoiding using SPList.Items.Add() – as referencing SPList.Items causes you to get all items in a list, and that can be pretty slow. He does suggest a solution.

I must confess, I’m surprised. I mean, what he describes makes sense – and also explains why have both SPList.ItemCount and SPList.Items.Count (same problem – and the former should be faster) – but surely there is some equivalent already build, some SPList.AddItem() to do it for you? Guess not.

Might be a small optimisation, but it starts to become clearer why the 2000 item recommendation…

At some point, I’ll try and generate some metrics, and then we’ll see when it becomes more efficient and how much so.

Interesting Idea for Efficiency – Avoid SPList.Items…

WSS Practice: Checking in/out Documents, and Versioning

Well, for the WSS application developer exam, you’re supposed to know about programmatically checking in and out documents:

//*** Check out a document
Console.WriteLine("Check out {0}", myItem["Name"]);
myItem.File.CheckOut();
Console.ReadLine();
//*** Check in a Document (Minor Check in)
myItem.File.CheckIn("Checked in Programmatically", SPCheckinType.MinorCheckIn );
Console.WriteLine("Item Checked in");
Console.ReadLine();

One should also be able to list all versions of a document:

//*** List all versions of a document
Console.WriteLine(myItem.Name);
foreach (SPFileVersion ver in myItem.File.Versions)
{
Console.WriteLine(" - v{0} ({1})", ver.VersionLabel, ver.CheckInComment);
}
Console.ReadLine();

And restore a version:

//*** Restore to version 1.0
myItem.File.CheckOut();
myItem.File.Versions.RestoreByLabel("1.0");
myItem.File.CheckIn("Restored by Program to v1.0");
Console.WriteLine("{0} restored to v1.0", myItem.Name);

All pretty straight forward.

WSS Practice: Checking in/out Documents, and Versioning