Click here to Skip to main content
14,331,729 members

Web Development

 
Question[UPDATED ]MVC Web API Controller - Pass List<string> Pin Pin
Kevin Marois12-Feb-19 6:32
professionalKevin Marois12-Feb-19 6:32 
AnswerRe: [UPDATED ]MVC Web API Controller - Pass List<string> Pin Pin
Richard Deeming12-Feb-19 7:54
mveRichard Deeming12-Feb-19 7:54 
GeneralRe: [UPDATED ]MVC Web API Controller - Pass List<string> Pin Pin
Kevin Marois12-Feb-19 8:08
professionalKevin Marois12-Feb-19 8:08 
AnswerRe: [UPDATED ]MVC Web API Controller - Pass List<string> Pin Pin
F-ES Sitecore12-Feb-19 23:14
mveF-ES Sitecore12-Feb-19 23:14 
QuestionASP.Net MVC Serialization Problem - "No parameterless constructor defined for this object" Pin
Kevin Marois11-Feb-19 8:30
professionalKevin Marois11-Feb-19 8:30 
AnswerRe: ASP.Net MVC Serialization Problem - "No parameterless constructor defined for this object" Pin
Richard Deeming11-Feb-19 11:44
mveRichard Deeming11-Feb-19 11:44 
GeneralRe: ASP.Net MVC Serialization Problem - "No parameterless constructor defined for this object" Pin
Kevin Marois12-Feb-19 6:27
professionalKevin Marois12-Feb-19 6:27 
QuestionHow to send the 'Connection' header using HttpListenerResponse Pin
Shmuel Zang11-Feb-19 5:29
memberShmuel Zang11-Feb-19 5:29 

Hello all.

While trying to implement a web-socket handshake, I encountered a weird behavior. It looks like the HttpListenerResponse class doesn't send the 'Connection' header.

Here is an example for explaining what I mean:

