Troubleshooting ASP.NET SignalR Applications - Pro ASP.NET SignalR: Real-Time Communication in .NET with SignalR 2.1 (2014)

Pro ASP.NET SignalR: Real-Time Communication in .NET with SignalR 2.1 (2014)

Chapter 5. Troubleshooting ASP.NET SignalR Applications

Chapter 1 gave you some background information about real-time web and SignalR. Chapter 2 was a quick start to ASP.NET SignalR, and in Chapters 3 and 4 you discovered two important methods for building ASP.NET SignalR applications: hubs and persistent connections.

These two concepts are sufficient to get most of the common jobs done with ASP.NET SignalR, but that’s in a perfect world. In practice, we often face issues when we write programs, and there are several other topics that we encounter for scaling up and out, and for deploying to different environments. In the current chapter and the rest of this book, we focus on topics that target different aspects of such problems to give you more practical knowledge about building real ASP.NET SignalR applications.

This chapter is all about one of the main phases of developing any type of software: troubleshooting—in other words, debugging and testing. You need to debug and test almost any program that you write, regardless of its size. This process can be easier for smaller programs that run on a single environment such as console applications because you can easily see the output and can use many debugging features such as breakpoints.

However, the world is not always that simple, and there are often more difficult cases to deal with. One example is the case for client-server applications such as those we build with ASP.NET SignalR. The whole program execution is distributed among two independent components that execute in two different contexts (and most likely different environments or machines): server and client. Debugging such programs requires more efforts and needs better tooling support.

This chapter goes through common techniques and tools for debugging the server and client components of ASP.NET SignalR and discusses the common issues that you might face during the development of an ASP.NET SignalR application.

Here is a brief list of the major topics covered in Chapter 5:

· General process of troubleshooting an ASP.NET SignalR application

· How to use Chrome Developer Tools to debug the client-side execution of an application and JavaScript or jQuery issues

· How to use Fiddler to troubleshoot client-to-server (and server-to-client) communications

· How to troubleshoot the server-side execution of an application

· How to enable tracing in ASP.NET SignalR

· Common issues with ASP.NET SignalR applications

ASP.NET SignalR Troubleshooting Overview

There is no silver bullet for troubleshooting an ASP.NET SignalR application (or any server-client application for that matter) because there are different independent pieces that are working together, executing in different contexts, and even running on different machines to debug. Therefore, the whole idea of troubleshooting a SignalR application requires some experience and following general guidelines.

Here we outline a general list of areas to be checked in order to troubleshoot an ASP.NET SignalR application (although you might want to look only into a subset of these items and not necessarily follow them in order):

· JavaScript errors on the client (using debugging tools such as Chrome Developer Tools or others)

· Communication issues from the client to the server or vice versa (using HTTP debugging tools such as Fiddler)

· Server-side issues (using Visual Studio debugging features)

· Trace logs for any invisible or silent problem (using the tracing mechanisms provided in ASP.NET SignalR and Visual Studio outputs)

These steps might need to be followed in conjunction with each other. For example, if server-side debugging is needed, there is a high probability that corresponding JavaScript debugging and client-side actions are also needed.

The rest of the chapter discusses more details about each of these items.

Image Note Although we try to cover the common troubleshooting process and development tools for .NET developers such as Google Chrome Developer Tools, Fiddler, and Visual Studio, there are alternative tools available to use for the same purposes. The functionality and features of such tools are often very similar to tools discussed here (we chose the most popular and common tools for discussion), so it is worth reading this chapter to know how to use other tools.

Using Chrome Developer Tools for Client-Side Debugging

Common issues with ASP.NET SignalR applications are generated on the client side because of the lack of data coming from the server blowing up the JavaScript functionality, incorrect data coming from the server, or even a logic problem in the client JavaScript code.

In any case, we need to debug the JavaScript code to find out what is wrong in order to take the correct action. With the fast-growing and common uses of JavaScript in software development, there have been many tools developed to simplify JavaScript debugging. Historically, it has been tricky and sometimes challenging to debug JavaScript code. These obstacles come from the nature of this language, which is different from other programming languages (although it also runs in a browser).

Regardless, quite a few tools are used by developers to debug JavaScript; it has been a need that has led browser builders to integrate very rich JavaScript debugging tools with the recent versions of all the major browsers such as Google Chrome, Mozilla Firefox (it comes as an extension), and Microsoft Internet Explorer.

Not only do these browsers come with a good JavaScript debugger but they also support other tracing capabilities such as network access to resources, HTML and CSS code viewing, and profiling, among others. These tools allow you to view, test, and debug your HTML, CSS, and JavaScript for different browser versions to ensure that your application renders correctly on all the major browsers for all the recent versions.

