Monday, December 14, 2009

Take THAT, Sharepoint Document Library Copy Procedure!

Copying documents from one location in SP to another: Should be easy, no?

Well, it seems that it depends entirely on how far you're moving them, and how much you care about metadata (created by, modified by, version history, etc.)

If you don't mind losing your metadata, just open your source and destination libraries in explorer view, and copy/paste or drag/drop as needed. This works for moves between doc libraries in the same AND in different site collections.

If you want to preserve metadata and you're just moving stuff within a single site, use the Site Content and Structure page to select and move your files.

What if you need metadata AND want to move items between two entirely different site collections, tho?

The best solution is probably a coded one - write some custom web service or some such to move all of that. A few 3rd party tools are also out there which can help with this. Unfortunately, I don't have the C# skills or the purchasing power to pursue either of those. What's a BI monkey to do?

Poking around for an alternative solution, it occured to me - say, don't backups preserve metadata? ...I don't want to overwrite my destination site for these files, but what if I created a temporary sub-site, dumped the backup there, and then used the Site Content and Structure page to move the files to their final resting place?

Worth a try! I hit the source site and backed up the first sub-site I was concerned about, using the stsadm Export tool. I created an empty sub-site on my destination site, plunked the resulting .cab file into my destination site's server, and ran the import procedure to dump the data into it.

It worked! It takes a little longer than a straight copy-paste, but it does preserve metadata on your files while moving them to the new location.

Tips:
If you have to use -nofilecompression to export your list, be sure to add the same parameter to your import procedure (syntax example here)

Make sure your source subsite and destination subsite are the same. I got an error saying mine weren't, and had to refer to this list to translate the template code it gave me.

When first running my -import, I got an error regarding the 'AllowAutomaticASPXPageIndexing' attribute. Found a hotfix and a workaround here, and used the workaround.

Doublecheck to make sure you use the –includeusersecurity parameter when exporting/importing; when I left that out, the ownership metadata dissapeared.

Thursday, December 3, 2009

Sharepoint: Item-Level Permissions in Doc Library Based on List Data

Had an interesting challenge to set item-level permissions on a SharePoint document library based on list metadata. If a user uploaded a document and set the value of a list column to "published", everyone could see it. It the document was "unpublished", only a restricted group could view the file.

After a lot of surfing around the web, I found Richard Seroter's excellent post, which covered the vast majority of what I needed.

As Richard did, I created both my main document library and a lookup list which contained my published/unpublished values, and a list of users associated with each.

NOTE: I tried using a people/groups field type for this column at first, but when queried, that returned both the field ID and value, like "1;DOMAIN/username;2;DOMAIN/user2". I finally switched to a multi-line text field instead, which was easier to query cleanly.

In my main document library, I set up a lookup field that pulls the title values from my lookup list. So far, so good!

In order to run the Sharepoint Server Sequential Workflow project in VS 2005 Richard used, I needed to nab first the Visual Studio 2005 extensions for .NET Framework 3.0 add-in, and then the SharePoint Server 2007 SDK: Software Development Kit.

NOTE: I actually ran into an issue where neither set of templates were showing up in my already-installed copy of VS 2005, so I ran a repair install before I could finally access them. Hopefully, it will just work for you. =)
OK, ready to run! I fired up VS, started the project, and got through the first couple of steps. I referenced another article at The Code Project for some of the finer details, including how to deploy the DLL to the GAC.

NOTE: Don't be a moron like I was. Make sure that you nab the PublicKeyToken when deploying the DLL, and fill that in wherever the code asks for it. Leaving it as '111111111111' doesn't work. ;)

When all was said and done, the project was finally deployed and it looked like things were working...but wait, that workflow that just said 'completed' is now 'in progress' again. We're getting 'out of memory' errors. What's going on?

Thanks to an article on how to debug your SP workflow, we found the problem: An infinite loop. No, not caused by our code - by the workflow itself.

See, the workflow was set to run when a new item is created OR when an item is changed. It turns out that when the workflow runs, it makes a change to the item...Which then triggers the workflow...Which makes a change...Which triggers the workflow...And you're stuck in an infinite loop. Brilliant.

Back to the web! An article on the same problem in another workflow scenario suggested simply disabling event firing immediately before the update is called, and turning it back on right afterwards.

That's the solution we put in for now, although I think it would be better long-term to move the IF statement up a notch. It could check and see whether the values it would be updating the list item to is already there. If old values = new values, do not update.

It's working for now, tho. Phew!