Thursday, 17 July 2008 09:29 by
jshaw
In my 1st technical post I'd like to share how I implemented a delicious-like feature in a Sharepoint site (called "Quick Post") that lets users post a file or Url to a Sharepoint document library with one click of a button on any page of the site; the user can tag each post just like with delicious, and the site has tag cloud and searching-by-tags features for users to find info later; the user will get suggestions on existing tags when he tags.
The following is a screen shot of the pop-up window after the user clicks on the Quick Post button in the site:
The type just gives the user a choice on one of the two different
document libraries. The location is a toggle between the ASP.NET
FileUpload control for file and TextBox control for Url, using
Javascript.
With this custom UI, the user is able to post a file or Url to the
document library without leaving the page he's on, and in one screen
(unlike the built-in multiple Sharepoint pages for adding a file or
Url, and any tags in the tag field of the document library); the custom
UI also has tag suggestion to maximize tag reuse :).
The Pop-up Window
The pop-up window you see in the screen shot is a DHTML window (which
is better than a browser window because of pop-up blocker). I'm all
for re-using others' code as much as possible :), so for the pop-up
window I used and would recommend this 3rd party widget.
Just include the 3rd party widget in your page that pops up the window
(in our case the master page since the QuickPost button needs to show
up everywhere):
<link rel="stylesheet" href="http://devcentral/_vti_bin/windowfiles/dhtmlwindow.css" type="text/css" />
<script type="text/javascript" src="http://devcentral/_vti_bin/windowfiles/dhtmlwindow.js">
</script>
and have the button click call the following javascript function:
var quickPostWin = null;
function openQuickPostWindow ()
{
quickPostWin = dhtmlwindow.open("quickPostBox",
"iframe",
"http://devcentral/Pages/QuickPost.aspx",
"Quick Post",
"width=650px,height=400px,resize=1,scrolling=1,center=1",
"recal");
if (quickPostWin.onclose == null)
{
quickPostWin.onclose=function(){ //Run custom code when window is being closed (return false to cancel action):
return true;
}
}
}
The content inside the window comes from a ASP.NET user control
(.ascx). The easiest way I found to develop custom pages in Sharepoint
is to develop it in Visual Studio (so you take advantage of the
designer support, code-behind, etc), and host it in a Sharepoint web
part: a page viewer web part to host .aspx, or like in this case, a 3rd
party smart part web part
to host .ascx; the page shown in the DHTML window (http://devcentral/Pages/QuickPost.aspx) is just a Sharepoint page with one smart part web part that hosts a .ascx. Sharepoint still has some way to go in terms of its
integration with Visual Studio for development, and this is kind of a
stopgap until MSFT builds the functionality of developing custom pages
for Sharepoint right into Visual Studio.
AJAX functionality
As seen in the screen shot, Quick Post provides suggestions as the user
starts typing in tags, just like delicious. To add AJAX functionality
like this, I used the AJAX Control Toolkit
from codeplex; it contains quite a few extenders to ASP.NET controls to
add AJAX to your web page, and in this case I used the auto-complete
extender to the tags text box.
To use AJAX Control Toolkit in Sharepoint, make sure to reference it
and include the ScriptManager in the page. Since in our case we want
AJAX functionality in every page (as in most cases I think), I just put
the following in the master page:
<%@ Register Tagprefix="ajaxToolkit"
Namespace="AjaxControlToolkit"
Assembly="AjaxControlToolkit, Version=3.0.11119.26320,
Culture=neutral, PublicKeyToken=28f01b0e84b6d53e" %>
...
<ajaxToolkit:ToolkitScriptManager ID="ScriptManager1" runat="server" />
Here I'm using AJAX Control Toolkit's implementation of the
ScriptManager rather than the one in ASP.NET AJAX, as the former is
supposed to be more efficient at sending the javascript down to the
client.
The auto-complete extender itself is pretty straight-forward as
documented: in my implementation, the web-service responding to the
user key strokes in the tags text box just iterates over all records in
the document library, extracts and parses the tags from the
comma-separated tag field (using Sharepoint API's), and return the tags
matching the given prefix.
There's perhaps one tricky thing in the web service. In our Sharepoint
site, the user is free to create sub-sites, and those sub-sites can
contain library items with tags as well, so to make sure we capture all
existing tags from all sites in this site collection, you need to make
sure either every user has the permission to iterate over all sites, or
elevate the privilege in the web service code somehow, .e.g, by
impersonating a user that for sure has permission to do it:
SPUser wssAccount = null;
using (SPSite siteCollection = new SPSite("http://devcentral"))
{
// need to impersonate to iterate over all sub-sites
wssAccount = siteCollection.OpenWeb().AllUsers["corp\\dcentral_wss_svc"];
}
using (SPSite impersonatedSiteCollection = new SPSite("http://devcentral", wssAccount.UserToken))
{
// iterate over all sites, get all the tags, and return matching tags
...
}
The above will also do the trick any time your custom code using the Sharepoint API's needs to run in elevated privilege mode.
Storing Url in a Document Library
Sharepoint document libraries can have multiple content types, and when
it does, the user can choose which content type it is when adding a
record to a document library. There's a "Link to a Document" content
type that's well suited for storing Url's in a document library; in
fact it can store link to another document as well. For our Sharepoint
site, however, we just need to support storing Url's.
It's however not well documented how to add a document link
programmatically, as I had to do for our custom UI. When a user adds a
document link to a document library, what happens behind the scenes is
that Sharepoint actually creates an aspx file on the fly that does
nothing more than redirecting to the document link Url you give, and
it's the aspx file that's stored in the document library, just like a
document stored in the document library. A rather convoluted way to
store links in my opinion, but that's the way the document link content
type works.
After bugging him about it, Cliff Green from MSFT wrote up how to
programmatically add a document link to a document library in his blog
:). Essentially you have a aspx template file that you read into
memory each time you add a document link to a document library, after
filling in the Url in the template file in-memory.
Conclusion
In this blog post, I've hopefully covered how to have custom pages
in Sharepoint (leveraging Visual Studio designer), adding AJAX to your
page, and how to have Url's in a document library. In future posts I
will share more customizations I've done in Sharepoint. Hope this
has been a useful read :).
Friday, 6 June 2008 13:51 by
jshaw
TechEd 2008 just finished. It was a blast! I enjoyed it a lot. Microsoft did a great job throwing a fairly smooth event, given the number of attendees, and pampering of the attendees, including a night at the Universal Studio. See my picture with the Simpsons there:
Look. They even provided bean bags for us to sleep on when we are exhausted from the conference:
The sessions themselves were about 1/3 bad, 1/3 good, and 1/3 excellent. I have to give MS credit for trying to get feedback; I heard from one of the speakers that they have a monitor that constantly shows the bottom rated speakers who probably won't be invited back next year. I also noticed a pattern of the MS speakers there: they are all PM's rather than developers. Hmm... Even most of the staff manning the product booths were PM's. I asked one of them why there's no developers; he said that they'd rather work and finish the product. Do you believe that? :).
The excellent sessions I attended were (in case you want to view their videos online): "Asynchronous ASP.NET", "Silverlight Tips", and "ASP.NET AJAX Extensions Deep Dive" by Jeff Prosise, "ASP.NET Performance Black Belt" by Steven Smith, and "SEO for Developers" by Nathan Buggia. I only went to the sessions based on the topic, and Jeff's sessions always overflowed. Apparantly a lot of people went to sessions based on the speaker :).
These sessions are also good to check out: "IIS 7 Security and Tuning" by Ruslan Yakushev, "Silverlight Controls" by Karen Corby, "REST web services using WCF" by Jon Flanders, and "Optimizing Javascript and IE" by Cyra Richardson.
At the conference, I was really impressed by Silverlight's capabilities and felt that it's really going to disrupt the web space. I attended a BofF session (i.e., a peer discussion among TechEd attendees w/o MS) on Silverlight vs AJAX, and as people started listing out the pro's and con's of AJAX and Silverlight, it became clear that RIA like Silverlight is the superior solution and the next step of evolution in web development; AJAX is really an intermediate stage towards richer content/easier development (Google is solving ease of development with GWT, but there are just things you can't do with AJAX that you can do with Silverlight/plugin-type of model). The one major drawback is searchability (Plugin model is still a black box that search engines can't crawl), but like Nathan said, it's something that all search engines are trying to crack and find a solution of.
With all the talk about Silverlight, I also felt a bit deja vu. In my college years Java applet was all the hype of the day, and, except more advanced graphics and a declarative model, it pretty much has everything Silverlight has (including a bridge with Javascript/Browser DOM). Java applets didn't take off for some reason (non-ubiquitous broadband?). It seems like we're going back full circle to a plugin-model of web development like Flex/Flash and Silverlight.
I also saw an interesting book at the conference store and couldn't resist buying it:
I've skimed through it and think it's a pretty candid assessment of Microsoft today; it's written by a well-know Microsoft analyst Mary Jo Foley. Check it out!
Overall it was a great experience for my 1st time at a Microsoft conference. The MS people were friendly technical enthusiasts who seem genuinely passionate about technology, and I felt right at home talking to them :).
Monday, 18 February 2008 12:39 by
jshaw
I really gotta get in the habit of writing blogs...
Recently I just bought a new personal laptop, to replace my venerable IBM Thinkpad T41. Thought it'd be good to share my experience:
Originally I was just going to buy the latest Thinkpad (T60 at the time); seemed like a logical choice. I was at the same time upgrading my work laptop to a T60p; good thing I waited to see how it is before buying one for my personal use. The laptop was heavier than T41, freezes half of the time whenever I undock and bring it back from sleep, or whenever I dock. It was terrible. A lot of my co-workers also had the same problem, and the IBM service rep on-site did his best (including putting a jumper on one of the docking station pins and some software option) but the freeze still happened. Nowadays I just use it like a desktop, i.e., always having it docked and remoting to it from another laptop when I need to access it, which totally defeats the purpose of having a laptop. It seems that since the acquisition by Lenovo the quality of thinkpad just went way down...
I then started looking for another brand for my personal laptop. In the end I settled for a macbook (BTW I bought it from ecomelectronics; probably the cheapest place for it). Still getting used to it; there has been lots of little things that annoyed me, like the extra small screws that need a special screw driver to open to install more memory, and the stupid bootcamp download from apple website that expires as soon as you run it (since it's part of Leopard and they don't want people using the beta one; why don't they just disable the link on their website if it's not meant to be used?). What frustrated me the most was that the drivers bootcamp installs for Vista by default conflict and whenever you play music (or game) it skips. It cost me quite a few hours before finally finding a solution (see Smaels' 1st post on the page).
Overall I'm just disappointed at the quality of laptops (and electronics in general) nowadays. Seems like companies just try to rush to market without doing enough QA; these 2 scenarios are so basic (docking and undocking a laptop; playing music after installing Vista on a macbook) that I'm apalled to see that Lenovo and Apple released their products without covering them.
For now I'm fine with the macbook. It's still not as good as my old T41 (where everything just works as expected), but probably the best laptop experience I'll get. One good thing about owning a macbook for a software developer is that you can test your web app on all 3 major browsers (IE, Firefox and Safari).