public void TestWebSocketHttpHandshake()
{
    int port = 9444;
    ManualResetEvent serverStartedEvent = new ManualResetEvent(false);
    ManualResetEvent clientClosedEvent = new ManualResetEvent(false);

    // HTTP server that gets a web-socket handshake request and,
    // send back a web-socket handshake response.
    async Task RunHttpServer()
    {
        HttpListener hl = new HttpListener();
        hl.Prefixes.Add($"http://+:{port}/");
        hl.Start();
        serverStartedEvent.Set();
        HttpListenerContext hlc = await hl.GetContextAsync();

        string secWebSocketKeyHeader = hlc.Request.Headers["Sec-WebSocket-Key"]?.Trim();
        string secWebSocketAcceptHeader = Convert.ToBase64String(
            System.Security.Cryptography.SHA1.Create().ComputeHash(
                Encoding.UTF8.GetBytes(secWebSocketKeyHeader + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11")
            )
        );

        hlc.Response.StatusCode = (int)HttpStatusCode.SwitchingProtocols; // 101
        hlc.Response.StatusDescription = "Switching Protocols";
        hlc.Response.ProtocolVersion = new Version("1.1");
        hlc.Response.AddHeader("Upgrade", "websocket");
        hlc.Response.AddHeader("Connection", "Upgrade");
        hlc.Response.AddHeader("Sec-WebSocket-Accept", secWebSocketAcceptHeader);

        hlc.Response.Close();

        // Wait for the client to close.
        clientClosedEvent.WaitOne();
        hl.Stop();
    }

    // Tcp Client that sends a web-socket handshake request and,
    // writes the received web-socket handshake response.
    async Task RunTcpClient()
    {
        const string eol = "\r\n"; // HTTP/1.1 defines the sequence CR LF as the end-of-line marker

        // Wait for the server to start.
        serverStartedEvent.WaitOne();

        using (TcpClient tc = new TcpClient())
        {
            tc.Connect("localhost", port);

            using (NetworkStream ns = tc.GetStream())
            {
                string wsRequest =
                    $"GET /chat HTTP/1.1{eol}Host: localhost:{port}{eol}"+ 
                    $"Upgrade: websocket{eol}Connection: Upgrade{eol}" +
                    $"Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ=={eol}"+ 
                    $"Sec-WebSocket-Version: 13{eol}{eol}";

                byte[] wsRequestBytes = Encoding.ASCII.GetBytes(wsRequest);
                await ns.WriteAsync(wsRequestBytes, 0, wsRequestBytes.Length);
                Console.WriteLine("Sent request:");
                Console.WriteLine(wsRequest);

                byte[] responseBuf = new byte[256];
                int resBytesCount = await ns.ReadAsync(responseBuf, 0, responseBuf.Length);
                string wsResponse = Encoding.ASCII.GetString(responseBuf, 0, resBytesCount);
                Console.WriteLine("Received response:");
                Console.WriteLine(wsResponse);
            }
        }

        clientClosedEvent.Set();
    }

    Task.WaitAll(RunHttpServer(), RunTcpClient());
}

The result is:

Sent request:
GET /chat HTTP/1.1
Host: localhost:9444
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
Sec-WebSocket-Version: 13


Received response:
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Content-Length: 0
Server: Microsoft-HTTPAPI/2.0
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
Date: Mon, 11 Feb 2019 16:16:37 GMT

So, what we can see here is that we have a HttpListener server that sets the 'Connection' header in the response but, when the client gets the server's response, the 'Connection' header is missing.

I know that we can use the HttpListenerContext.AcceptWebSocketAsync method for handling the web-socket connection but, this method uses the operating system web-socket support that is supported only from Windows 8/ Windows Server 2012 and, we want this to work also on a Windows Server 2008 system.

I know that there are some solutions on the web for running a web-socket server. But, all the solutions I found are for running a server that listens to web-socket requests on a given port. Since in my case I want to accept web-socket requests on the same port of an existing server (Owin server that does other things), I have to handle it using the given request's HttpListenerContext.

Can anyone explain this behavior (the missing 'Connection' header) or, suggest a solution?



modified 11-Feb-19 14:27pm.

QuestionLocal IIS Development Question Pin
Kevin Marois7-Feb-19 11:07
professionalKevin Marois7-Feb-19 11:07 
AnswerRe: Local IIS Development Question Pin
Richard Deeming7-Feb-19 11:13
mveRichard Deeming7-Feb-19 11:13 
GeneralRe: Local IIS Development Question Pin
Kevin Marois7-Feb-19 11:37
professionalKevin Marois7-Feb-19 11:37 
GeneralRe: Local IIS Development Question Pin
Richard Deeming8-Feb-19 0:55
mveRichard Deeming8-Feb-19 0:55 
GeneralRe: Local IIS Development Question Pin
Kevin Marois11-Feb-19 5:26
professionalKevin Marois11-Feb-19 5:26 
GeneralRe: Local IIS Development Question Pin
Kevin Marois12-Mar-19 12:48
professionalKevin Marois12-Mar-19 12:48 
GeneralRe: Local IIS Development Question Pin
Richard Deeming13-Mar-19 1:33
mveRichard Deeming13-Mar-19 1:33 
GeneralRe: Local IIS Development Question Pin
Kevin Marois13-Mar-19 6:14
professionalKevin Marois13-Mar-19 6:14 
Question"The requested resource does not support http method 'GET" Pin
Kevin Marois7-Feb-19 10:05
professionalKevin Marois7-Feb-19 10:05 
AnswerRe: "The requested resource does not support http method 'GET" Pin
Richard Deeming7-Feb-19 10:28
mveRichard Deeming7-Feb-19 10:28 
GeneralRe: "The requested resource does not support http method 'GET" Pin
Kevin Marois7-Feb-19 11:05
professionalKevin Marois7-Feb-19 11:05 
QuestionAsp.Net MVC Delete Method Not Allowed Pin
Kevin Marois6-Feb-19 6:53
professionalKevin Marois6-Feb-19 6:53 
AnswerRe: Asp.Net MVC Delete Method Not Allowed Pin
Richard Deeming6-Feb-19 7:12
mveRichard Deeming6-Feb-19 7:12 
GeneralRe: Asp.Net MVC Delete Method Not Allowed Pin
Kevin Marois6-Feb-19 10:18
professionalKevin Marois6-Feb-19 10:18 
GeneralRe: Asp.Net MVC Delete Method Not Allowed Pin
Richard Deeming7-Feb-19 0:44
mveRichard Deeming7-Feb-19 0:44 
GeneralRe: Asp.Net MVC Delete Method Not Allowed Pin
Kevin Marois7-Feb-19 8:35
professionalKevin Marois7-Feb-19 8:35 
QuestionASP.NET CORE AUTHENTICATION AGAINST ADFS Pin
_dk66072-Feb-19 6:18
member_dk66072-Feb-19 6:18 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.