none
Problem with WebRequest RRS feed

  • Question

  • Hi

    I am trying to access websites using C# WebRequest Windows Mobile 6.5. When ever I try, I keep getting ProtocolViolationException. This is the code I am using:

    using System;

    using System.Linq;

    using System.Collections.Generic;

    using System.ComponentModel;

    using System.Data;

    using System.Drawing;

    using System.Text;

    using System.Windows.Forms;

    using System.IO;

    using System.Net;

    using System.Net.Sockets;

    using System.Threading;

     

    namespace SmartDeviceProject6

    {

      public partial class Form1 : Form

      {

        String X = @"<soapenv:Envelope xmlns:soapenv=""http://schemas.xmlsoap.org/soap/envelope/""    <soapenv:Header/>

       <soapenv:Body>

          <urn:importHandtermRemovals>

             <urn:APIUser>

                <!--Zero or more repetitions:-->

                <urn:APIUserRow>

                   <urn:user-key>webservice</urn:user-key>

                   <urn:user-pw>webservice</urn:user-pw>

                   <urn:auto-create-list>?</urn:auto-create-list>

                </urn:APIUserRow>

             </urn:APIUser>

             <urn:temp_handterm_removals>

                <!--Zero or more repetitions:-->

                <urn:temp_handterm_removalsRow>

                   <urn:work_supplier_barcode>12345</urn:work_supplier_barcode>

                   <urn:wo_barcode>4405996</urn:wo_barcode>

                   <urn:stock_control_barcode>42438</urn:stock_control_barcode>

                   <urn:physical_quantity>75</urn:physical_quantity>

                   <urn:removal_quantity>25</urn:removal_quantity>

                </urn:temp_handterm_removalsRow>

             </urn:temp_handterm_removals>

          </urn:importHandtermRemovals>

       </soapenv:Body>

    </soapenv:Envelope>";

     

        public Form1()

        {

          InitializeComponent();

        }

     

        private void menuItem1_Click(object sender, EventArgs e)

        {

          try

          {

            HttpWebRequest Request = (HttpWebRequest)WebRequest.Create(@"http:// 2.110.58.166");

            // System.Net.ProtocolViolationException:

            // The System.Net.HttpWebRequest.Method property is GET or HEAD.-or-

            // System.Net.HttpWebRequest.KeepAlive is true,

            // System.Net.HttpWebRequest.AllowWriteStreamBuffering is false,

            // System.Net.HttpWebRequest.ContentLength is -1,       
            // System.Net.HttpWebRequest.SendChunked is

            // false, and System.Net.HttpWebRequest.Method is POST or PUT.

            // I tried all combinations of the above errors, and it still fails...

            Request.Method = "POST";

            Request.ContentType = "test/xml";

            Request.Timeout = 10000;

            Request.ContentLength = X.Length;

            /*

            One possible combination...

            Request.KeepAlive = true;

            Request.AllowWriteStreamBuffering = false;

            Request.SendChunked = false;

            */

            using (Stream stream = Request.GetRequestStream())

            using (StreamWriter writer = new StreamWriter(stream, Encoding.UTF8))

            {

              writer.Write(X);

            } // << This is where I get the error

     

            HttpWebResponse WR = (HttpWebResponse)Request.GetResponse();

            using (Stream reader = Request.GetResponse().GetResponseStream())

            {

              long lLgde = reader.Length;

              Int32 Lgde = Convert.ToInt32(lLgde);

              Byte[] buffer = new Byte[Lgde];

              Int32 Laest = reader.Read(buffer, 0, Lgde);

              String result = BitConverter.ToString(buffer, 0, Lgde);

            }

          }

          catch (Exception ex)

          {

            MessageBox.Show(ex.Message, "Error");

          }

        }

      }

    }


    I tried just about everything I can imagine, but I never seem to be able to pass writer.Write(X). Unfortunately I have to solve the problem with Windows Mobile 6.5, since my customer have a ton of these terminals.

    So I could really need some help.

    Any suggestions anyone?

    Best regards

    Poul




    Poul, Developer of programs for Windows Mobile


    • Edited by DaPaul Tuesday, January 16, 2018 12:57 AM
    Tuesday, January 16, 2018 12:53 AM

