I've noticed over the years that a lot of different types of windows popup whenever I click on a document in SharePoint. Back in the "2003" days, you'd be lucky if anything popped up at all. Then in 2007, when the whole publishing paradigm started to solidify in people's minds, we began to see different options when we accessed different documents...especially Office documents.
With the 2010 release (of both client and server), Office integration has only deepened. I mean, even Visio has been invited to the Office/SharePoint integration party. Nowadays, this type of functionality that was new and cool in 2007 has come to be expected. The workflow of checking something out from your browser in SharePoint, having it open in Word, and then saved, tagged, and checked back in all in the same session is really cool.
Several factors determine the experience your browser will give you upon integrating with Office: document library settings (around versioning, check in/out, etc.), the actual version of Office installed, domain-joined-ness, and of course browser platform, version, and security. This is why sometimes the file just opens in the browser, sometimes you get a security warning, sometimes you get a popup asking if you want to open the file in "read only" or "edit" mode, and sometimes Office comes to life, opens the document, and handles all the SharePoint integration from there.
This method is defined in core.js, which is nestled in the layouts/1033 subdirectory of the SharePoint Root (aka the 14 hive). (It's no longer called "the hive," probably because the files inside are not actually bees.) Core.js is "obfuscated" and to be honest, not worth decoding. Whatever this method does (I'd guess something with cookies, if you put a gun to my head) it makes all the beautiful goo between SharePoint and Office remain sticky.
So if you want to mimic SharePoint's functionality, create an anchor tag, set the "href" attribute equal to the URL of the document, hook "onclick," and call "DispEx." (I'll provide an example later in this post.)
What I meant by SharePoint "owning" the page is that the ASPX is using a customization of a raw SharePoint MasterPage, and core.js will be available. But this isn't always the case. My current project is a collaboration tool for our client's design team, and the UI has a lot of heavy animation and styling, as well as very stringent performance requirements. Furthermore, the majority of the users are on Macs using FireFox and Safari.
For these and other reasons, we went with a straight Silverlight page, where the only HTML is the object tag used to host the plugin. Everything else is XAML. SharePoint is the backend, used for image and file storage, search, administration, etc. (Yes: a SharePoint app with no SharePoint UI!) So, we can't simply call methods in core.js, since our page doesn't even live in a SharePoint web application, and therefore no SharePoint client code is pulled down.
A disclaimer before I should you some code: this might seem a bit over-engineered. This is because of a weird nuance with the way DispEx works. When you close the Office application that it opens, the browser refreshes the page automatically. My guess is that this is to update the metadata of the document in the case where you changed something client-side. This is problematic, because if the page refreshes, my jQuery runs again, and Office will launch another time!
First, let's look at the code behind for our application page:
All this does is inform the client when it should open the document. Next, let's move on the HTML. I used the OOTB layout you get when you create a new application page, so I excluded a lot of the template markup from the following listing. All we're interested in are the "PageHead" and "Main" content placeholders.
Like I said, all this does is click the link only the first time to page is loaded, instead of after each refresh. Notice the window.close() call in Line #9. The first implementation of Silverlight/SharePoint/Office integration I came up with involved popping our application page up in a new window. This line "cleaned up" our application page as Office loaded, but absolutely wouldn't work on our test Mac. Besides, this was a Silverlight app, where every drop shadow and Visual State was crafted with care; why get sloppy and start having empty browser windows spamming around?
Instead, we shoved a hidden iframe right next to Silverlight's history iframe. If you do this, make sure to keep your iframes inline with the closing Silverlight object tag, otherwise you'll see an otherwise-inexplicable gap of white space at the bottom of your page. Figuring that out took an hour of my life that I'll never get back. Make sure you give your iframe an id, since we'll be referring to it programmatically.
Finally, let's look at how Silverlight plugs into this. If you use a Silverlight Hyperlink control and set the NavigateUri property to the absolute URL of an Office document, clicking it will open the file in the targeted frame with no integration features enabled. So instead of using the NavigateUri property to do our bidding, we bound the click Command to a method in our view model, (if you're thinking Prism/MVVM you're thinking correctly) and the CommandParamer to the URL of the document. For more on MVVM command binding, read this. Our view model's command implementation takes the document URL from the CommandParameter and passes it to the following utility method:
Oh well; at least it works. Have fun integrating!