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.

User Profile Synch SA – Bringing it back to life


I’ve probably blogged about this ten times, but I keep running into more and more interesting scenarios with this “admittedly” very complex service, the infamous User Profile Synchronisation.

In this scenario there was a mix-up with passwords and the accounts that were running the various services and management agents had changed / were locked or a combination of  both.

The symptom for the users were simple; Changes made in Active Directory were not being populated through to SharePoint.  This was causing havoc with the K2 business processes (dependant on reporting lines and departments) to name one element.

Upon initial investigation the user profile synchronisation service application seemed to have “stopped”.  Weird I know, but there is more.  When going into the “Manage” link within the service applications management page, the user profile synchronisation status read – “User Profile Synchronisation is being provisioned”.  This message never changed.  Under services on server, the user profile synchronisation service was also stuck on “Starting”.  Note:  Don’t confuse this starting with the ones documented in other deployment scenarios.

In order to resolve this mess, I completed the following steps:

- Manually re-enabled two services via the services console, namely “Forefront Identity Manager Service” and “Forefront Identity Manager Synchronization Service”

sychservices

- This was done, by also updated the “Log-On” element with the correct user credentials.  The services started.

- I then navigated to the Manage User Profile Service Application page and clicked on “Configure Synchronization Connections”.

- In this page, I updated the credentials of the user that is used to synchronise.  Failing to do this step will cause your event log to blow up like a Christmas tree as the synch service will execute but the actual agent traversing Active Directory will not be correct.  For more information on the actual agent running behind the show, have a look at the application ("miisclient”) in this directory:

“C:\Program Files\Microsoft Office Servers\14.0\Synchronization Service\UIShell”

- I then executed a incremental update and all was well again.

I’ve read up quite a bit on this service and when it works I am super amazed at the technicality of it all.  On a side note, I really wish that Microsoft at some point bring out a simple way to store pictures in once place and synchronise them across Exchange, Lynch and SharePoint.

How I solved the problem of DLL’s being removed during WSP uninstallation


I ran into a problem a few weeks ago that took quite a bit of work to sort out, so I thought I’d share my findings with you guys.

WARNING: This post contains the words ‘WSP’ and ‘assembly’ many, many times.

I had a few different web parts that each had their own WSP as they are sold/deployed separately and are not related. I also had a ‘common’ assembly that was referenced by each of these web parts.

My first task was to package this common assembly so that it could be deployed with each web part, so I simply told (demanded?) Visual Studio to include the common assembly in each WSP. So now I had a bunch of WSP’s each containing a copy of the same common DLL. Would I be able to install these WSP’s without conflicts?

Yes. Lo and behold SharePoint installed my WSP’s and common assembly to the GAC just fine. I’m not sure if it overwrote or simply ignored the existing common assembly but it worked nonetheless – one common assembly referenced by multiple web part assemblies.

But I now had another challenge: if someone uninstalls one of the web parts, it would remove the common assembly from the GAC, breaking the remaining web parts that reference it. I tested this theory and indeed that is what happens.

Now I missioned trying to come up with a solution to this, and my searches all came up with the same suggestion: you need to create a separate WSP for your common assembly so that it doesn’t get removed when you uninstall your web part. I considered a couple of other ideas:

- Loading the assembly into the GAC programmatically (i.e. not via a WSP). I decided against this when I realised that I would have problems deploying to multiple servers in the farm, permissions etc. Best to leave that to SharePoint.

- Creating multiple versions of my common DLL so that each WSP would reference its own separate common assembly. I decided against this due to the nightmare involved with maintaining multiple versions of the same DLL. Deploying updates would be a major headache, and it’s just a messy solution.

- Moving the common code to each web part and scrapping the idea of a common assembly. Problem is, it was a very complex assembly with thousands of lines of code. Not having this as a common assembly would be maintenance hell and would make versioning really difficult.

I eventually settled on the idea of deploying the common assembly via a separate WSP just like the wonderful internet people suggested, which unfortunately presented yet another challenge…

I was using the popular SharePoint Solution Installer from CodePlex to deploy my WSP’s, but it only accommodated a single WSP as part of its standard functionality, and I had two of them to install: my web part’s WSP, and my common assembly’s WSP. I didn’t want people to have to go through two full installations (i.e. run two EXE’s) just to install a web part, so I decided to modify the SharePoint Solution Installer to install both WSP’s as part of a single installation (one EXE).

Some hacking was necessary, so I got to work modifying the Installer to first install my common assembly’s WSP, and then continue with its standard installation procedure of deploying my web part.

A couple days later and the end solution works like a bomb, so now my common assembly is deployed independently of the web parts that reference it.

The details of how I modified the Installer to do this are too complex to post here, but I just wanted to pass this general info on to anyone out there who is stuck with this same problem and pondering possible solutions.

Happy SharePointing!

About _layouts and referencing application pages


If you need to reference SharePoint’s _layouts path to point to an application page that you’ve built, it’s tempting to simply go <a href=”/_layouts/…”> as this works in most cases. It works fine when referencing images for example, which just need to be loaded from the filesystem, and /_layouts will get you there.

A problem creeps in though when using this method to point to pages (e.g. aspx/ashx) that reference SharePoint entities such as lists or list items.

You see, if your custom code is executed within a site collection with a different URL to the root, like say http://myserver/sites/MySiteCollection, and you’re using SPContext.Current.Site to reference the current site collection, your code could break when trying to load a list or another entity via its ID, because that list may not exist in the site collection that is referenced.

I ran into this problem recently when passing an SPWeb ID to my custom application page via the querystring. I wanted to instantiate the web, so I got a reference to SPContext.Current.Site and attempted to load the web, but the code threw an exception and complained (much to my disgust) that the web could not be found. It turns out that this was because it was physically located in a site collection at a different URL from the one I used to reference my page. My bad.

Because the _layouts folder is a virtual path, it can generally be accessed from any URL, even from a location that doesn’t actually exist (e.g. http://myserver/ThisIsNotARealSite/_layouts/images/ANNOUNCE.GIF). This makes it easy to reference stuff in the _layouts folder from anywhere, but it can give the false impression that you can reference your aspx pages using any URL and everything will be hunky dory. As I learned, it does matter what URL you use to reference your application pages.

So if you’re using SPContext.Current in your custom application pages be aware that your context is derived from that URL location, and when constructing URLs, always make sure that you reference the page at the correct site collection location. For example, http://myserver/sites/MySiteCollection/_layouts/MyCustomPage.aspx.

One way to point to your _layouts folder correctly is to use the same simple method that SharePoint uses internally, which I’ve delivered to you courtesy of .NET Reflector.

string layoutsPath = web.ServerRelativeUrl + (web.ServerRelativeUrl.EndsWith("/") ? string.Empty : "/") + "_layouts";

Yes, it’s a bit crappy to have to construct URLs in this way (instead of simply hard-coding /layouts in your hrefs), but it ensures that your custom code will always be executed under the correct site collection.

SharePoint Nuggets – June 2011 Part 2


So the Nuggets I managed to gather in May was so much that my June issue wasn’t big enough.  Herewith the second instalment of my June 2011 SharePoint Nuggets.

Hope they spark some thought, discussion and potentially safe you some time.

Enjoy.

SharePoint 2010 Administration

SharePoint 2010 Licensing

SharePoint 2010 for ITTPro’s

SharePoint 2010 and InfoPath 2010

TechNet Awesomeness

SharePoint Nuggets – June 2011


You guessed it, it’s that time of the month again.  The topics covered in this months Nuggets ranges includes, Federated Search, Fixing Troubled Farms, Fun with InfoPath, Testing SQL Connectivity, Publishing Feature Mayhem and more.

Have fun reading through the bits and pieces I’ve collected over the past 4 weeks:

SharePoint and Mobility

SharePoint Farm, SQL Connectivity

  • If you are trying to disconnect from a troubled SharePoint Farm, simply stop SQL which will force SharePoint to give you the option to disconnect from the farm.
  • To test SQL connectivity you can use sqlcmd -S <servername> -E
  • Read this blog entry to find out how to see what port SQL Server is listening on (http://www.smallcitydesign.com/problems/cannot-connect-to-database/)

Configuring SSL for SharePoint 2010

  • Export from IIS 7
  • Import from website
  • Edit bindings to web application
  • Select certificate
  • Add alternate access mapping to SharePoint

SharePoint Administration

SharePoint Search

    • If search crawler complains about crawling account cannot connect to sps3://[servername] repository, ensure to complete the following steps:
      • Open Manage Service Applications
      • Select User Profile Service Application
      • Click on “Administrators”
      • Add the default content access account and select “Retrieve People Data for Search Crawlers” as per the following screenshot:

clip_image001[4]

SharePoint Migration Challenges

I’ve just realised that my Nuggets for June are too many to fit into one blog post.  I’ll either start doing this bi-weekly, or post it whenever I have 10 or so items to share.

Hope this sparks some thought and potentially saves a bit of time searching the net for answers.

SharePoint 2010 Search and Word 2007 Documents


We ran into an interesting issue with a client the other day.  The search decided that the first word in the document was more relevant than the title or name of the document which caused obvious confusion for the users completing searches.  Sepaka, one of my team members, did the troubleshooting and successfully resolved the issue.  I’ve given him the opportunity to write his finding in the post below as a guest author.

//Guest Author – Sepaka Hlongwane

Before editing the registry I tried searching for the word “numbering” which happens to be the document title for my word 2007 document. The search results returned “description”  when it should be returning the document title. See an example below

Description

The following is an example on how to number your drawings…

http://example.portal.com/document library/Numbering of drawings.docx

instead of

Numbering

The following is an example on how to number your drawings…

http://example.portal.com/document library/Numbering of drawings.docx

I double checked and the Title Property of the word document is set. I checked it by downloading the document to my local machine, then right clicking the document à properties à then details tab.

Thanks to Saji Viswam’s Blog for recommending the following fix.

1. Open registry for editing by typing “regedit.exe” in Start > Run

2. Navigate to the key [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Office Server\14.0\Search\Global\Gathering Manager]

3. Change the hexadecimal value for EnableOptimisticTitleOverride to 0 (zero) on the right hand side.

4. Restart SharePoint Search service by typing the following commands in command prompt.

o net stop osearch14

o net start osearch14

5. Perform a full crawl

After full crawl, the search will display the correct title for Word 2007 documents just like any other word document versions.

Thank you.

Kind Regards,

Sepaka Hlongwane

Introducing SharePoint Nuggets


During the course of any given period I come across an enormous amount of SharePoint related content, whether it be articles, tips, tricks, cool sites and more.  I tend to bookmark things, gather it in OneNote and plan to write elaborate posts about almost each item I find. 

This hasn’t worked.  The amount of content generated in the community on a daily basis is simply too much to take note of all and draw your own conclusions on it all OR add insightful comment to it all.

Enter SharePoint Nuggets

I’ve decided to create a new post heading where I will literally jot down ideas, notes, links and more that I’ve amassed over a period of time.  I’m not sure whether I’ll do this weekly, monthly or whatever, but I’ll be doing my best to keep it going.  Herewith the first instalment:

SharePoint Nuggets – May 2011

The theme of nuggets this time around is Microsoft SharePoint Foundation 2010.  I did a lot of research for my presentation at SharePoint Saturday and have decided to share some of the links with the greater community.  Here they are, have fun:

http://www.sharepoint911.com/blogs/laura/Lists/Posts/Post.aspx?List=676af157%2D7d96%2D4e15%2Da987%2D54b8a3e4d948&ID=44

http://www.microsoft.com/downloads/en/details.aspx?FamilyID=c8cf1631-0f48-4a02-a18d-54b04eb7f0a7 (Microsoft SharePoint Foundation 2010 Technical Library in Compiled Help format)

http://satishsri.wordpress.com/2010/04/05/lists-of-webparts-in-sharepoint-server-2010/

http://www.wssdemo.com/Lists/WebParts/sharepoint-web-parts.aspx

http://technet.microsoft.com/en-us/library/gg508696.aspx (What’s new in Windows Small Business Server 2008)

http://msdn.microsoft.com/en-us/library/ee539826(office.14).aspx (What’s new in SharePoint Foundation 2010)

http://blog.allyis.com/blog/bid/48102/Working-with-SharePoint-2010-Foundation-Master-Pages

http://www.pentalogic.net/sharepoint-knowledge-base/white-papers#smallbusiness

http://technet.microsoft.com/en-us/library/ff934618.aspx (Co-authoring)

http://technet.microsoft.com/en-us/library/ff934620.aspx (Co-authoring admin)

http://veroniquepalmer.wordpress.com/2011/02/11/deleting-users-from-hosted-sharepoint-2010-foundation-sites (Security in MSF2010)

Enjoy.  Smile

How To Time a Piece of SharePoint Code


If you’re optimizing your custom web parts or SharePoint components for performance, you might want to time how long it takes for a certain piece of your code to execute.

Here’s a handy C# snippet that you can use to do just that:

var timer = System.Diagnostics.Stopwatch.StartNew();

(your code goes here)

timer.Stop();
Response.Write(timer.ElapsedMilliseconds);

This isn’t SharePoint specific – you can use this snippet in any .NET app, but I’ve found that it definitely comes in handy when performance tuning your SharePoint code.