I occasionally have to use the SharePoint .Net Client-Side Object Model (CSOM) API to reach into SharePoint and poke around a little bit. It’s all pretty straightforward, but something that I have not found to be straightforward is reliably determining which version of a file is the latest major/published version.
In this context, I’m usually working with a SharePoint Document Library where versioning is enabled with Major and Minor versions. The application is also using a user with administrator access to the site, which means it can view all versions of a document, including minor versions which would not normally be visible to the average end user. Lastly, I’m checking the properties of a
ListItem, which may be part of a Document Library (
ListItemCollection) through which I’m iterating, or which may have been loaded individually by some property (name, Id, URL, etc.)
Checking Latest Version Is Easy
If the latest version of a file happens to be a published major version, it’s easy:
ListItem.File.Level will be
FileLevel.Published. So always start by checking that property of an item. If it’s something other than
Published, then you have to dig through the older versions to find the latest major/published version (if one exists).
Checking Older Versions Gets Tricky
To see if an older version of the file is the latest major version, you can iterate through either
ListItem.Versions (collection of
Item.File.Versions (collection of
FileVersion). It’s important to note that
Item.Versions includes all versions, including the current version, while
Item.File.Versions includes all file versions except the current version, which is already accessible through
But what properties should you check?
The IsCurrentVersion Fallacy
Most online resources indicate that you can simply check an older version of an item/file to see if
FileVersion.IsCurrentVersion == True or
ListItemVersion.IsCurrentVersion == True, and if so, this is your latest published major version. This is not the case! I have found that
IsCurrentVersion can be
True on more than one minor version of a document.
Before I explain that, I should point out that the current version of a document always has
IsCurrentVersion==True, even if it’s a minor version. This is especially important to keep in mind when you choose to iterate through the versions in
Item.Versions, because the latest version (which I assume is not major/published, otherwise you wouldn’t be iterating through the versions) will have
IsCurrentVersion==True even though it’s not published. If iterating through
Item.File.Versions, this point is moot because the latest version is not included in that collection.
So, other than it being true on the latest version of a file (expected), and being true on the latest Major version of a file (expected), when else can it be true?
CrazyTalk: When a document is checked out, IsCurrentVersion == True on the second-latest version of the file.
Now we have THREE possible versions in an item’s version history where
IsCurrentVersion can be true:
- Latest version (minor or major) always has
- Latest major version has
- 2nd latest version has IsCurrentVersion==True ← (WHAT?)
Even if that second-latest version of the file is minor, or a rejected draft, etc., it will always have
IsCurrentVersion==True. And there may be more scenarios where that property is unexpectedly true. As a result, I’ve given up on using it to help me find the latest major/published version of a document.
So What’s The Solution Already?
I’ve switched to using the
VersionId property, which is an integer that can tell you a lot about the version you’re dealing with. When you’re looking at a
ListItem.Versions), the property is
VersionId. And when you’re looking at a
ListItem.File.Versions), the property is
VersionId uses multiples of 512 for every major version and multiples of 1 for every minor version. The first minor version of a new document will have a
VersionId of 1. Adding two more minor versions will bring the
VersionId up to 3. Publishing the first major version will bring the
VersionId up to 512, and adding one more minor version will bring it up to 513. The second major version will be 1024, and the next minor version will be 10125, and so on. This means there can be 511 minor versions of an item between every major version. The item with the highest
VersionId that is > 0 and a multiple of 512 is the latest major/published version.
Alternatively, instead of the properties
FileVersion.Id, you could also look at the properties
FileVersion.VersionLabel. These are decimal values formatted as <Major>.<Minor>, e.g. 3.12 (Major=3, Minor=12). If the Major version > 0 and the Minor version is 0, it is a major/published version of the file. Finding the highest non-0 Major version where the Minor version is 0 gives you the latest major (published) version of the file.
ListItem.Versions returns versions in descending order, starting with the latest version, I prefer to use this (over
ListItem.File.Versions). Check if each item’s
VersionId is > 0 and a multiple of 512 (or
VersionLabel has non-0 Major version with 0 Minor version), and the first one you find matching that criteria is the latest major/published version. You can ignore the first result if you’ve already checked if
FileLevel.Published, because you already know the latest version is not major/published. Alternatively, you could use
ListItem.File.Versions, but because it returns versions in ascending order, it’s a little less performant; you would have to iterate through all versions to know which is the highest.