Steve Jobs, SharePoint, Quality, and Plywood


With all the Steve Jobs news going around these days (resigning as Apple CEO), one invariably comes across many of his famously enduring quotes.

Yes I know this is a SharePoint blog and Steve Jobs probably hates SharePoint, but one cannot deny that his vision and work ethic is amazing, and his ability to facilitate the building of great products is absolutely inspiring. Steve’s focus on quality is something that every person should strive for when creating software, or anything really.

This quote of his is something that really resonates with me:

"When you’re a carpenter making a beautiful chest of drawers, you’re not going to use a piece of plywood on the back, even though it faces the wall and nobody will ever see it. You’ll know it’s there, so you’re going to use a beautiful piece of wood on the back. For you to sleep well at night, the aesthetic, the quality, has to be carried all the way through.”

Are you applying this principle to your SharePoint implementations?

Are you content guilty?


With most SharePoint migration projects, content is often copied/pasted from the original system into the new one as-is.

Maybe some categorizing, tagging and styling is applied to freshen up the content a little and make it comfortable in its new home.

But how often do you help your customers define a sustainable strategy for creating content? Yes, you train them on how to add and edit pages, use content editor web parts and rich text editors, but that’s not enough.

If the entire point of implementing SharePoint is to provide a platform for individuals to create and collaborate, then above all we owe it to our customers to help them define a proper content strategy.

Because content is, as always, the real champion. The particular system that delivers that content – the flavor of the year – is irrelevant.

SharePoint Nuggets – July 2011


As you can tell life has been a bit crazy.  I missed my own Nuggets deadline at the end of July as I was moving into a new house (not a base excuse me thinks).  Anyway, without further ado, here you go:

How to use SharePoint’s SPUtility class to format file size for display


UPDATE: I just came across a post that I blogged in 2008, which offers a different method of displaying file size.

SPUtility is a wonderful class.

The other day I needed to display the file size of a document in SharePoint via C#. I had a hunch that SPUtility would be the man for the job, so after some reflector madness and Visual Studio intellisensing, I located SPUtility.FormatSize.

My search would have been made easier if Microsoft had provided a method summary on FormatSize() (wtf?), but a quick test of this bad boy revealed the perfect solution for my requirement, which was to convert a long value representing the file size in bytes, into a user friendly file size display (e.g. 430 KB).

The long value was retrieved from the FileSizeDisplay field of my SPListItem, and converted into a user friendly file size display with the following code:

if (listItem.Fields.ContainsField("FileSizeDisplay") && listItem["FileSizeDisplay"].ToString().Length > 0)
    fileSizeDisplay = SPUtility.FormatSize(Convert.ToInt32(listItem["FileSizeDisplay"]));

Be sure to check out some of the other cool things you can do with the SPUtility class, like redirecting users to SharePoint’s built-in error page, or sending emails from SharePoint programmatically.

Happy coding!

All about SPAuditEventType.SecRoleBindUpdate: Part II


In my previous post I wrote about some of the stuff I’ve learned about SPAuditEventType.SecRoleBindUpdate so far. Since then I’ve gained a few more tidbits of info, so I thought I’d share them with you.

I’ve discovered that the following line I provided last time will sometimes throw an SPException:

SPUser eventUser = web.SiteUsers.GetByID(principalId);

This seems to occur when the audit operation happened on a group and not a user, which means the principalId is the ID of an SPGroup in the web.

To handle that problem in your code, simply put a try/catch around the above line and call the following code if it fails:

SPGroup eventGroup = web.Groups.GetByID(principalId);

NOTE: I haven’t yet figured out if the principalId could be something other than a user or a group, but I’ll pass on the info if I find out anything else.

I also learned a bit more about the roleId and how it relates to the principalId…

From what I can tell, the following rules apply:

  • If the operation is “ensure added“, and the principalId is a group, then then roleId will indicate the permissions that were given to the group.
  • If the operation is “ensure added“, and the principalId is a user, then then roleId will indicate the permissions that were given to the user.
  • If the operation is “ensure removed“, and the principalId is a group, then then roleId will indicate the permissions that were removed from the group.

But, strangely…

  • If the operation is “ensure removed“, and the principalId is a user, then then roleId will be -1.

That last rule doesn’t make sense. I’m not sure if it’s just something on my local environment (this was tested on SharePoint Foundation) which is causing the roleId to be -1 if permissions were removed from a user. All I know is that it makes it a little trickier when writing code to display this audit stuff on a page, because you won’t be able to display the permissions removed from a user, but you can display the permissions for every other operation.

Well, that’s all the new info I’ve gained about SPAuditEventType.SecRoleBindUpdate. Who would have thought so much could be said about this little gem?

PS: This is some of the stuff I learned while working on my document auditing add-on for SharePoint 2010. DM me on twitter (@lawrencecawood) if you’d like more details. It will be for sale via Vinewave.

All about SPAuditEventType.SecRoleBindUpdate: Part I


UPDATE (15 Aug 2011): There’s a Part II to this post which you can read here.

If you have an SPAuditEntry object and its Event property is set to SPAuditEventType.SecRoleBindUpdate, this means that the “permissions of a user or group for the audited object are changed” – basically, someone was given permissions to the the audited item, or their permissions were removed.

When the SPAuditEventType is SecRoleBindUpdate, the SPAuditEntry object’s EventData property will contain the following XML structure:

<roleid>1073741829</roleid>
<principalid>7</principalid>
<scope>BEFA8A05-F97A-46C4-80A3-FBC1350C8247</scope>
<operation>ensure added</operation>

To read this data (in .NET) you would preferably load it into an XMLDocument, but first you need to append your own root node around this XML or your XMLDocument’s LoadXml() method will fail. Something like this should do the trick:

