log4net •  C++ •  VB6 •  VBA •  .NET  •  Silverlight •  ASP.NET

Universal Trace Monitor for Software Developers and Testers

Using DevTracer with Microsoft® Silverlight™

DevTracer can be used with all versions of Microsoft Silverlight, starting with version 2 beta up to the version 4.

Silverlight has its own version of the .NET framework, which is a small subset of the standard framework to give it a small footprint what download size is concerned. Because the .NET Framework Class Library for Silverlight is a small subset of the standard framework many classes are missing. Unfortunately the class TraceListener is missing as well. Therefore it is not possible to use DevTracer the way it is possible with Windows Forms or ASP.NET applications.

The framework for Silverlight still contains a class Debug in namespace System.Diagnostics. But this class is limited; it outputs the trace information to the output window of Visual Studio, and it does not use a TraceListener. It also does not have methods Indent(), Unindent() and Write(), which are part of the Debug class in the full framework class library. And class Trace is missing completely. Therefore it is not possible to use DevTracer Component with Silverlight. But because DevTracer can be used with ASP.NET, there is still a way to use it.

Normally you will use ASP.NET on the server when you develop a Silverlight application, and the Silverlight plugin is hosted in an ASP.NET page. The  principle is fairly easy: send the trace information to a Web Service build with ASP.NET, and this Web Service then uses DevTracer Component to send it to DevTracer Monitor. The steps to make it work are:

  • Add a Web Service to your ASP.NET application.

    Just add one method to this Web Service: public void WriteLine(string str)

  • Configure the ASP.NET application to use DevTracer.
  • Add a reference to the Web Service to your Silverlight application.
  • Add a helper class NRTracer to your Silverlight application which encapsulates the Web Service.

    This class is handling the calls to the WebService.

Then you will be able to add tracing to your Silverlight application with code like this:

NRTracer.WriteLine("Hello from Silverlight");

Step by Step

This step by step introduction uses Visual Studio 2010 and Silverlight 4.

Create a new Silverlight project

Start Visual Studio 2010 and create a new Silverlight project

New Project dialog in Visual Studio 2010 to create the Silverlight project

In the next dialog for adding a web site just take the defaults.

Add Web Site dialog

The solution will be created with two projects: SilverlightDemo.Web for the ASP.NET application and SilverlightDemo for the Silverlight plugin.

Add a button

Initially the file MainPage.xaml is displayed, which is basically empty. Therefore just add a button with an event handler for the click event. The xaml code should look like this:

<UserControl x:Class="SilverlighDemo.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    d:DesignHeight="300" d:DesignWidth="400">
    <Grid x:Name="LayoutRoot" Background="White">
        <Button Content="Click Me!" 
        Height="23" HorizontalAlignment="Left" Margin="92,70,0,0" 
        Name="testButton" VerticalAlignment="Top" Width="75" 
        Click="testButton_Click" />>
    </Grid>
</UserControl>

Add a Web Service to SilverlightDemo.Web

To add a Web Service, right click the project SilverlightDemo.Web and select Add New Item ... The Add New Item dialog is shown. Choose WCF Service, change the name to DevTracerService.svc, and close the dialog using the Add button.

Dialog to add a Web Service to project SilverlightDemo.Web

Visual Studio adds the Web Service to the project, and displays file IDevTracerService.cs with the Service Contract. It already has a method DoWork(). Change this method to WriteLine(string str). The file with the Service Contract should look like this now:

[ServiceContract]
public interface IDevTracerService
{
    [OperationContract]
    void WriteLine(string str);
}

 

The using statements have been omitted here. You must also change file DevTracerService.cs. Replace method DoWork() with WriteLine()

public class DevTracerService : IDevTracerService
{
    public void WriteLine(string str)
    {
        System.Diagnostics.Debug.WriteLine(str);
    }
}

 

Here we use the class Debug of the standard .NET framework. Instead of calling Debug.WriteLine(), it is possible to call Trace.WriteLine() alternatively. The difference is: Debug.WriteLine() is only available when building a debug version, Trace.WriteLine() is also available in the release version.

Now we have to configure the Web Service to use DevTracer Component. We choose to use the configuration file method and add the following lines to WEB.CONFIG.

<system.diagnostics>
 <trace autoflush="false" indentsize="4">
  <listeners>
   <add name="myListener"
    type=
    "NRSoftware.Tracer.Listener,NRSoftware.Tracer,Version=1.0.0.0,Culture=neutral,PublicKeyToken=867dfab712f16c0b"
    initializeData="localhost:12345" />
   <remove name="Default" />
  </listeners>
 </trace>
</system.diagnostics>

 

Have a look at initializeData="localhost:12345". 12345 is the port number used, and localhost specifies the ip address used to send trace information to DevTracer Monitor (localhost corresponds to 127.0.0.1). If you want to run DevTracer Monitor on a computer different from the one running the Web Service, you have to adjust this setting.

