Blazor Server SignalR Chat works on Local, not on Azure

Viewed 210

I have a working Blazor Server application with a Chat component running locally correctly, using signal R hub connection.

When deploying to Azure, I receive error Invalid negotiation response received.---> System.Text.Json.JsonReaderException: '0x1F' is an invalid start of a value.

Here is a similar linked ticket, but it was never answered: Blazor Server SignalR hub fails on StartAsync due to Azure ADB2C

Goal: Create a private chat feature for Blazor server application. I am unable to use singleton service because all users cant share the same instance of the service.

I have yet to find a sample where there is a messaging feature between users/usergroups in blazor server.

Since I am using Azure B2C auth with OIDC default authentication scheme, I have to manually pass the cookies and the headers.

Like I mentioned, this sample is working perfectly on localhost, when I open up two browsers (one in incognito), i am able to send messages between logged in users. When I publish to Azure App Service, however, I am unable to connect to the hub.

Code:

private HubConnection _hubConnection;
private User user;
ObservableCollection<Message> messages = new ObservableCollection<Message>();
SfTextBox MessageBox;
SfTextBox SendTo;

public class Message
{
    public string Id { get; set; }
    public string UserName { get; set; }
    public string MessageText { get; set; }
    public string Chat { get; set; }
}

protected override async Task OnInitializedAsync()
{
    var state = await authenticationStateProvider.GetAuthenticationStateAsync();
    user = state.ToUser();
    _hubConnection = new HubConnectionBuilder()
        .WithUrl(navigationManager.ToAbsoluteUri("/chatHub"), options =>
        {
            options.UseDefaultCredentials = true;
            var httpContext = HttpContextAccessor.HttpContext;
            var cookieCount = httpContext.Request.Cookies.Count();
            var cookieContainer = new System.Net.CookieContainer(cookieCount);
            foreach (var cookie in httpContext.Request.Cookies)
                cookieContainer.Add(new System.Net.Cookie(
                cookie.Key,
                WebUtility.UrlEncode(cookie.Value),
                path: httpContext.Request.Path,
                domain: httpContext.Request.Host.Host));
            options.Cookies = cookieContainer;

            NameValueHeaderValue headers = null;
            foreach (var header in httpContext.Request.Headers)
            {
                if (header.Key != ":method")
                    options.Headers.Add(header.Key, header.Value);
            }
            options.HttpMessageHandlerFactory = (input) =>
            {
                var clientHandler = new HttpClientHandler
                    {
                        PreAuthenticate = true,
                        CookieContainer = cookieContainer,
                        UseCookies = true,
                        UseDefaultCredentials = true,
                    };

                return clientHandler;
            };
        })
 .WithAutomaticReconnect()
 .Build();

    _hubConnection.On<string, string, string, string>("ReceiveMessage", (userName, from, to, message) =>
    {
        if (user.Email == to || user.Id == from)
        {
            messages.Add(new Message()
                {
                    Id = Guid.NewGuid().ToString(),
                    MessageText = message,
                    Chat = user.Id == from ? "sender" : "receive",
                    UserName = user.Id == from ? "You" : userName
                });
            StateHasChanged();
        }
    });

    await _hubConnection.StartAsync();
}

public async void Send()
{
    if (MessageBox.Value != "" && SendTo.Value != "")
    {
        var userName = user.DisplayName;
        var to = SendTo.Value;
        var message = MessageBox.Value;
        var from = user.Id;
        _hubConnection.SendAsync("SendMessage", userName, from, to, message);
    }
}

public bool IsConnected => _hubConnection.State == HubConnectionState.Connected;

}

1 Answers
Related