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?
WebSocketAccept
is a using alias
Example:
...
using Foo.Bar
using MyBar = Fee.Bar
...
Here we are using Bar from 2 different namespaces, but we alias the 2nd one with 'MyBar
' so we can differentiate between the two.
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.
If we look closer we see that the type is:
Action<A, B>
This means that it is essentially a function that does not return and takes 2 arguments, in C# lambda:
(A, B) => { }
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 a C
and returns a D
. In C# lambda:
(C) => { return D; }
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
.
accept
tries to extract the parameters from the IOwinContext
and map them to the WebSocketAccept
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.
Well in the example, the callback function is WebSocketEcho
but essentially you could pass in any function, that satisfies the function signature of:
Task MyCallbackFunction(IDictionary<string, object> context)
{
// Do something
return Task.FromResult(0);
}
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 be Abort
ed. Meaning you can't send/receive messages on the connection if you pass the websocketContext
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...
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With