I am very new to websockets and WebAPI (our system has been all .NET MVC, just not WebAPI), so I may very well just be missing something obvious (I hope).

I am attempting to implement a simple client to play around with. I am working in .NET in (sadly) VB, and I'm trying to just get the websocket working, and hitting the OnOpen/Message/Close events server and client side.

My code is below, but in short, the websocket handshake seems to happen without any issue, as my onOpen() event in the javascript gets hit, and when I output the readyState its 1. However OnOpen does NOT get hit server side

The output ends up looking like this:

IMMEDIATE READYSTATE: 0

ONOPEN READYSTATE: 1

Socket closed

The constructor for my WebSocketHandler is hit (for example if I throw a breakpoint on the MyBase.New() line, it hits it). However OnOpen is never hit, and the socket immediately hits the onclose event in the js.. is there something I should be doing to keep the socket open? Why would OnOpen not get hit?

My code is below:

Javascript:

var wsUri = 'ws://' + window.location.hostname + '/api/Chat?username=hello';
var output;

$(document).ready(function () {

  //setup and fire
  output = document.getElementById("output");
  testWebSocket();
})

function testWebSocket() {
  //Instantiate the websocket, hopefully opening it
  websocket = new WebSocket(wsUri);
  writeToScreen("IMMEDIATE READYSTATE: " + websocket.readyState);

  //bind event handlers
  websocket.onopen = function (evt) { onOpen(evt) };
  websocket.onclose = function (evt) { onClose(evt) };
  websocket.onmessage = function (evt) { onMessage(evt) };
  websocket.onerror = function (evt) { onError(evt) };
}

function onOpen(evt) {
  writeToScreen("ONOPEN READYSTATE: " + websocket.readyState);
  websocket.send("Websocket's open!")
}

function onClose(evt) {
  writeToScreen("Socket closed");
}

function onMessage(evt) {
  writeToScreen('RECEIVED: ' + evt.data);
}

function onError(evt) {
  writeToScreen('ERROR:' + evt.data);
}


function writeToScreen(message) {
  var messageToAppend = document.createElement("p");
  messageToAppend.style.wordWrap = "break-word";
  messageToAppend.innerHTML = '<span>' + message + '</span>';
  output.appendChild(messageToAppend);
}

Server:

Public Class ChatController
  Inherits ApiController

  Public Function [Get](username As String) As HttpResponseMessage

    If HttpContext.Current.IsWebSocketRequest Then
      HttpContext.Current.AcceptWebSocketRequest(Function() Tasks.Task.FromResult(New ChatWebSocketHandler(username)))
      Return Request.CreateResponse(HttpStatusCode.SwitchingProtocols)
    Else
      Return Request.CreateResponse(HttpStatusCode.BadRequest)
    End If
  End Function


  Private Class ChatWebSocketHandler
    Inherits Microsoft.Web.WebSockets.WebSocketHandler

    Public Sub New(username As String)

      MyBase.New()

      'Do stuff with username eventually.

    End Sub

    Public Overrides Sub OnOpen()
      Debug.WriteLine("Websocket is open")
    End Sub

    Public Overrides Sub OnMessage(message As String)
      Debug.WriteLine("Message Received: " & message)
    End Sub

    Public Overrides Sub OnClose()

      Debug.WriteLine("Websocket Closed")

      MyBase.OnClose()

    End Sub
  End Class

End Class
1

There are 1 best solutions below

0
On BEST ANSWER

To be honest, I cant say with 100% certainty what fixed this, but I have a very strong suspicion.

I was including too many namespaces in my code and I believe there was some confusion in the compiler etc when it actually ran. Apparently both Microsoft.Web.Websockets and SignalR's namespaces BOTH contain WebSocketHandler. While I dont know all the ins and outs of SignalR, it looks like WebSocketHandler in THAT namespace is not meant to be used outside of SignalR. I believe that class was being referenced instead of the one in Microsoft.Web.Websockets, as it works now, but I really didn't change too much. It also let me directly call the constructor by instantiating a new instance of the handler instead of having to call it in a lambda function.

Anyway, If anyone else has similar issues, make sure you're referencing the right one!