GWS Application: See It Run!
Having covered the security pre-requisites, we can build an application which actually runs.
In Part 1 I built a basic Outlook addin with a form triggered by clicking a button. Then Part 2 added the basics of Groove Web Services access.
Now add three combo-boxes to the form; call them IdentitiesCombo, WorkspacesCombo and ToolsCombo. And add OK and Cancel buttons.
I want the combo-boxes to hold references to GWS proxy class instances, but display appropriate string values. So I made some little helper classes to override ToString(). Here's the helper for identities; there's a very similar class WorkspaceInfo to wrap a Space, and ToolInfo to wrap a Tool.
// Helper class for us to place Identities in a combobox
private class IdentityInfo
{
public Identity identity;
public IdentityInfo(Identity i)
{
this.identity = i;
}
public override string ToString()
{
return identity.Name;
}
}
Now in the form constructor, it's easy to read the list of identities known to Groove:
public Form1()
{
InitializeComponent(); // Required for Windows Form Designer support
// Set up a call to the GrooveAccounts web service
GrooveAccounts accountsService = new GrooveAccounts();
accountsService.GrooveRequestHeaderValue =
new GrooveAccountsWebService.GrooveRequestHeader();
accountsService.GrooveRequestHeaderValue.GrooveRequestKey =
GWSUtil.GrooveLocalRequestKey;
accountsService.Url =
GWSUtil.GrooveURL + @"/GWS/Groove/2.0/Accounts";
// Read the list of Groove accounts
Account[] accounts = accountsService.Read();
// Add the list of identity names to the combo box
IdentitiesCombo.Items.Clear();
foreach (Account a in accounts)
{
foreach (Identity i in a.Identities)
{
IdentitiesCombo.Items.Add(
new IdentityInfo(i));
}
}
// Select the first identity
if (IdentitiesCombo.Items.Count > 0)
{
IdentitiesCombo.SelectedIndex = 0;
}
}
When selection changes in the IdentitiesCombo, we read the list of workspaces for the selected identity.
IdentityInfo
i = (IdentityInfo)IdentitiesCombo.SelectedItem;
selectedIdentity = i;
WorkspacesCombo.Items.Clear();
string spacesServiceURI = i.Spaces;
GrooveSpaces spacesService = new GrooveSpaces();
spacesService.GrooveRequestHeaderValue = new GrooveSpacesWebService.GrooveRequestHeader();
spacesService.GrooveRequestHeaderValue.GrooveRequestKey = GWSUtil.GrooveLocalRequestKey;
spacesService.GrooveRequestHeaderValue.GrooveIdentityURL = i.URI;
spacesService.Url = GWSUtil.GrooveURL + spacesServiceURI;
// Read the identity's workspaces.
Space[] spaces = spacesService.Read("");
// Add the workspaces to the combobox (unselected).
foreach (Space s in spaces)
{
if (s.Local)
{
WorkspacesCombo.Items.Add(
new WorkspaceInfo(s));
}
}
// Select the first workspace
if (WorkspacesCombo.Items.Count > 0)
{
WorkspacesCombo.SelectedIndex = 0;
}
A few things here are worth commenting.
We remember which identity was selected (selectedIdentity), because we'll need that later.
The Identity has a property Spaces which is the URI of the "spaces-for-this-identity" web service. So the spacesService.Url, where we'll send the SOAP request to read spaces, is the Groove local URL (http://localhost:9080) plus that opaque, identity-specific URI.
The call to spacesService.Read() is synchronous (just like the earlier call to accountsService.Read) - the application will block until Groove returns a response. Usually reading the list of accounts and identities is very quick; but reading the list of workspaces can take a little longer. If the selected identity is not logged in, Groove pops up the login dialog, and GWS will not respond until the account is logged in (or the login canceled). You could use the BeginRead/EndRead to make the web services call asynchronous, but that's a bit more work.
Also: we only add workspaces to the list if they are local. With multiple machines using the same Groove account, it's possible to be a member of a workspace but not have that space on your current device; there's no further information available about workspaces which aren't local, so let's filter them out right away.
Lastly: identities, workspaces and tools won't necessarily be returned in any particular sequence; certainly not alphabetical by name. So I made all the combo-boxes sorted (as well as DropDownList style, so they're not editable).
When selection changes in the WorkspacesCombo, we read the list of tools for the selected workspace.
WorkspaceInfo
w = (WorkspaceInfo)WorkspacesCombo.SelectedItem;
ToolsCombo.Items.Clear();
string toolsServiceURI = s.Tools;
GrooveTools toolsService = new GrooveTools();
toolsService.GrooveRequestHeaderValue =
new GrooveToolsWebService.GrooveRequestHeader();
toolsService.GrooveRequestHeaderValue.GrooveRequestKey =
GWSUtil.GrooveLocalRequestKey;
toolsService.GrooveRequestHeaderValue.GrooveIdentityURL = selectedIdentity.URI;
toolsService.Url =
GWSUtil.GrooveURL + toolsServiceURI;
// Read the workspace's tools.
Tool[] tools = toolsService.Read();
// Add the tools to the combobox (unselected).
foreach (Tool t in tools)
{
ToolsCombo.Items.Add(
new ToolInfo(t));
}
// Select the first tool
if (ToolsCombo.Items.Count > 0)
{
ToolsCombo.SelectedIndex = 0;
}
And that's it! A functional "Groove-browser". (Next I suppose we should read some data!)