← Back to SignalR/SignalR

How to Deploy & Use SignalR/SignalR

ASP.NET SignalR Deployment & Usage Guide

⚠️ Maintenance Mode Notice: ASP.NET SignalR is in maintenance mode. No new features will be added. This guide applies to .NET Framework applications only. For new projects using .NET Core/.NET 5+, use ASP.NET Core SignalR.

1. Prerequisites

Development Environment

  • .NET Framework 4.5 or higher (required for SignalR 2.x)
  • Visual Studio 2017 or later (VS 2022 recommended for compatibility)
  • IIS 7.5 or higher with WebSocket Protocol enabled (for WebSocket transport support)
  • NuGet Package Manager (included with Visual Studio)
  • Git (for source builds only)

Runtime Requirements

  • Windows Server 2012+ or Windows 10/11 (for server deployment)
  • Full .NET Framework (not .NET Core/.NET 5+)
  • For self-hosting: OWIN compatible host

Optional for Scale-Out

  • SQL Server 2008+ (for SQL Server backplane)
  • Redis 2.6+ (for Redis backplane)
  • Azure Service Bus (for cloud scale-out)

2. Installation

Option A: NuGet Package Installation (Recommended)

Install the server package in your ASP.NET web application:

Install-Package Microsoft.AspNet.SignalR

Install the client package in your client application (WPF, Console, Web, etc.):

Install-Package Microsoft.AspNet.SignalR.Client

Install the official sample to explore features:

Install-Package Microsoft.AspNet.SignalR.Sample

Option B: Building from Source

For contributors or custom builds:

# Clone the repository
git clone https://github.com/SignalR/SignalR.git
cd SignalR

# Build (Windows only)
build.cmd

Note: The solution requires Visual Studio 2017 or later to open. The build script handles NuGet package restoration automatically.

3. Configuration

OWIN Startup Configuration

Create or modify Startup.cs in your web application root:

using Microsoft.AspNet.SignalR;
using Microsoft.Owin;
using Owin;

[assembly: OwinStartup(typeof(YourNamespace.Startup))]

public class Startup
{
    public void Configuration(IAppBuilder app)
    {
        // Basic SignalR configuration
        var config = new HubConfiguration
        {
            EnableDetailedErrors = true, // Set false in production
            EnableJavaScriptProxies = true,
            Resolver = new DefaultDependencyResolver()
        };

        app.MapSignalR(config);
    }
}

Web.config Settings

Add or verify these settings in Web.config:

<system.webServer>
  <handlers>
    <!-- Ensure SignalR handlers are not blocked -->
    <remove name="WebDAV" />
    <add name="SignalR" path="signalr/hubs" verb="*" type="Microsoft.AspNet.SignalR.Hubs.HubDispatcher" />
  </handlers>
  <security>
    <requestFiltering>
      <hiddenSegments>
        <remove segment="bin" />
      </hiddenSegments>
    </requestFiltering>
  </security>
</system.webServer>

<system.web>
  <httpRuntime targetFramework="4.5" />
  <compilation debug="true" targetFramework="4.5" />
</system.web>

Transport Configuration

To force specific transports or configure timeouts, modify HubConfiguration:

var config = new HubConfiguration
{
    // Transport timeout settings
    EnableJSONP = true, // For cross-domain support
    // Note: Transport selection is typically handled client-side
};

Scale-Out Configuration (Redis Example)

Install the Redis package:

Install-Package Microsoft.AspNet.SignalR.Redis

Configure in Startup.cs:

GlobalHost.DependencyResolver.UseRedis("server", port, "password", "SignalRApp");

4. Build & Run

Local Development with IIS Express

  1. Create a Hub:
public class ChatHub : Hub
{
    public void Send(string name, string message)
    {
        Clients.All.broadcastMessage(name, message);
    }
}
  1. Create Client Page (index.html):
<!DOCTYPE html>
<html>
<head>
    <script src="Scripts/jquery-3.6.0.min.js"></script>
    <script src="Scripts/jquery.signalR-2.4.3.min.js"></script>
    <script src="/signalr/hubs"></script>
</head>
<body>
    <script>
        $(function () {
            var chat = $.connection.chatHub;
            chat.client.broadcastMessage = function (name, message) {
                console.log(name + ': ' + message);
            };
            $.connection.hub.start().done(function () {
                chat.server.send('System', 'Connected');
            });
        });
    </script>
</body>
</html>
  1. Run: Press F5 in Visual Studio (IIS Express) or run:
# If using full IIS
iisexpress /path:"C:\path\to\your\app" /port:8080

Self-Hosting (Console/Windows Service)

For desktop applications or Windows Services:

