Search code examples
c#asp.net-coreconnection

How do you implement a custom ConnectionHandler for aspnetcore?


I have looked through samples in the github repo, but when i develop my process, i get "Connection ID required" when accessing the route that is mapped to a custom ConnectionHandler. My log message is never printed, nor do i land in the implementation with the debugger.

Startup:

        builder.Services.AddConnections();

        app.UseEndpoints(endpoints =>
        {
            endpoints.MapConnectionHandler<CustomDelegationHandler>("/proxy/{id}");
        });

Implementation:

public class CustomDelegationHandler : ConnectionHandler
{
    private readonly ILogger<CustomDelegationHandler> _logger;

    public CustomDelegationHandler(ILogger<CustomDelegationHandler> logger)
    {
        _logger = logger;
    }

    public override async Task OnConnectedAsync(ConnectionContext connection)
    {
        _logger.LogWarning("Connection incoming");

        while (true)
        {
            var result = await connection.Transport.Input.ReadAsync();
            var buffer = result.Buffer;
            try
            {
                if (!buffer.IsEmpty)
                {
                    var stream = new MemoryStream();
                    var data = buffer.ToArray();
                    await stream.WriteAsync(data, 0, data.Length);
                    stream.Position = 0;
                }
                else if (result.IsCompleted)
                {
                    break;
                }
            }
            finally
            {
                connection.Transport.Input.AdvanceTo(buffer.End);
            }
        }
    }
}

Solution

  • You need add the connection like below and it will map the custom ConnectionHandler:

    public async Task<IActionResult> Index()
    {
        var url = "https://localhost:yourPortNumber/proxy/1";
        var connection = new HttpConnection(new Uri(url));
        await connection.StartAsync();
    
        var bytes = Encoding.UTF8.GetBytes("aaaa");
        async Task SendMessage()
        {
            await connection.Transport.Output.WriteAsync(bytes);
        }
        // Send the receive concurrently so that back pressure is released
        // for server -> client sends
        await SendMessage();
        return View();
    }