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:
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

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

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.

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.

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);
}
}
}
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.
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>