using Microsoft.Owin.Hosting;
using Microsoft.AspNet.SignalR;
using System;

class Program
{
    static void Main(string[] args)
    {
        string url = "http://localhost:8080";
        using (WebApp.Start<Startup>(url))
        {
            Console.WriteLine($"Server running at {url}");
            Console.ReadLine();
        }
    }
}

public class Startup
{
    public void Configuration(IAppBuilder app)
    {
        app.MapSignalR();
    }
}

Note: Self-host requires running with administrator privileges or reserving the URL:

netsh http add urlacl url=http://+:8080/ user=DOMAIN\Username

5. Deployment

IIS Deployment (Traditional)

  1. Publish from Visual Studio: Right-click project → Publish → File System
  2. Configure IIS:
    • Create Application Pool running .NET CLR Version 4.0
    • Enable WebSocket Protocol (Server Manager → Add Roles and Features)
    • Set Application Request Routing (ARR) if using load balancer
  3. Web.config Production Settings:
<configuration>
  <system.web>
    <customErrors mode="RemoteOnly" />
    <compilation debug="false" targetFramework="4.5" />
  </system.web>
</configuration>

Azure Web Apps (Classic)

  1. Deploy via Git, FTP, or Web Deploy
  2. Enable WebSockets: Azure Portal → App Service → Configuration → General Settings → Web sockets: On
  3. ARR Affinity: Disable for SignalR (stateless) unless using sticky sessions for other reasons
  4. Scale-Out: Use Azure Service Bus or Redis backplane for multiple instances

Windows Service Deployment

  1. Create a Windows Service project
  2. Install the OWIN self-host package:
Install-Package Microsoft.Owin.Host.HttpListener
Install-Package Microsoft.Owin.Hosting
  1. Install the service using sc.exe or Topshelf:
sc create SignalRService binPath= "C:\path\to\your\service.exe"

Performance Counter Considerations

SignalR installs performance counters on first run. For production servers:

  • Ensure the application pool identity has permissions to create performance counter categories, OR
  • Run the application once as Administrator to initialize counters, OR
  • Disable performance counters if not needed:
var config = new HubConfiguration
{
    Resolver = new DefaultDependencyResolver()
};
// Replace PerformanceCounterManager with no-op
config.Resolver.Register(typeof(IPerformanceCounterManager), () => new NoOpPerformanceCounter());

6. Troubleshooting

Connection Issues

Symptom: 404 errors on /signalr/hubs or /signalr/negotiate

  • Solution: Verify OWIN Startup class is discoverable. Check that Microsoft.Owin.Host.SystemWeb is installed for IIS hosting:
Install-Package Microsoft.Owin.Host.SystemWeb

WebSocket Transport Fails

Symptom: Client falls back to Server-Sent Events or Long Polling

  • IIS: Ensure WebSocket Protocol is installed (Control Panel → Programs → Turn Windows features on or off → IIS → Application Development Features → WebSocket Protocol)
  • Azure: Enable WebSockets in Portal (see Deployment section)
  • Proxy: Check that intermediate proxies support WebSocket upgrade

Cross-Domain Issues

Symptom: CORS errors in browser console

  • Solution: Install OWIN CORS package and configure:
Install-Package Microsoft.Owin.Cors
app.UseCors(CorsOptions.AllowAll);
app.MapSignalR();

Version Mismatch

Symptom: "Protocol error" or negotiation failures

  • Solution: Ensure client and server versions match. Check jquery.signalR-{version}.js matches the server assembly version (2.4.x).

Performance Counter Errors

Symptom: "Access denied" or "Category does not exist" in logs

  • Solution: Run as Administrator once to initialize, or disable counters (see Configuration section). This is common on locked-down production servers.

Memory Leaks in Long-Running Processes

Symptom: Memory growth in self-hosted services

  • Solution: Ensure proper disposal of HubConnection on client side. On server, verify IConnection objects are being cleaned up after disconnect timeout (default 30 seconds).

Load Balancer Issues

Symptom: Random disconnections with multiple servers

  • Solution: Configure a backplane (Redis, SQL Server, or Service Bus). Without sticky sessions, SignalR requires a backplane to synchronize across instances.

Debug Logging

Enable detailed tracing in Web.config:

<system.diagnostics>
  <sources>
    <source name="Microsoft.AspNet.SignalR" switchValue="Verbose">
      <listeners>
        <add type="System.Diagnostics.DefaultTraceListener" />
        <add name="SignalRListener" />
      </listeners>
    </source>
  </sources>
  <sharedListeners>
    <add name="SignalRListener" type="System.Diagnostics.TextWriterTraceListener" initializeData="signalr.log" />
  </sharedListeners>
</system.diagnostics>