Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Using SignalR to Show Server-side Trace Messages in a SPA

0.00/5 (No votes)
13 Oct 2015 1  
This tip shows how SignalR can be used to show Trace messages in real-time fashion in the browser to trace and debug a Single Page Application.

Introduction

In this tip, I show how you can use SignalR to transfer server-side log and trace messages to an HTML client side. This can help to create a centralized and easy log facility that is necessary to debug complex systems.

Background

In this tip, I also provide a class that will dump all HTTP interactions into Trace, which then will be shown in our SignalR client in the browser. In the real world, you probably would like to filter to include only some requests. For example, WebAPI calls from your SPA to the server.

To run the code, you will need Nuget packages required to build a SignalR application in ASP.NET. You can check the repositories file in the provided source to see what I have been using.

Using the Code

The code has these components:

  1. An HTML & JavaScript bit to show incoming messages from SignalR
  2. Codes to create SignalR Hub in the server-side
  3. A TraceListener to listen to all Trace writes, which we add to Listeners in Global.asax
  4. A HTTP Module that puts all HTTP actions into Trace by decorating the stream in each HTTP request lifecycle

Now, let's look at the important bits of each component.

I have created a SignalrLog JavaScript type which is defined like this (I removed the DOM manipulation so you can see what is happening here.

var SignalrLog = (function () {
    function SignalrLog(element) {
        this.Element = element;
        this.Ul = document.createElement("ul");
        this.Element[0].appendChild(this.Ul);

    }
    SignalrLog.prototype.Start = function () {
        var parent = this;
        var hub = $.connection.serviceSpyHub;
        var ul = this.Ul;
        var e = this.Element;

        hub.client.clientSideCall = function (msg) {
            //.... We create Html elements and add to DOM here

        };

        $.connection.hub.start()
        .done(function () {

              //.........We add a 'Clear' and 'Ping' button here and add 'click' listeners to them
        })
        .fail(function (e) {
            //...........Error Handling
        });

    };
    return SignalrLog;

})();

Note how we set the hub.client.clientSideCall. Here, clientSideCall is the method that we will call from server side.

Now, in our _Layout.cshtml, after making sure I have reference to my JavaScript file, I add this:

<script>
    $(function(){
            var log1 =new SignalrLog($("#EmbededLog"));
            log1.Start();
        });
</script>

which is going to nominate a div with id of EmbededLog for our logs. You can have that div as a popup or in an iFrame.

Then we do our serverside code. The code is a quite standard SignalR setup that you can find in any SignalR tutorial. This is the Hub definition. As you probably know, the ServerSideCall and ClientSideCall methods are going to be exposed in camel-case in JavaScript.

public class ServiceSpyHub : Hub
{

    public ServiceSpyHub()
    {

    }
    public void ServerSideCall(string msg)
    {
        var user = HttpContext.Current.User.Identity;
        var machine = Environment.MachineName;

        Clients.All.ClientSideCall("("+machine+"):"+ msg);
    }
}

Then I have created a TraceListener that invokes the Hub's method.

public class MemoryTraceListener : System.Diagnostics.TraceListener
{
    public MemoryTraceListener()
    {
    }
    public override void Write(string message)
    {
        WriteToHub(message);
    }

    public override void WriteLine(string message)
    {
        WriteToHub(message);
    }

    private void WriteToHub(string msg)
    {
        var hubContext = GlobalHost.ConnectionManager.GetHubContext<ServiceSpyHub>();
        hubContext.Clients.All.ClientSideCall("( Trace):" + msg);
    }
}

I have added this listener to the list of listeners in Global.asax code like this:

protected void Application_Start()
{
  System.Diagnostics.Trace.Listeners.Add(new MemoryTraceListener());

This is actually all you need to start seeing your Trace messages in client side. But to make this really useful, you should start putting useful information into your Trace. For example, you may want to know what REST API calls your SAP does to the server and see them real-time in client-side. You can achieve that by creating a custom HttpModule that looks into HTTP requests getting processed and collects the information for you and puts them in Trace. In the attached code, I am putting every Response text into the Trace using my Module implementation.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here