Chrome Developer Tools (see Figure 5-1), Firefox Firebug (see Figure 5-2), and Internet Explorer Developer Tools (see Figure 5-3) are mentioned here. In this chapter, we focus on using Google Chrome Developer Tools because it is more popular among web developers and also provides a slightly richer set of debugging features that are easier to use. The use of other tools is very similar.

image

Figure 5-1. Example of Google Chrome Developer Tools

image

Figure 5-2. Example of Firefox Firebug

image

Figure 5-3. Example of Microsoft Internet Explorer Developer Tools

In this section, we focus on Google Chrome Developer Tools and give you a quick overview of how to use it to debug possible client–side JavaScript errors in ASP.NET SignalR.

First, we create a simple ASP.NET SignalR application with hubs. It is a very basic message-broadcasting application that shows some common scenarios. (We described the details about developing such an application in Chapter 3.) The code for the BroadcastHub class implementation is shown in Listing 5-1.

Listing 5-1. Broadcast Hub Implementation

using Microsoft.AspNet.SignalR;

namespace Chapter5.Controllers
{
public class BroadcastHub : Hub
{
public void BroadcastMessage(string message)
{
Clients.All.sendMessage(message);
}
}
}

For this application, we avoided starting up the hosting environment so the JavaScript reference to the dynamic hubs proxy failed to access this resource. A JavaScript error was introduced that we can detect and debug. But first, we have to write the client-side code presented in Listing 5-2.

Listing 5-2. Client-Side Implementation of the Broadcast Application

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title></title>
</head>
<body>
<script src="Scripts/jquery-1.6.4.js"></script>
<script src="Scripts/jquery.signalR-2.0.0-rc1.js"></script>
<script src="/signalr/hubs" type="text/javascript"></script>

<script type="text/javascript">
$(function () {
var broadcaster = $.connection.broadcastHub;

broadcaster.client.displayText = function (text) {
$('#messages').append('<li>' + text + '</li>');
};

$.connection.hub.start().done(function () {
$("#broadcast").click(function () {
broadcaster.server.broadcastMessage($('#msg').val());
});
});
});
</script>

<div>
<input type="text" id="msg" />
<input type="button" id="broadcast" value="Broadcast" />

<ul id="messages">
</ul>
</div>
</body>
</html>

If we run this application in Google Chrome, we don’t get the expected behavior. At this point, if we open Google Chrome Developer Tools and navigate to the Console tab, the JavaScript errors can be seen (see Figure 5-4).

image

Figure 5-4. JavaScript error for dynamic hub proxy

As shown in the figure, the top error suggests that the JavaScript reference to the dynamic hubs proxy is throwing a 500 HTTP status error, which suggests a server error because the hosting is not set correctly. The second error is a side effect of the first one, and because the dynamic proxy is not loaded correctly, the client property of that proxy cannot be loaded, either.

You can find the name of the resource file and line number on the right side of each error line where that error is happening. By clicking this link, you are navigated to the actual source code at the location in which it is happening in the Sources tab (see Figure 5-5). This tab has more information about the error to help you debug the problem.

image

Figure 5-5. Source of JavaScript errors in Google Chrome Developer Tools

Now let’s focus on another scenario in which we want to actually see the values being communicated between client and server, and vice versa. This scenario requires the use of breakpoints in JavaScript, and Google Chrome Developer Tools comes with a handy set of features to simplify it.

Let’s assume that we want to debug the existing code and find out what message is sent from the server to clients with broadcasting. To detect it, we need to insert a breakpoint inside the displayText function callback in JavaScript (see Listing 5-3).

Listing 5-3. Code to Insert a JavaScript Breakpoint

broadcaster.client.displayText = function (text) {
$('#messages').append('<li>' + text + '</li>');
};

By running the application and going to Google Chrome Developer Tools and then to the Sources tab, we can find the JavaScript code in the HTML file. By clicking the left column next to the line of code, we can insert a breakpoint (see Figure 5-6). This mechanism is very similar to the breakpoint system in Visual Studio.

image

Figure 5-6. Inserting a JavaScript breakpoint in Google Chrome Developers Tools

After executing the code and entering a message to broadcast, the code stops at this line and enables us to view the value of a variable by moving the cursor over the variable name (see Figure 5-7).

image

Figure 5-7. Debugging variable values in Google Chrome Developers Tools

As shown in the figure, it is easy to pause and continue the execution, add variables to a watch list, and check the call stack on the right column of Google Chrome Developer Tools.

