RGS Web Components Language Pack

Finally, also the Response Group Service Language Pack is available. As of last Thursday, it can be downloaded from http://www.microsoft.com/downloads/details.aspx?FamilyID=b49b7671-3a3a-4bca-bd97-1566ffb1413a. It installs additional resources for the Response Group Configuration Tool and the Response Group Agent Tab in 9 additional languages, so users get the user interface in their preferred language. The languages which are contained in the Language Pack are

  • Chinese (Simplified)
  • Chinese (Traditional)
  • English
  • French
  • German
  • Italian
  • Japanese
  • Korean
  • Portuguese
  • Spanish

Install and enjoy.

RGS Agent OC Tab with Silverlight

I’ve already described how you would create your own client using the RGS Agent WebService. Now what if you want to keep the tab in OC but make it look more fancy? Silverlight of course is your friend here. This post describes how you can create your own Silverlight based Agent tab, which will look like following. Btw, I am using Visual Studio 2008 to build this entire solution.

AgentTab

All the code for this can be found in AgentTabSl.zip (45.3 KB).

Getting Started

First I created a new Silverlight Application project and named it ‘AgentTabSl’. The project template already comes with the basic structure which we need for this Silverlight control. I added another Silverlight user control which I use to show one Agent Group, named ‘Group.xaml’. Its XAML looks like following.

<UserControl x:Class="AgentTabSl.Group"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <Grid x:Name="LayoutRoot" Background="White">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="Auto" />
            <ColumnDefinition Width="*" />
            <ColumnDefinition Width="Auto" />
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition />
            <RowDefinition />
        </Grid.RowDefinitions>

        <Rectangle Width="Auto" Height="Auto" Stroke="Black" RadiusX="4" RadiusY="4"
                   Grid.ColumnSpan="3" Grid.RowSpan="2" Name="Back" />

        <CheckBox Grid.RowSpan="2" Content="" VerticalAlignment="Center" Name="SignedIn"
                  Margin="2" Cursor="Hand" Checked="OnSignedInChanged" Unchecked="OnSignedInChanged" />

        <TextBlock Grid.Column="1" Grid.ColumnSpan="2" Name="GroupName" Margin="0,2"
                   FontWeight="Bold" />

        <TextBlock Grid.Column="1" Grid.Row="1" Margin="0,2">Number of Agents</TextBlock>

        <TextBlock Grid.Column="2" Grid.Row="1" TextAlignment="Right" Name="AgentCount"
                   Margin="2,2,4,2" />
    </Grid>
</UserControl>

I also added some code to the Group class to allow setting the agent group name, whether or not it’s a formal agent group, if the user is currently signed in and the number of agents. On top of this, I added a static method which return a new instance of Group created based on the required parameters.

Retrieving the data from the Web Service

Unfortunately, because of the limitations of the Silverlight runtime, we cannot use the client proxy generated from wsdl.exe here. But you can still add a reference to the web service, e.g. through the ‘Add Service Reference …’ command in Visual Studio. Simply enter the url to a deployed RGS Agent WebService (e.g. https://ocs-pool-01.contoso.com/Rgs/Clients/ProxyService.asmx) and everything else will be done for you. It is worthwhile to note that all methods of the web service will be asynchronous, but that’s not a problem. I’ve added an event handler for the Loaded event of the Silverlight application:

private void OnLoaded(object sender, RoutedEventArgs e)
{
    _service = new ProxyServiceSoapClient();

    _service.Endpoint.Address = new EndpointAddress(
        "https://ocs-pool-01.contoso.com/Rgs/Clients/ProxyService.asmx");

    _service.GetGroupsCompleted += OnGetGroupsCompleted;
    _service.GetAgentCompleted += OnGetAgentCompleted;
    _service.SignInCompleted += OnSignInCompleted;
    _service.SignOutCompleted += OnSignOutCompleted;

    _service.GetAgentAsync();

    _timer = new Timer(OnTimer, null, 0, 60 * 1000);
}

Timer is from System.Threading and I use it to periodically (every 60 seconds) refresh the data from the web service. This is required because else the Silverlight application won’t figure out if groups have been added / removed / modified. You should not make it refresh in less than 60 seconds, but in the end, it is your decision (and your servers).

Please keep in mind that if you want to deploy this Silverlight application on a web server different than the OCS WebComponents, you’ll need to allow Silverlight to access to that server. Please read the HTTP Communication and Security with Silverlight topic on MSDN for more information.

Retrieving the agent group memberships

The following code snippet shows the event handler for the GetGroupsCompleted event generated for us through the service reference. The first thing I am doing is to check whether or not we’re on the UI thread. If we’re not, we have to use the Dispatcher to invoke the method on the UI thread. The actual code to add the groups is then as simple as going through all groups and creating a new instance of the Group control which we’ll add to the Children collection of the StackPanel which holds the groups.

private void OnGetGroupsCompleted(object sender, GetGroupsCompletedEventArgs e)
{
    if (!Dispatcher.CheckAccess())
    {
        Dispatcher.BeginInvoke(() => OnGetGroupsCompleted(sender, e));
    }
    else
    {
        IEnumerable<AcdGroup> groups = e.Result.OrderBy(group => group.Name);

        Groups.Children.Clear();

        foreach (AcdGroup group in groups)
        {
            Group ctrl = Group.Create(group.Id, group.CanSignIn, group.IsSignedIn,
                                      group.Name, group.NumberOfAgents);

            ctrl.SignedInChanged += OnSignedInChanged;

            Groups.Children.Add(ctrl);
        }

        SetStatus("Ready.");
    }
}

Sign in / Sign out

Now what’s left is basically to let the user sign in / out throug a click on the checkbox for the corresponding group. As you can see in the code (when you downloaded it), I also added an event to the Group control which is fired when the sign-in state for the group is changed. In the code above you see that we’re subscribing to that event on line 18. So all we need to do is to actually call the corresponding method on the web service when the event is fired.

private void OnSignedInChanged(object sender, EventArgs e)
{
    Group group = sender as Group;

    SetStatus("Please wait while the operation is performed ...");

    if (group.IsSignedIn)
    {
        _service.SignInAsync(group.Id);
    }
    else
    {
        _service.SignOutAsync(group.Id);
    }
}

What’s missing?

If you look at the interface of the web service again, you see that it also allows you to sign in / out with multiple groups at the same time. I’ll leave it to you to implement that in this Silverlight application as well as it does not really involve anything which I haven’t discussed here. Also, you may want to highlight groups which have just been added by using a different gradient for the box.

If you’re planning on actually deploying a Silverlight Agent OC Tab, you most likely also want to make sure that the users get the static strings in their preferred language. The article Deployment and Localization on MSDN should give you all the information required to do that.

Multi-Lingual User Interfaces

One thing I found particularly interesting about the blog engine I am using (i.e. BlogEngine.NET) is that it comes with a multi-lingual user interface. To be more specific, the engine tries to find the best fit for the preferred language which you have set in your browser. This is nothing new but usually requires some work behind the scences. And as the guy behind (amongst many more) the multi-lingual user interfaces in all the administrative interfaces of the Response Group Service of Office Communications Server 2007 R2 I know what I am talking about 😉