Reading through here and looking at the example here:
I am trying to understand actually what the WebSocketAccept actually does. I know that WebSocketAccept is:
using WebSocketAccept =
Action
<
IDictionary<string, object>, // WebSocket Accept parameters
Func // WebSocketFunc callback
<
IDictionary<string, object>, // WebSocket environment
Task // Complete
>
>;
and is used in this manner:
public void Configuration(IAppBuilder app)
{
app.Use(UpgradeToWebSockets);
app.UseWelcomePage();
}
// Run once per request
private Task UpgradeToWebSockets(IOwinContext context, Func<Task> next)
{
WebSocketAccept accept = context.Get<WebSocketAccept>("websocket.Accept");
if (accept == null)
{
// Not a websocket request
return next();
}
accept(null, WebSocketEcho);
return Task.FromResult<object>(null);
}
So what is accept() actuallyt doing? Is it calling the Func<> property of the WebSocketAccept and a method WebSocketEcho is defined? WebSocketEcho is defined as:
private async Task WebSocketEcho(IDictionary<string, object> websocketContext)
So where does the websocketContext come from? What if we wanted to pass this further down the pipeline once we have identified it is a web socket request?
What is WebSocketAccept?
WebSocketAccept
is a using aliasExample:
Here we are using Bar from 2 different namespaces, but we alias the 2nd one with '
MyBar
' so we can differentiate between the two.Why use an alias as WebSocketAccept?
The alias in this case is just a convenience, so that you don't have to type the whole thing, which means that instead of writing the whole name when using it, you can use the alias instead.
Understanding WebSocketAccept
If we look closer we see that the type is:
This means that it is essentially a function that does not return and takes 2 arguments, in C# lambda:
We see that the 1st argument (A) is:
IDictionary<string, object>
, which is also known as the Owin environment.The 2nd argument is (B) is:
Func<C, D>
which means that it is a function that takes aC
and returns aD
. In C# lambda:We then need to dive into the 1st argument (C) of the 2nd argument (B). And we see that it takes an Owin environment and returns a
Task
.What is accept?
accept
tries to extract the parameters from theIOwinContext
and map them to theWebSocketAccept
type.If it can't extract them it is
null
and we proceed to the next middleware.Otherwise it was a websocket request and we call the function that takes 2 parameters (
WebSocketAccept
), as we discussed above (Action<A, B>
).The first parameter being an ordinary dictionary, which contains the websocket accept parameters.
The second parameter being a function that takes a dictionary and returns a task.
This function is called by someone else, what the code does, is pass the callback function along to the caller.
The caller then calls the function with the correct argument. Because the caller knows the signature of the function. The function is called AFTER accepting the websocket connection request. Hence the comment callback.
What if we wanted to pass this further down the pipeline once we have identified it is a web socket request?
Well in the example, the callback function is
WebSocketEcho
but essentially you could pass in any function, that satisfies the function signature of:The takeaway is that you don't call the function, the function is called for you. You specify that after negotiating the web socket request connection, you decide what happens.
The
WebSocketEcho
function is called once for every client, and loops until the client chooses to close the connection. Meanwhile it echo back whatever it receives.Disclaimer: I too am just trying to wrap my head around web sockets and owin, but I wanted to share my findings for posterity, since no one had answered your question. I welcome any corrections.
EDIT
I noticed with my own experiment, that if you return from the callback function that the
websocketContext
connection will beAbort
ed. Meaning you can't send/receive messages on the connection if you pass thewebsocketContext
around after ending the callback.UPDATE
Last time I tried to use this on a Windows 2008 R2 IIS 7.5 server I could not get the websocket to work. Then according to this: https://stackoverflow.com/a/14130152/1640121 - The IIS 7.5 server does not support websockets.
Which means that if your application is hosted in IIS 7.5 it would not be able to have websockets.
Then I thought about a possible solution:
This felt too cumbersome for me, which made me put aside implementing a websocket for now...