I love selling SharePoint as an application platform. When I'm in client conversations or architectural debates regarding SharePoint development, I usually end up referencing my three "tiers" of SharePoint applications, depicted as follows:
The sizes of the boxes are sized relative to what you can deliver feature-set wise. I've been able to file every SharePoint project I've done in the last six years into one of these categories. The vast majority of my work has been in the middle box: branding SharePoint with custom functionality. Even though you get to build a lot of cool stuff in these types of projects, you must be deeply entrenched in SharePoint to do so. How many times have you been writing CAML or provisioning lists or modeling content types and angrily caught a coworker out of the corner of your eye happily hanging out in SQL Management Studio?
Even though our tools are getting better and better, SharePoint development is still hard.
That's why I love SharePoint as a backend. You can leverage all the stuff SharePoint is really good at: search, a "free" image / document repository, security delegation, scalability, Office integration, etc. without having to deal with the inevitable challenges intrinsic to any CMS technology. My last major project followed this very high-level architecture. It was a whiz-bang Silverlight 4 application, with EF 4, SQL 2008 R2, .NET RIA Services, and Prism as supporting characters.
But it was also a SharePoint app! Our performance and branding requirements pointed directly to a custom application. However, the client also wanted to leverage their existing SharePoint environment. The solution? Use both! This opened up a lot of really interesting integration points for my dev team. You can read the Office Integration post for one of them. But nearest to my heart among these was using SharePoint as the search provider for our data-driven Silverlight app.
In order to make this happen, we had to do a lot of work across the application's layouts. On the front end, we needed to define the metadata that would be bound to the various search result UIs in our app. The backend reintroduced me to writing insane SQL views to surface the data SharePoint would index (my t-SQL fortunately hadn't gotten too rusty since I let EF into my heart). And in the middle was not only all the configuration required to make SharePoint able to index our data, but a WCF service as well to make it available down on the client.
This was my general approach to customize search:
The aim of this post isn't to go into a great amount of "how-to" detail on the above points; plenty of other blogs have really good detailed instructions on the minutia of these configurations. These are the same resources I used to help me come up with the approach. Instead, I wanted to share some of the issues I ran into along the way. The aforementioned blogs are great for "how-to's" but don't address any of the "what-if's." I am all about the "what-if's."
So now I'll go back through the procedure above and annotate them with my $0.02, as well as any problems, headaches, or anxiety I got along the way.
Finally, I'd like to discuss the service I've alluded to a few times. This is a standard WCF endpoint that lives on the SharePoint server, and is called by the Silverlight frontend to facilitate search. Basically, the app sends the query and the search scope to the service, which then does all the magic needed to query both our database and the content stored within documents, merge the results together into a single array of DTOs, and send everything back down.
Let's look at some of the more interesting parts of this service. First, the following code shows my entry point into the SharePoint search API, and how I parsed the query to support key words (and quoted phrases).
Next, (and this would be starting at Line #11 above) we add the metadata properties we want to search against. This is the "select" clause of our search query.
Now the "from" and "where" statements:
Line #2 sets the scope, and Line #8 is what pulls in content from documents in Document Libraries. Now we configure the query and execute it:
The final bit goes in the for loop at Line #12. This is the logic that determines if a search result is from our application (the database) or content (SharePoint).
And there you have it. The service returns a collection of SearchResult objects that Silverlight binds to the UI.
So that's the story of a highly-customized SharePoint search solution that indexes both a custom database and content from asset stored in document libraries. As I said in the beginning: SharePoint is not just a CMS; it can play a serious role in a custom application as a provider of backend services. It provides all the enterprise search and storage APIs that you'll ever need.