Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to catch ASP.NET Core 2 SignalR exceptions on server-side and handle them on client side with JavaScript?

Context: There are differences between ASP.NET SignalR and ASP.NET Core SignalR you can read here.

As described in this stackoverflow post in ASP.NET SignalR you can catch unhandled exceptions on server side via the HubPipelineModule which not exists in ASP.NET Core SignalR.

How can we catch unhandled exceptions and pass them to the client side in ASP.NET Core SignalR?

JavaScript code (client):

var hub = null;

var initWebSocket = function () {

    hub = new signalR.HubConnectionBuilder().withUrl("/MyHub").build();

    hub.on("ReceiveMessage", function (pMessage) {

        [...]
    });

    hub.start().catch(function (err) {
        return console.error(err.toString());
    });
};

var executeWebsocketTestException = function () {

    // send to server
    hub.invoke("TestException").catch(function (exception) {

        if(exception.type)
        {
            ...
        }
    });
};

ASP.NET Core 2 Hub (server):

public class MyHub : Hub
{
    public async Task TestException()
    {
        throw new SignalRTest.Exceptions.TestException("This is a Websocket Test Exception.");
    }
}
like image 991
Simon Avatar asked Nov 07 '18 13:11

Simon


2 Answers

In order to complement @Mohamed's answer and as per SignalR - Handle errors:

If you want to propagate the error to the client, you can use the HubException class. If you throw a HubException from your hub method, SignalR will send the entire message to the client, although it will include just the exception message, not the inner exception, stack trace or other properties.

public Task ThrowException()
{
    throw new HubException("This error will be sent to the client!");
}
like image 148
brunochaina Avatar answered Oct 20 '22 05:10

brunochaina


Summary

  • I could't and I'm not aware of direct replica

  • but you can use this hack to send the exception

  • for simplicity I didn't use a custom Hub class , but you can.

  • or you can use move it to standalone method

Solution

Hubs\MyHub.cs

public class MyHub : Hub
{ 
    public void test_exception()
    {
        try
        {
            var x = 0;
            var d = 1 / x;
        }
        catch (Exception ex)
        {
            // log or extra
            Clients.Caller.SendAsync("handle_exception", ex);
        }
    }
}

wwwroot\js\app1.js

"use strict";

var connection = new signalR.HubConnectionBuilder().withUrl("/MyHub").build();

connection.start();

connection.on("handle_exception", function (err) {
    if (err.ClassName === "System.DivideByZeroException") {
        alert("You need to take a math class 😊");
    }
});

document.getElementById("test_btn")
    .addEventListener("click", function (event) {
        connection.invoke("test_exception");
        event.preventDefault();
});

Pages/Index.cshtml

@page
<p/><p/>
<input type="button" id="testExceptionButton" value="TestException" />
<script src="~/lib/signalr/dist/browser/signalr.js"></script>
<script src="~/js/app1.js"></script>

Screenshot

]


Extra :

  • you can add global Server-side logging

    • Logging and diagnostics in ASP.NET Core SignalR | Microsoft Docs

      public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
          WebHost.CreateDefaultBuilder(args)
              .ConfigureLogging(logging =>
              {
                  logging.
                  AddFilter(
                   "Microsoft.AspNetCore.SignalR",
                   LogLevel.Debug);
                  logging.
                  AddFilter(
                   "Microsoft.AspNetCore.Http.Connections",
                   LogLevel.Debug);
              })
              .UseStartup<Startup>();
      

Ref.

  • Get started with ASP.NET Core SignalR | Microsoft Docs

  • HubException Class (Microsoft.AspNetCore.SignalR) | Microsoft Docs

  • HubException Constructor (Microsoft.AspNetCore.SignalR) | Microsoft Docs

like image 30
Mohamed Elrashid Avatar answered Oct 20 '22 04:10

Mohamed Elrashid