All replies

  • Could be caused by a number of things so it is going to be difficult for us to help you out. The problems I see.

    • Sending a custom built SOAP message to an endpoint that doesn't appear to be a service.
    • The URL is not correct as it has a space in it.

    There have been reports online that trying to communicate with certain web servers will fail if you don't set KeepAlive false. Alternatively it has also been mentioned that allowing unsafe headers will enable some web servers to communicate with the client.


    Michael Taylor http://www.michaeltaylorp3.net

    Tuesday, January 16, 2018 2:50 PM
    Moderator
  • Hi Michael

    The extra blank in the URL is my fault, it does not appear in the real code.

    I tried your suggestion, and it did make a difference, I now get a Unable to connect to the remote server. So I guess the ProtocolViolationException is solved now, and I am now facing another error, the next in the row.

    You wouldn't happen to know if the GetRequestStream returns a proper http-block or not?

    Thanks a lot, I will make sure to mark your answer as a solution.

    Best regards

    Poul


    Poul, Developer of programs for Windows Mobile

    Tuesday, January 16, 2018 11:23 PM
  • You don't use GetRequestStream to get the response. You'd use GetResponseStream. Here's typical WebRequest code.

    var request = WebRequest.Create(url) as HttpWebRequest;
    //Set any request options you need
    
    //Make actual call
    using (var response = request.GetResponse())
    {
       //Response has the core HTTP status info
    
       //Get the actual response
       using (var output = response.GetResponseStream())
       {
          //Do something with the actual response
       };
    };

    The Response object (HttpWebResponse) will have the HTTP response information including the returned headers, content type, status code, etc.  The GetResponseStream method gives you access to the content itself.

    Note though that using WebRequest is pretty old. You should be using HttpClient or WebClient instead. They are far easier to work with. Here's one of many articles on how to do SOAP with Httpclient. Just note that the if statement for handling responses isn't necessary. You can use EnsureSuccessStatusCode to handle this logic automatically.


    Michael Taylor http://www.michaeltaylorp3.net

    Wednesday, January 17, 2018 2:45 PM
    Moderator
  • Hi Michael

    I don't understand. I send a request (using writer.write to do the actual transfer of the code). I then get a response, right? So your comment "Make actual call" should be replaced with this code:

            using (Stream stream = Request.GetRequestStream())
            using (StreamWriter writer = new StreamWriter(stream, Encoding.UTF8))
            {
              writer.Write(X);
            }
    Correct?

    But I still crash in GetRequestStream()? Nothings actually changed - and I already am using GetResponse() to fetch the response on my request. I am confused.

    Maybe I completely misunderstand how the underlying system works. I think like this:

    1. Send a request
    2. Await and receive a response.

    Is that not correct?

    Best regards

    Poul


    Poul, Developer of programs for Windows Mobile

    Wednesday, January 17, 2018 4:39 PM
  • GetRequestStream would trigger a connect request to the remote server so the stream can be opened if you are then going to send data using the stream. GetResponseStream does the same thing (if not already open) when there is no body to send and it blocks waiting on the response.

    Given your "unable to connect" error now, are you sure the URL is correct? You mentioned you're trying to connect to websites but unless this is an intranet site that IP address probably isn't going to work. Generally you use a DNS name (for internal or external sites).

    Can you successfully send a fiddler request to this endpoint? 


    Michael Taylor http://www.michaeltaylorp3.net

    Wednesday, January 17, 2018 4:58 PM
    Moderator
  • Hi Michael

    First: Would you say that my description of the inner workings of a POST is correct? Ie. I send a request, and await for and receives a response. Because I get the impression that we are not really on the same page here. Sometimes it kinda slips, if you know what I mean. Or maybe it's just me.

    You are right, I should try to work with never code, so I will try HttpClient and WebClient.

    Yes, I think the URL is correct. It's just a kinda "pseudo server", a little program made to receive data just so I can see precisely what I am sending. But let me check it again.

    And no, I've never even heard about Fiddler before. Very interesting. I'll look into it.

    Let me check all this a bit more, just to be sure I'm not having butter fingers.

    Bets regards


    Poul, Developer of programs for Windows Mobile

    Wednesday, January 17, 2018 5:41 PM
  • Not specific to a POST but HTTP is very much a send a request, block waiting for the response protocol. So that description is correct. Where things vary is in when this stuff occurs. WebRequest is actually an abstract class unrelated to HTTP so when you're using it you're using an abstraction. So its interface isn't designed specifically for HTTP and therefore it is harder to tell when things occur.

    HttpClient is clearly designed for HTTP so there is no request/response separation. You send a request with a single method and the return value is the response. It is clear when the call occurs. The request/response is basically built into the signature.

    Fiddler is useful for watching HTTP traffic. You can run it while you're making these types of calls and see the request/response as they naturally occur. Very useful when debugging HTTP issues.


    Michael Taylor http://www.michaeltaylorp3.net

    Wednesday, January 17, 2018 6:00 PM
    Moderator
  • Hi Michael

    HttpClient is not implemented in Windows Mobile 6.5


    Poul, Developer of programs for Windows Mobile

    Wednesday, January 17, 2018 6:05 PM
  • HttpClient is a newer class in the framework. What version of the framework are you working with?

    Michael Taylor http://www.michaeltaylorp3.net

    Wednesday, January 17, 2018 6:15 PM
    Moderator
  • Windows Mobile 6.5
    My customer has about 20 or so of these dinosaurs, and want to be able to use them.



    Poul, Developer of programs for Windows Mobile

    Wednesday, January 17, 2018 8:13 PM
  • My understanding of Mobile 6.5 is that it can have differing versions of the framework installed. WebClient is the predecessor to HttpClient (and works very similarly). So you could see if it is available. But I think if you're close to getting the existing WebRequest working as is then there is likely no reason to change for the mobile code.

    Michael Taylor http://www.michaeltaylorp3.net

    Wednesday, January 17, 2018 8:21 PM
    Moderator
  • Hi Michael

    What do you mean when you say"Framework"? (English is not my first language)

    I have no idea how close i really am to making WebRequest working. But I can now catch the errors returned by the server in detail, and it now says that the SOAPActivate header is missing. (Sigh)

    I have a Pc-program that works, so I am now trying to make a "pseudo-server" so I can see what the Pc actually sends and what is missing from whatever the PDA is sending.

    Best regards

    Poul


    Poul, Developer of programs for Windows Mobile

    Thursday, January 18, 2018 4:52 PM
  • Framework (in this case) is the .NET framework. You can determine that by looking at the project properties window. It specifies which version of the framework you're using. Nevertheless I think you're close on WebRequest so you might as well stick with that.

    For SOAP you might try first getting it to work in SOAPUI. It was designed to allow you to play around with SOAP messages outside of code. Once you've gotten a message working you should be able to take the SOAP body and merge it into your code. At this point it sounds like you're just trying to find the right combination of headers.


    Michael Taylor http://www.michaeltaylorp3.net

    Thursday, January 18, 2018 4:59 PM
    Moderator
  • Hi Michael

    I already did that, actually. And I also have a Pc-program running XML-scripts without any trouble whatsoever. It just doesn't work with PDA's. I am trying now to build a simple webserver that will receive the data so I can see what my PDA is actually sending. But I've run into massive problems with port 80 and inability to shut HTTP down and stuff. I plan to continue for a while, and see if I cannot make it work.

    Best regards

    Poul, Developer of programs for Windows Mobile

    • Edited by DaPaul Thursday, January 18, 2018 8:07 PM
    Thursday, January 18, 2018 8:06 PM
  • Hi Michael

    I found out what the problem was (Actually, I found a guy who knew how to fix it ;))

    This is the difference between his, functioning code and my not-functioning:

            Request.Headers.Add("SOAPAction", "''");
            Request.ContentType = "text/xml;charset=\"utf-8\"";
            Request.Method = "POST";

    Since I tried the two lower lines, you can claim it's just the SOAPAction parameter which is supposed to be '' instead of a blank line. <Sigh> This is just soooo frustrating. ;)

    In any case, thank you very much. I cannot in honesty mark your answer as an answer, because, well it really wasn't, but it was still a big help.

    Have a nice day

    Best regards

    PoulK

    Poul, Developer of programs for Windows Mobile

    Thursday, February 1, 2018 2:18 PM