Now we are finished with project SilverlightDemo.Web. Next we have to prepare the Silverlight plugin.

Add a Service Reference to SilverlightDemo project

To add the service reference, right click project SilverlightDemo in solution explorer and select Add Service Reference ... . The Add Service Reference dialog pops up, with basically all fields empty.  Press the button Discover, and the Web Service we created before will be found. Select IDevTracerService on the left, and change the name to DevTracerService before proceeding with OK.

Add Service Reference dialog in Visual Studio

Now we only need the helper class to encapsulate the call to the Web Service.

Add wrapper class NRTracer

This is quite easy. Right click project SilverlightDemo in solution explorer and select Add → Class... . Enter NRTracer.cs as name. You get an empty class skeleton, which needs to be filled with some life. Here is the completed class:

using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;

namespace SilverlightDemo
{
    public static class NRTracer
    {
        private static DevTracerService.DevTarcerServiceClient _client = null;

        public static void WriteLine(string str)
        {
            if (_client == null)
                _client = new DevTracerService.DevTarcerServiceClient();
            _client.WriteLineAsync(str);
        }
    }
}
NRTracer.cs Download

 

That's all. Now your Silverlight application is ready to use DevTracer. You just have to call

NRTracer.WriteLine("information ....");

 

and the information will be displayed.

In the first step Create a new Silverlight project we added a button to MainPage.xaml, including a click event handler TestButton_Click. Let's fill this event handler with some code. The event handler can be found in file MainPage.xaml.cs

private void TestButton_Click(object sender, RoutedEventArgs e)
{
    NRTracer.WriteLine("In Event Handler 'TestButton_Click' : Hello from Silverlight");
}

 

Now let's start DevTracer Monitor (ip address to listen to should be localhost, the port 12345) and the Silverlight application (F5 in Visual Studio). The browser will start, and display an empty page with the button created before. Clicking the button then shows the message from the event handler in DevTracer Monitor.

Running Silverlight test application with DevTracer Monitor

Running Silverlight test application with DevTracer Monitor

 

Some Remarks about this implemention

The sample code shown here only implements one method in class NRTracer and the Web Service: WriteLine(). Theoretically it would be possible to implement methods like Write(), Indent() and Unindent() as well. We did not do this for a simple reason. With .NET for Silverlight you can call a Web Service only asynchronously (that's why class NRTracer calls method WriteLineAsync(), there is no method WriteLine()).

This has some consequences. Look at the following code snippet:

for (int line=1 ; line <=1000 ; line++)
{    
        NRTracer.WriteLine(string.format("This is line no. {0}.",line));
}

 

Running this code works, but looking closely at the data received by DevTracer Monitor will reveal that sometimes the data do not appear in the order expected.

This is caused by the asynchronous calls to the web service. But because there is no guarantee that the data are received in the same order they were send, methods like Write() or Indent() do not make much sense.

With some effort it is possible to synchronize calls to the Web Service. But it is not recommended.

In case it is required that data arrive in the Monitor in the correct order, we recommend a different approach. For this case enhance class DevTracer to cache trace information, and add a method which flushes the cached information and sends them to the Web Service. The enhancement could look like this:

private static StringBuilder _sb = null;

public void WriteLineToCache(string str)
{
  if (_sb == null)
     sb = new StringBuilder();
  sb.AppendLine(str);   
}    

public void Flush()
{
  if (_sb != null)
    {
       WriteLine(_sb.ToString());
       _sb = null;
    }
}
    
    

 

The sample with 1000 lines can then be rewritten:

for (int line=1 ; line < 1000 ; line++)
{
  NRTracer.WriteLineToCache( string.format("This is line no. {0}.",line));
}
NRTracer.Flush();
    

This approach also has the advantage that performance is much better, because the number of round trips to the Web Service is reduced.

IMPORTANT:

WCF Web Services have a default limit what the maximum length of strings is concerned. To reduce the risk of DOS attacks, this limit is set to 8196 characters. When using the cached method like described above, you have to change some settings for the Web Service, which can be done in the Web.config file of the service. The important parameter is maxStringContentLength, but you have to change some other parameters as well. Here are the important lines of the Web.config file:

<bindings>
  <basicHttpBinding>
    <binding
             maxReceivedMessageSize="1000000"
             maxBufferPoolSize="1000000"
             maxBufferSize="1000000">
      <readerQuotas
        maxDepth="32"
        maxStringContentLength="1000000"
        maxArrayLength="16384"
        maxBytesPerRead="1000000"
        maxNameTableCharCount="16384"  />

      <security mode="None" >
        <transport clientCredentialType="None" />
      </security>
    </binding>
  </basicHttpBinding>
</bindings>

<services>
  <service name="DevTracerService.svc" >
    <endpoint
      address="http://localhost:49351/DevTracerService.svc"
      binding="basicHttpBinding"
          
      contract="SilverlighDemo.Web.IDevTracerService"
      name="Test" >
    </endpoint>
  </service>
</services>