Click here to Skip to main content
15,886,519 members
Articles / Web Development / HTML
Tip/Trick

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

Rate me:
Please Sign up or sign in to vote.
4.78/5 (2 votes)
13 Oct 2015CPOL2 min read 13.5K   80   4  
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.

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

JavaScript
<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.

C#
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.

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

C#
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, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Australia Australia
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
-- There are no messages in this forum --