HttpListenerRequest InputStream Hang

I’m getting strange annoying behavior when executing this code. Anyone else experience this?

Steps:
[ul]
Submit a page that has form data
Execute the line that reads the InputStream ( string content = new System.IO.StreamReader(request.InputStream).ReadToEnd():wink:
Browser Hangs, both browser and code seem to be waiting on each other
Click STOP in the browser
Execution continues to the next line and the content/data is captured!
[/ul]

Why the heck is it stopping executing waiting on the browser when reading the stream???


public static Hashtable GetFormData(System.Net.HttpListenerRequest request)
        {
            Hashtable formVars = new Hashtable();

            try
            {
                string content = new System.IO.StreamReader(request.InputStream).ReadToEnd();

                if (request.ContentType.ToLower() == "application/x-www-form-urlencoded")
                {
                    string[] pairs = content.Split('&');

                    for (int x = 0; x < pairs.Length; x++)
                    {
                        string[] item = pairs[x].Split('=');
                        formVars.Add(item[0], UAM.InformatiX.SPOT.Web.HttpUtility.UrlDecode(item[1]));
                    }
                }
            }
            catch (Exception e)
            {
            }

            return formVars;
        }

It’s for the page I am submitting data from. /SignIn.htm in my case.

I am noticing though that the request for the page is sent more than once (added a Debug.Print() in there before adding the formvars). I don’t understand why the request is being triggered repeatedly. Is there some async thing I am not accounting for?

correct. no params on the URL, that is all RawUrl gives me.

I am finding that one submit from the browser client causes 2 requests, and so I had to modify the code as follows:

public static Hashtable GetFormData(System.Net.HttpListenerRequest request)
{
    Hashtable formVars = new Hashtable();

    try
    {
        // request.InputStream.
        Debug.Print(request.InputStream.Length.ToString());
        string content = new System.IO.StreamReader(request.InputStream).ReadToEnd();

        if (request.ContentType.ToLower() == "application/x-www-form-urlencoded")
        {
            string[] pairs = content.Split('&');

            for (int x = 0; x < pairs.Length; x++)
            {
                string[] item = pairs[x].Split('=');
                Debug.Print("Form Value add requested for: " + request.RawUrl);
                if (!formVars.Contains(item[0]))
                {
                    Debug.Print("Adding Form Value: " + item[0]);
                    formVars.Add(item[0], UAM.InformatiX.SPOT.Web.HttpUtility.UrlDecode(item[1]));
                }
            }
        }
    }
    catch (Exception e)
    {
    }

    return formVars;
}

And the output is as follows:

Click submit in Browser results in this output:
27 (the InputStream length)

At this point, the browser is waiting indefinitely and the app is doing nothing (as though it finished executing)

Click STOP in the browser, and the output result is:

Form Value add requested for: /signin.htm
Adding Form Value: username
Form Value add requested for: /signin.htm
Form Value Acquired: username=sdvd
Render Complete: Signin.htm
#### Exception System.Net.Sockets.SocketException - CLR_E_FAIL (3) ####
#### Message:
#### Microsoft.SPOT.Net.SocketNative::send [IP: 0000] ####
#### System.Net.Sockets.Socket::Send [IP: 0018] ####
#### System.Net.Sockets.NetworkStream::Write [IP: 0051] ####
#### System.Net.OutputNetworkStreamWrapper::Write [IP: 0017] ####
#### System.Net.HttpListenerResponse::SendHeaders [IP: 0039] ####
#### System.Net.OutputNetworkStreamWrapper::Write [IP: 000d] ####
#### dapug.MFToolkit.WebExtensions::Write [IP: 0017] ####
#### dapug.MicroASP.ASPHandler::ProcessRequest [IP: 0112] ####
#### dapug.MicroASP.HttpServer::ListenerThread [IP: 0028] ####
#### SocketException ErrorCode = 10053
#### SocketException ErrorCode = 10053
A first chance exception of type ‘System.Net.Sockets.SocketException’ occurred in Microsoft.SPOT.Net.dll
#### SocketException ErrorCode = 10053
#### SocketException ErrorCode = 10053
Exception was thrown: System.Net.Sockets.SocketException
Listening

At which point its awaiting another request.

Notice how it has a REPEAT on this output: “Form Value add requested for: /signin.htm”.

Also notice how it does successfully capture the form data in the end: “Form Value Acquired: username=sdvd”

I found a similar problem here, ReadToEnd() on an InputStream hangs.
http://www.tinyclr.com/forum/topic?id=10145&page=1#msg100579

I am completely confused. The hang is a hang, regardless if I have crap code causing the 2 requests. And BTW, that is not my case. I don’t get 2 requests using the same app code anywhere else, ONLY when I try and ReadToEnd() on this stream. Meaning, if I comment out the stream reader and leave the Debug.Print() in there, it shows one request exactly as expected.

There has to be something about a StreamReader on an InputStream that is causing unexpected behavior.

yeah, I just caught that myself, LOL. There are 2 form fields and I forgot about that.

@ andre: indeed, your suggestion works fine. Thank you. I was about to roll my own read operation here, and I guess that is what it takes.

Not sure why I have to do so much plumbing. Full .NET InpuStream has an EndRead(), and applying StreamReader ReadToEnd() also seems to work with success:

But not for NETMF… ? So perhaps there is a bug somewhere deep? For what it’s worth, here is more insight into ReadToEnd().

…

The ReadToEnd() line in my code example is literally waiting on something from the browser (not sure why, since the client to server trip should have already completed)

So I put a Breakpoint on the ReadToEnd() line, and I clicked Step Into

Step into: Stepping over non-user code ‘System.Net.HttpListenerRequest.InputStream.get’
Step into: Stepping over non-user code ‘System.IO.StreamReader.StreamReader’
Step into: Stepping over non-user code ‘System.IO.TextReader.TextReader’
Step into: Stepping over non-user code ‘System.MarshalByRefObject.MarshalByRefObject’
Step into: Stepping over non-user code ‘System.MarshalByRefObject.MarshalByRefObject’
Step into: Stepping over non-user code ‘System.IO.TextReader.TextReader’
Step into: Stepping over non-user code ‘System.IO.StreamReader.StreamReader’
Step into: Stepping over non-user code ‘System.Net.InputNetworkStreamWrapper.CanRead.get’
Step into: Stepping over non-user code ‘System.Net.Sockets.NetworkStream.CanRead.get’
Step into: Stepping over non-user code ‘System.Net.InputNetworkStreamWrapper.CanRead.get’
Step into: Stepping over non-user code ‘System.IO.StreamReader.StreamReader’
Step into: Stepping over non-user code ‘System.IO.StreamReader.CurrentEncoding.get’
Step into: Stepping over non-user code ‘System.Text.Encoding.UTF8.get’
Step into: Stepping over non-user code ‘System.Text.UTF8Encoding.UTF8Encoding’
Step into: Stepping over non-user code ‘System.Text.Encoding.Encoding’
Step into: Stepping over non-user code ‘System.Text.Encoding.Encoding’
Step into: Stepping over non-user code ‘System.Text.UTF8Encoding.UTF8Encoding’
Step into: Stepping over non-user code ‘System.Text.Encoding.UTF8.get’
Step into: Stepping over non-user code ‘System.IO.StreamReader.CurrentEncoding.get’
Step into: Stepping over non-user code ‘System.IO.StreamReader.StreamReader’
Step into: Stepping over non-user code ‘System.Text.UTF8Encoding.GetDecoder’
Step into: Stepping over non-user code ‘System.Text.UTF8Decoder.UTF8Decoder’
Step into: Stepping over non-user code ‘System.Text.Decoder.Decoder’
Step into: Stepping over non-user code ‘System.Text.Decoder.Decoder’
Step into: Stepping over non-user code ‘System.Text.UTF8Decoder.UTF8Decoder’
Step into: Stepping over non-user code ‘System.Text.UTF8Encoding.GetDecoder’
Step into: Stepping over non-user code ‘System.IO.StreamReader.StreamReader’
Step into: Stepping over non-user code ‘System.IO.StreamReader.ReadToEnd’
Step into: Stepping over non-user code ‘System.Net.InputNetworkStreamWrapper.CanSeek.get’
Step into: Stepping over non-user code ‘System.Net.Sockets.NetworkStream.CanSeek.get’
Step into: Stepping over non-user code ‘System.Net.InputNetworkStreamWrapper.CanSeek.get’
Step into: Stepping over non-user code ‘System.IO.StreamReader.ReadToEnd’
Step into: Stepping over non-user code ‘System.IO.StreamReader.ReadNonSeekableStream’
Step into: Stepping over non-user code ‘System.Collections.ArrayList.ArrayList’
Step into: Stepping over non-user code ‘System.Collections.ArrayList.ArrayList’
Step into: Stepping over non-user code ‘System.IO.StreamReader.ReadNonSeekableStream’
Step into: Stepping over non-user code ‘System.IO.StreamReader.Read’
Step into: Stepping over non-user code ‘System.IO.StreamReader.FillBufferAndReset’
Step into: Stepping over non-user code ‘System.Net.InputNetworkStreamWrapper.Read’
Step into: Stepping over non-user code ‘System.Net.InputNetworkStreamWrapper.ReadInternal’
Step into: Stepping over non-user code ‘System.Net.Sockets.NetworkStream.Read’
Step into: Stepping over non-user code ‘System.Net.Sockets.Socket.Available.get’
Step into: Stepping over non-user code ‘System.Net.Sockets.Socket.Available.get’
Step into: Stepping over non-user code ‘System.Net.Sockets.NetworkStream.Read’
Step into: Stepping over non-user code ‘System.Net.Sockets.Socket.Receive’


The debugger output stops here.

HANG… WAITING ON SOME MYSTERY FEEDBACK FROM BROWSER…

Clicking STOP in the browser allows the ReadToEnd() method to continue, successfully! ???..

Step into: Stepping over non-user code ‘System.Net.Sockets.Socket.Receive’
Step into: Stepping over non-user code ‘System.Net.Sockets.NetworkStream.Read’
Step into: Stepping over non-user code ‘System.Net.InputNetworkStreamWrapper.ReadInternal’
Step into: Stepping over non-user code ‘System.Net.InputNetworkStreamWrapper.Read’
Step into: Stepping over non-user code ‘System.IO.StreamReader.FillBufferAndReset’
Step into: Stepping over non-user code ‘System.Net.InputNetworkStreamWrapper.Read’
Step into: Stepping over non-user code ‘System.Net.InputNetworkStreamWrapper.ReadInternal’
Step into: Stepping over non-user code ‘System.Net.Sockets.NetworkStream.Read’
Step into: Stepping over non-user code ‘System.Net.Sockets.Socket.Available.get’
Step into: Stepping over non-user code ‘System.Net.Sockets.Socket.Available.get’
Step into: Stepping over non-user code ‘System.Net.Sockets.NetworkStream.Read’
Step into: Stepping over non-user code ‘System.Net.Sockets.Socket.Receive’
Step into: Stepping over non-user code ‘System.Net.Sockets.Socket.Receive’
Step into: Stepping over non-user code ‘System.Net.Sockets.NetworkStream.Read’
Step into: Stepping over non-user code ‘System.Net.InputNetworkStreamWrapper.ReadInternal’
Step into: Stepping over non-user code ‘System.Net.InputNetworkStreamWrapper.Read’
Step into: Stepping over non-user code ‘System.IO.StreamReader.FillBufferAndReset’
Step into: Stepping over non-user code ‘System.IO.StreamReader.Read’
Step into: Stepping over non-user code ‘System.IO.StreamReader.Read’
Step into: Stepping over non-user code ‘System.IO.StreamReader.FillBufferAndReset’
Step into: Stepping over non-user code ‘System.IO.StreamReader.Reset’
Step into: Stepping over non-user code ‘System.IO.StreamReader.Reset’
Step into: Stepping over non-user code ‘System.IO.StreamReader.FillBufferAndReset’
Step into: Stepping over non-user code ‘System.Net.InputNetworkStreamWrapper.Read’
Step into: Stepping over non-user code ‘System.Net.InputNetworkStreamWrapper.ReadInternal’
Step into: Stepping over non-user code ‘System.Net.Sockets.NetworkStream.Read’
Step into: Stepping over non-user code ‘System.Net.Sockets.Socket.Available.get’
Step into: Stepping over non-user code ‘System.Net.Sockets.Socket.Available.get’
Step into: Stepping over non-user code ‘System.Net.Sockets.NetworkStream.Read’
Step into: Stepping over non-user code ‘System.Net.Sockets.Socket.Receive’
Step into: Stepping over non-user code ‘System.Net.Sockets.Socket.Receive’
Step into: Stepping over non-user code ‘System.Net.Sockets.NetworkStream.Read’
Step into: Stepping over non-user code ‘System.Net.InputNetworkStreamWrapper.ReadInternal’
Step into: Stepping over non-user code ‘System.Net.InputNetworkStreamWrapper.Read’
Step into: Stepping over non-user code ‘System.IO.StreamReader.FillBufferAndReset’
Step into: Stepping over non-user code ‘System.IO.StreamReader.Read’
Step into: Stepping over non-user code ‘System.IO.StreamReader.ReadNonSeekableStream’
Step into: Stepping over non-user code ‘System.Array.Copy’
Step into: Stepping over non-user code ‘System.Array.Copy’
Step into: Stepping over non-user code ‘System.IO.StreamReader.ReadNonSeekableStream’
Step into: Stepping over non-user code ‘System.IO.StreamReader.ReadNonSeekableStream’
Step into: Stepping over non-user code ‘System.Collections.ArrayList.Count.get’
Step into: Stepping over non-user code ‘System.IO.StreamReader.ReadNonSeekableStream’
Step into: Stepping over non-user code ‘System.IO.StreamReader.ReadNonSeekableStream’
Step into: Stepping over non-user code ‘System.IO.StreamReader.ReadToEnd’
Step into: Stepping over non-user code ‘System.IO.StreamReader.ReadToEnd’
The program ‘[5056] Micro Framework application: Managed’ has exited with code 0 (0x0).

At this point, I DO capture the form fields, and the server app continues listening. But it’s pointless if it hangs both client and server in the process! So weird.

4.1

good to specify

HttpListener in 4.1 contains a lot of bugs, so much I’ve dropped it in my server project: http://www.tinyclr.com/codeshare/entry/186

I wish I could use 4.2, but it still lacks wifi (rs21) for Gadgeteer. Not sure why that is taking soooo long to fix.

Do you mean the gadgeteer network wrappers? Wifi is already available in current SDK!