Windows Service Administration with ASP.NET – Part 1 – Marshalling Status Information

This is the first of a three-part blog post on how to monitor and control a .NET Windows Service from an ASP.NET page.  The general approach I’ve taken involves using remoting to marshal a singleton object over a tcp channel.  If you’re not familiar with Singleton objects, remoting, serialization and marshalling, you may want to go figure out that stuff first, then come back here to the specifics.  I’m not an expert on these in general, so I’m not going to even try to do them justice with explanations here.  This approach does work well for me, I’m using it to monitor a service that checks for status changes on shipping containers. It looks like this:



Step 1: Add a reference to System.Runtime.Remoting to your Service project.  You also want to use the following namespaces in your .cs code:


using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Http;
using System.Runtime.Remoting.Channels.Tcp;


Step 2: Create a Serializable object that will be marshalled over the tcp channel. What I’ve done here create an object that contains the service information I want to monitor.  This class keeps information about how long the service has been running, how often it executes its checks, and an array of items that have info about each status check. It looks like this, sorta (I’ve simplified the code for this example).


[Serializable]
public class WatchListStatus
{
  
public
TimeSpan ExecutionInterval;
  
public
WatchListStatusItem [ ] StatusItems;
  
public
DateTime ServiceStarted;
}


[Serializable]
public class
WatchListStatusItem
{
  
public int
NumberEvents;
   public
DateTime CheckDateTime;
  
public
TimeSpan ExecutionTime;
  
public
WatchListCheckResult Result;
}


[Serializable]
public enum WatchListCheckResult
{
  
Successful,
  
FailedTimeOut,
  
FailedError
}


Step 3: Create a wrapper class that inherits from MarshalByRefObject.  This will be the remotable object. I’ve been calling these wrapper classes [wrapped-classname]Remotable for consistency. You can control the time-to-live for your object, by overriding the InitializeLifetimeService().  To make your object live for the life of the service process, return null here.


public class WatchListStatusRemotable : MarshalByRefObject
{
  
public
WatchListStatus ServiceStatus;
   
  
// Sets the time to live for this object. When this expires, the object will have to
   // be re-marshalled
  
public override
Object InitializeLifetimeService()
   {
    
return null
;
   }
}


Step 4: Add a private instance member object to your service class.  This is where the singleton model stuff becomes important.  You only want to have one instance of this object per service.

private
WatchListStatusRemotable m_Status;


Step 5: On – Startup of the service, marshal the object like so:


// Register the TCP Channel on port 8001
ChannelServices.RegisterChannel(new
TcpChannel(8001));

// Register the type

RemotingConfiguration.RegisterWellKnownServiceType (
        typeof
(WatchListStatusRemotable), 
        “WatchListStatus”, 
        WellKnownObjectMode.Singleton);

// Now, Marshal it  this will make it available to other processes via the TCP remoting channel
try 
{
     RemotingServices.Marshal(m_Status, “WatchListStatus”);
     System.Diagnostics.Trace.WriteLine(“Watch List Status Marshalled”);

catch
(System.Exception ex)
{
     System.Diagnostics.Trace.WriteLine(ex.Message);
     System.Diagnostics.Trace.WriteLine(ex.InnerException);
}


That’s it!  You can modify the object as the service does it’s thing and other processes that remote to this object will have access to this information.  All you have to do is consume it with a call to Activator.GetObject from your ASP.NET code. In part two, I’ll go into the details of how I did this in my app and how to control the service.


-Brendan


Music tip: Have I mentioned British Sea Power?

About Brendan Tompkins

Brendan runs CodeBetter.Com and Devlicio.Us. He is a former MVP for Microsoft .NET and is president of Port Technology Services, a partner with Port Solution Integrators a provider of hardware and software integration services for the transportation and logistics industry.
This entry was posted in ASP.NET Tutorials. Bookmark the permalink. Follow any comments here with the RSS feed for this post.
  • ahad zubair

    good work!

  • Brendan Tompkins

    Philip… There is a DataList in the System.Web.UI.WebControls namespace. You should be able to bind this to any object that implements System.Collections.IEnumerable

  • Philip_C

    Thanks a lot ! I thought it was another control cause i’m starting in designing ASP.Net pages.

    I’m searching tutorials to use DataList but i would like to know if i can use a DataList even if i’m not using any database as datasource. I just want to display data that i retrieve from my Windows Service as a string[][] array.

    Anyway, thanks again.

  • Brendan Tompkins

    Philip.

    The control you see is a System.Web.UI.WebControls.DataGrid, which you can bind directly to a DataSet or View.

  • Philip_C

    Hello! i thank you for this article very helpful and i would like to know how you’ve done your web control which picture is on the top of this page. Cause i’ve just learnt that it’s not possible to use a ListView control in an ASP.Net control or page. Though, your control on the picture seems very similar or close to a ListView, which i need !

    If you could tell me how to proceed to create a complex multicolumn list in C# it would be very nice or at least just a lead idea to do it.

    Thanks.