This set of features (along with many more that can be discovered by reading the documentation available at https://developers.google.com/chrome-developer-tools and following the process) can be used to troubleshoot any problematic circumstance with JavaScript client code for ASP.NET SignalR applications. If other client types are used (such as iOS, Android, or Windows Desktop), similar troubleshooting features exist to assist you with diagnosing them.

Besides the debugging features, Google Chrome Developer Tools offers the Network tab, which allows us to retrieve helpful information about the resources being requested by the client during execution. (You learn about debugging the client-to-server communication in the next section.) Figure 5-8 shows a general overview of this tab.

image

Figure 5-8. Networks tab in Google Chrome Developer Tools

The figure shows all the network requests made by the client (including any long-polling connections). The requests made by the ASP.NET SignalR library are highlighted, and there is an initiator column that shows which part of the code each resource is requesting. There are also some reporting numbers about the time that it takes for a resource to be retrieved as well as an HTTP status code that helps to determine and diagnose the application’s health.

Using Fiddler for Client-to-Server Communication Debugging

The other aspect of any server-client application, including SignalR applications, is the communication between client to server and server to client that is a very critical point of the whole architecture (everything fails if this communication hub is broken).

There are several tools and methods that can be used to debug and trace this communication for ASP.NET SignalR. Generally speaking, any HTTP debugging tool can assist us in this area, but most .NET developers agree that the most popular tool in the Microsoft (and even non-Microsoft) communities is Fiddler (http://fiddler2.com).

Fiddler was developed as a pet project by Eric Lawrence when he was working at Microsoft. It was acquired by Telerik, and Eric was hired to dedicate his time to advancing the tool features. Telerik Fiddler, which has been a very handy tool for developers for many years, enables you to easily test and trace communication requests on different protocols on your machine.

Although we focus on Fiddler, there are many other tools available for achieving the same goal. All browser debuggers (such as Google Chrome Developer Tools) provide some kind of features for this purpose. Charles is a good example of a similar tool for the Apple community.

Let’s take a look at the Fiddler output when we run our example from the previous section and enter a text to broadcast (see Figure 5-9).

image

Figure 5-9. Fiddler output for the example program

In the left pane, you see a list of resources requested by the application, including the request to the static HTML page, jQuery file, and dynamic ASP.NET SignalR hub proxy library.

After these requests comes the negotiation call, which is followed by connect, send, and abort steps that are necessary for ASP.NET SignalR to work (discussed later). The abortion step comes when we close the browser or move away from the page and try to end the connection with the server.

On this page you see information about these requests, including the result status code, protocol used, hostname, URL, body size, content type, and other valuable information. The right pane is for details about each of these requests. For example, the Statistics tab shown in Figure 5-10displays the details for one of the connect steps.

image

Figure 5-10. Fiddler request details

The details pane is split into a few tabs categorized by the type of information needed for each request. Some of these tabs are split into two horizontal panes as well to let you view more details. The Statistics tab gives general statistics about the request and response such as the protocol used, the execution time, size, and so on.

The handiest tab for troubleshooting ASP.NET SignalR applications is the Inspectors tab, which enables you to view the actual request and response headers and data in several formats.

Figure 5-11 shows the request and response for the connect request discussed previously.

image

Figure 5-11. Request and response details

This pane has some valuable details about the request and response. One interesting part of this data is the URL requested with a GET verb that shows some of the details about the request, such as the type of transport used. It is very helpful to see the actual data being communicated between server and client to find where the communication failed.

Debugging the Server-Side Execution

The server component of ASP.NET SignalR is very similar to a typical ASP.NET application, in which you can set up breakpoint in Visual Studio and use other debugging features to test program execution. It can be used in conjunction with the previous approaches used to debug the client–side JavaScript code as well as in client-to-server communication.

Image Note For further information on how to debug an ASP.NET application, see Pro ASP.NET 4 in C# 2010, by Matthew MacDonald and Adam Freeman (Apress 2010), or any similar title on ASP.NET or C# development and debugging.

We don’t want to repeat what you already know about Visual Studio debugging, so we don’t go into more detail. We assume that you are already familiar with debugging features and techniques in Visual Studio.

Tracing Features

One great feature available in ASP.NET SignalR is the capability to trace many things on the server side to know what is exactly going on with clients. As discussed in Chapter 3, you can enable tracing features in ASP.NET SignalR by adding certain elements to your Web.Config file or editing your application configuration in IIS.

Here we discuss tracing features in ASP.NET SignalR because they assist in debugging applications much more easily, especially by looking at what is happening on the server side for each and every client. The bold code in Listing 5-4 is all the code needed to enable the tracing capabilities on a server in an ASP.NET SignalR application. (Although this code enables the whole tracing functionality, you usually don’t need all the elements.)

Listing 5-4. Enable Tracing in ASP.NET SignalR

<?xml version="1.0" encoding="utf-8"?>
<!--
For more information on how to configure your ASP.NET application, please visit
http://go.microsoft.com/fwlink/?LinkId=169433
-->
<configuration>
<appSettings>
<add key="webpages:Version" value="2.0.0.0" />
<add key="webpages:Enabled" value="false" />
<add key="PreserveLoginUrl" value="true" />
<add key="ClientValidationEnabled" value="true" />
<add key="UnobtrusiveJavaScriptEnabled" value="true" />
</appSettings>
<system.web>
<httpRuntime targetFramework="4.5" />
<compilation debug="true" targetFramework="4.5" />
<pages>
<namespaces>
<add namespace="System.Web.Helpers" />
<add namespace="System.Web.Mvc" />
<add namespace="System.Web.Mvc.Ajax" />
<add namespace="System.Web.Mvc.Html" />
<add namespace="System.Web.Routing" />
<add namespace="System.Web.WebPages" />
</namespaces>
</pages>
</system.web>
<system.webServer>
<validation validateIntegratedModeConfiguration="false" />
<handlers>
<remove name="ExtensionlessUrlHandler-ISAPI-4.0_32bit" />
<remove name="ExtensionlessUrlHandler-ISAPI-4.0_64bit" />
<remove name="ExtensionlessUrlHandler-Integrated-4.0" />
<add name="ExtensionlessUrlHandler-ISAPI-4.0_32bit" path="*." verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness32" responseBufferLimit="0" />
<add name="ExtensionlessUrlHandler-ISAPI-4.0_64bit" path="*." verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework64\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness64" responseBufferLimit="0" />
<add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
</handlers>
</system.webServer>
<system.diagnostics>
<trace autoflush="true" indentsize="4">
<listeners>
<add name="default_traces" type="System.Diagnostics.TextWriterTraceListener" initializeData="default_traces.txt" />
</listeners>
</trace>
<switches>
<add name="SignalRSwitch" value="All" />
</switches>
<sources>
<source name="Application" switchValue="All">
<listeners>
<add name="traces" />
</listeners>
</source>
<source name="Microsoft.Owin.Host.SystemWeb" switchValue="All">
<listeners>
<add name="traces" />
</listeners>
</source>
<source name="SignalR.Connection">
<listeners>
<add name="traces" />
</listeners>
</source>
<source name="SignalR.PersistentConnection">
<listeners>
<add name="traces" />
</listeners>
</source>
<source name="SignalR.HubDispatcher">
<listeners>
<add name="traces" />
</listeners>
</source>
<source name="SignalR.Transports.WebSocketTransport">
<listeners>
<add name="traces" />
</listeners>
</source>
<source name="SignalR.Transports.ServerSentEventsTransport">
<listeners>
<add name="traces" />
</listeners>
</source>
<source name="SignalR.Transports.ForeverFrameTransport">
<listeners>
<add name="traces" />
</listeners>
</source>
<source name="SignalR.Transports.LongPollingTransport">
<listeners>
<add name="traces" />
</listeners>
</source>
</sources>
<sharedListeners>
<add name="traces" type="System.Diagnostics.TextWriterTraceListener" initializeData="server_traces.txt" />
</sharedListeners>
</system.diagnostics>
</configuration>

This code consists of some switches, listeners, and sources that help you trace different sources of information in an application. These are some concepts in the .NET Framework for the diagnostics features. If you’re not familiar with them, take a look at MSDN documentation and other online sources to understand what they do.

ASP.NET SignalR has implemented these sources by default and has simplified the process for developers to enable tracing to diagnose application problems.

Here is a brief list of different sources that are self-explanatory by name:

· Application

· Microsoft.Owin.Host.SystemWeb

· SignalR.Connection

· SignalR.PersistentConnection

· SignalR.HubDispatcher

· SignalR.Transports.WebSocketTransport

· SignalR.Transports.ServerSentEventsTransport

· SignalR.Transports.ForeverFrameTransport

· SignalR.Transports.LongPollingTransport

Figure 5-12 shows the output when we run our example on two browsers to broadcast messages.

image

Figure 5-12. Tracing output

As shown in the figure, there are two connections established from two different browsers, and the previous connections are dropped. On the left side of each tracing line, you see the name of the source that is generating the output.

If a request by a client gets to the server but fails to be processed, and you cannot find any appropriate exception using your debugging features, the good news is that such an exception should show up with details in the Output window.

Summary

This chapter discussed the important topic of debugging and tracing ASP.NET SignalR applications. These are essential steps of developing any SignalR application and can be complicated due to the server-client nature of ASP.NET SignalR.

We discussed the client-side JavaScript debugging of applications using browser tools, especially Google Chrome Developers Tools; then discussed the debugging of the communication bridge between client(s) and server using HTTP debugging tools, particularly Telerik Fiddler. Next was a brief discussion on debugging the server-side execution of applications.

You saw the helpful feature in ASP.NET SignalR that traces the server-side execution, and the chapter concluded with a discussion of the custom performance counters bundled with ASP.NET SignalR to monitor its performance.

Some common principles, tools, and techniques for debugging and tracing were discussed, and it is important to note that these tasks vary significantly by circumstance. Depending on your situation, you have to use your experience, skills, and these principles to take the appropriate actions.