Why the wait?
I wasn't planning on writing a blog post now but... since Windows Explorer has given me a moment I decided to take this time to ask the question "Why?"
I've just uploaded a couple of files to a SharePoint site and I thought that I ought to organize the directory a bit by creating some folders and moving the documents into them. This of course would be a breeze on a local hard drive. On a network share not bad, but in SharePoint... a royal pain.
Consider what happens when you right click to bring up a context menu from a Windows Explorer window that is exploring a SharePoint site.
- Explorer goes into a coma while it waits for something. I can only guess it is contacting the remote server to decide just what it is going to be able to show me in the context menu.
- The wait cursor spins for so long that you give up and go do something else.
- When the enumeration is finished, explorer detects that the window no longer has focus so it doesn't show the menu.
- Perplexed you try again - instead of showing the same menu that it just paid a great deal to build - you go back to step 1 and start all over again.
I understand - explorer just wants to show me what I'm allowed to do. However, in order to protect me from trying to do something I'm not allowed to do, it is willing to make me wait 20 or 30 seconds while it queries a remote server.
A Better Way
Let's think about this problem from an architectural and user experience point of view.
Context
A user has requested a context menu by right clicking on a window that is displaying content from a remote system.
Problem
How do we provide the user with a context menu without putting the UI into a coma for so long that the user gives up?
Forces
- The remote system could be accessed over anything from a gigabit speed high bandwidth, low latency connection to a low bandwidth, high latency connection.
- The security authorization of the user on the remote system could be changed at any moment
- The list of commands that the user is allowed to invoke on the remote system is not fixed but it is not infinite either. One could guess at the commands that would be allowed because they list is commonly the same for most cases.
Solution
As we consider an optimal solution the following principles should apply
- Try to show the user the commands they are allowed to do if possible, but don't make the user wait
- Never, ever allow the user interface to go comatose by blocking the UI thread
- Inform the user of a long running operation and always allow the user to cancel the operation
- Cache work done on remote servers for some reasonable amount of time
If working on a high bandwidth, low latency connection build the menu on the first click
If you are on a low latency connection this will happen so fast it won't really matter to the user. The trick is deciding on just how good your connection is. If you are not sure then follow the next steps in this pattern.
When the app creates a connection to a remote resource, cache a "best guess" menu.
The commands allowed on the remote resource are fairly common. In the case of explorer they are the typical file handling commands. From the client point of view you know almost everything you need to know to display the menu with the exception of the current security authorization.
If you cache your "best guess" you could display a command that the user is not allowed to do. Is this optimal? No... but it is better than making the user wait. In the event that they try to do something that they are not allowed to do the request gets an error from the remote system. Is that bad? Sure, but we should point out that this can happen even if you check the authorization before you show the menu because the authorization can change at any moment.
When the app executes a remote command, add a request to enumerate the authorizations for future requests
Once you have decided to make the remote call, why not be a little proactive and add a batch of requests? Now you can have the server specifically enumerate the commands that the user is authorized to execute. Replace your "best guess" cached menu with a menu based on the server response.
When making a remote call, always use async IO
Yes it makes the programming model a little more difficult but please don't put your app into a coma - keep it alive, alert and pumping messages by doing async IO. Show the user what you are doing with something like a status bar message and please add a way to cancel the async request.
Keep in mind that there really is no way to cancel an async request - this is just an illusion. What you are saying is that when a request is canceled you will simply ignore the result when it is returned.
Conclusion
I finally got the folder created by going back to the SharePoint Web UI and creating it there. Then I did drag/drop to move the files from Explorer. It worked but it took a very, very, long time and even the drag/drop operation resulted in explorer querying the remote server prior to changing the mouse pointer. The effect of this was that I had to do drag/drop by faith. No I did not see the mouse pointer change to indicate the operation, however since the Mouse Button Down and Mouse Button Up operations were in the message queue when explorer finally got around to processing them it did indeed work.
What a pain... we can do better my friends, you can do better, for the users, for the experience of great software.
Comments
- Anonymous
March 31, 2008
The comment has been removed - Anonymous
April 01, 2008
The comment has been removed - Anonymous
April 03, 2008
I have been thinking is was our installation of Sharepoint or something was wrong with my computer. Thanks for sharing your similar experience. I hope that the SharePoint team can get this fixed in an service pack because it is very annoying. Dean