XmlDocument xmlEventData = new XmlDocument();
xmlEventData.LoadXml("<EventData>" + entry.EventData + "</EventData>");

*entry is the SPAuditEntry object

Now that you have an XmlDocument, you can get the user whose permissions were affected:

int principalId = Convert.ToInt32(xmlEventData.DocumentElement.SelectSingleNode("/EventData/principalid").InnerText);  SPUser eventUser = web.SiteUsers.GetByID(principalId);

*web is obviously the SPWeb object that contains the item that was audited

To get the role that the user was given permissions to, try this:

int roleId = Convert.ToInt32(xmlEventData.DocumentElement.SelectSingleNode("/EventData/roleid").InnerText);
SPRoleDefinition eventRole = web.RoleDefinitions.GetById(roleId);

Note that roleId can be -1, which seems to be the case if a user’s permissions were removed. You can check if permissions were granted or removed by checking the <operation> node:

string operation = xmlEventData.DocumentElement.SelectSingleNode("/EventData/operation").InnerText;

I’ve only seen it contain the following two values, although there could be other values that SharePoint writes into this node (let me know if you know of any):

<operation>ensure added</operation>
<operation>ensure removed</operation>

Some Substring jiggery pokery should allow you to check if permissions were added or removed.

You can write out the audit entry to the page like this:

Response.Write((eventUser.Name.Length > 0 ? eventUser.Name : eventUser.LoginName) + " was granted " + eventRole.Name + " permissions");

How To Add a CustomAction to the EditControlBlock of ALL list types


You may be familiar with the typical settings for the RegistrationType and RegistrationId attributes of a CustomAction when inserting items into the dropdown menu or ‘context menu’ (EditControlBlock) that appears when you click the little down arrow next to a list item:

RegistrationType=List
RegistrationId=101

The RegistrationId of 101 indicates that the item will be inserted into the context menu of all Document Libraries. 102 indicates survey lists, 103 is links lists, 104 is announcement lists etc. (see a full list of RegistrationId’s here)

But what if you want to insert an item into the EditControlBlock of all types at once?

You could create a separate CustomAction for each RegistrationId, or you could do it the easy way:

RegistrationType=ContentType
RegistrationId=0×01

This will insert your menu item into the dropdown of every type of list in the site collection, because your CustomAction was added to the root content type (item).

I’m not sure if there are any caveats or problems with using this approach, but it seems to work ok.

Should you embrace SharePoint’s full set of capabilities?


In The Executive Perspective: Top 7 Things You Must Consider for SharePoint 2010, Scott Jamison makes some excellent points on how to ensure that your SharePoint implementation doesn’t simply get used as a company file server:

“If you’re going to invest the time and effort to deploy SharePoint, along with the cost of servers and storage, then you owe it to yourself and your organization to invest in governance, a good information architecture and training.”

He goes on to make the standpoint that when implementing SharePoint in your organization, you should “Go All-In or Don’t Bother”:

“Don’t just deploy team sites. If you’re going to invest, deploy all six workloads (sites, content management, search, BI, social, composite applications). Customers who use SharePoint to its potential are much happier customers.”

My take on this is that while I agree that one should use the full breadth of SharePoint’s capabilities in order to maximize its potential, one should also remember the holy grail of SharePoint implementations (and software in general): keep it simple.

If you’re deploying SharePoint in an organization where people are not yet used to working collaboratively online, deploying a huge intranet solution up-front is only going to overwhelm the users (and the poor SharePoint admins).

Remember, these users have probably been working on documents locally and emailing them to one another for years, and a switch to a centralised system is a big enough jump to start with.

My suggestion would be to start small and simple; first train users on how to use team sites effectively, and only once they’re familiar with how SharePoint works and the whole concept of working collaboratively, start adding all those fancy features such as social and BI.

Is SharePoint Going Away? My Take


Recently Bamboo Nation released a thought provoking article titled – “SharePoint is going away.”  In this article the author argues that Microsoft is putting less emphasis on SharePoint therefore it must not have an extended road for it’s existence.

This opinion (which he is entitled too) has obviously caused quite a bit of stir amongst the industry and people that make their living off of this very product.  Veronique, from Let’s Collaborate, responded almost immediately with a post of her own.  She supports SharePoint to the max and has every right too.

As I wasn’t at WPC, my knee jerk reaction when I saw the blog title and synopsis was to faint, but as I read further I calmed down and realised that this was nothing more than a take on where the emphasis of the conference was.

The post was thought provoking and it made me consider a couple of things.

Microsoft Dynamics, consisting of a number of products that Microsoft bought and are slowly but surely redeveloping (not all), are big parts of Microsoft’s roadmap for the future.  Dynamics AX is Microsoft’s SAP compete and needless to say, they are milking R&D cash into it.  Also part of the Dynamics stable is MSCRM 2011, the latest darling with it’s solid compete for salesforce.com.

Now consider this.  CRM 2011 uses Workflow Foundation as the underlying workflow technology.  It’s also tightly integrates with SharePoint Foundation (or higher) for it’s document storage capability.  Furthermore, Dynamics AX, uses Workflow Foundation for it’s workflow.  Dynamics SL, uses SharePoint for it’s business portal capability. See a theme?

I thought so…

My take is this;  SharePoint will continue to change over the foreseeable future.  Rather than it going away, I see it becoming more and more entrenched into the server architecture of Windows Server 2008 and the like. 

SharePoint Foundation is a lovely development platform and I don’t see Microsoft ditching it’s only Content Management System (SharePoint For Internet Sites) which, (if you can remember) used to be a stand-alone product, MCMS 2002 and then integrated into SharePoint with the ‘07 release.

SharePoint, in some shape way or form, is here to stay so don’t be surprised if your Desktop in the Cloud is based on a operating system called SharePoint Foundation.  Winking smile