Tuesday, December 13, 2011

SharePoint as a document database

No, not the No-SQL kind. I'm nearing completion of a project at work where our internal customer wanted a central repository for their documents. The catch? SharePoint tends to be a bad word among most users. Thankfully SharePoint 2010 ships with a nice RESTful service exposed via ListData.svc so we can leverage SharePoint without anyone really knowing about it.

Following Corey Roth's blog post and this MSDN article, I was able to easily query for documents using LINQ. You even get an index back, but I had to parse it from the server response when adding the document since it gives you the full location as "http://<sharepoint-server>/<site>/_vti_bin/ListData.svc/<ListName>(<Index>)". A lot of this is off the top of my head (sorry, can't really post code samples from my work code):
var service = new MyListDataService(new Uri("http://<sharepoint-server>/<site>/_vti_bin/ListData.svc"))
{
     Credentials = CredentialCache.DefaultCredentials
};

string path = "/<site>/<ListName>/doc.txt";
string contentType = "plain/text";

DocumentItem item = new DocumentItem()
{
    ContentType = contentType,
    Name = "doc.txt",
    Path = path,
    Title = "doc"
};
            
service.AddToDocuments(item);

byte[] data = //wherever the raw file data comes from

service.SetSaveStream(item, data, false, contentType, path);

var response = service.SaveChanges();

int id = //code to parse the index from the Location header of the response

var document = service.Documents.FirstOrDefault(d => d.Id == id);

So I can save and find the document, but how do I edit it? That was a little trickier. My initial idea was just to use Process.Start on the url for the document (this is a WPF app by the way), but for some reason SharePoint defaults to read only when you do that. Nick Grattan has a great solution that I modified to use dynamics since it works so well when you have to bust out some COM code.
var docUrl = "http://<sharepoint-server>/<site>/<ListName>/doc.txt";
Type t = Type.GetTypeFromProgID("SharePoint.OpenDocuments.3");
dynamic sharePointControl = Activator.CreateInstance(t);

sharePointControl.EditDocument(docUrl, string.Empty);

And voilĂ ! Now I can store meta data about the document in my app database, retrieve it from SharePoint and get the power of locking and versioning! I wish I could take credit for the idea, but my boss recommended it. I just thought I'd share the adventure of trying to make it work.