0

I was first getting "Unable to connect to the remote server" but then remembered that I couldn't use "localhost" from a handheld device. I swapped that out with the name of the machine like so:

String uri = String.Format(@"http://PLATYPUS:21608/api/inventory/sendXML/woodrow/gus/{0}", fileName);
//I reckon I could also use the IP address in place of the machine name, but probably would make no difference

...and now I get, "The remote server returned an error: (400) Bad Request"

The same basic code (shown below) runs fine from a "regular" (C# desktop) app created in VS 2013. From the handheld device, with this code created in VS 2003, I get that ("400") err msg. Why might that be?

public static string SendXMLFile(string xmlFilepath, string uri, int timeout)
{
    HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri);

    request.KeepAlive = false;
    request.ProtocolVersion = HttpVersion.Version10;
    request.ContentType = "application/xml";
    request.Method = "POST";

    StringBuilder sb = new StringBuilder();
    using (StreamReader sr = new StreamReader(xmlFilepath))
    {
        String line;
        while ((line = sr.ReadLine()) != null)
        {
            sb.Append(line); 
            sb.Append("\r\n");
        }
        byte[] postBytes = Encoding.UTF8.GetBytes(sb.ToString());

        if (timeout < 0)
        {
            request.Timeout = timeout;
        }

        request.ContentLength = postBytes.Length;
        request.KeepAlive = false;

        request.ContentType = "application/x-www-form-urlencoded"; // not "text/xml" correct?

        try
        {
            Stream requestStream = request.GetRequestStream();

            requestStream.Write(postBytes, 0, postBytes.Length);
            requestStream.Close();

            HttpWebResponse response = (HttpWebResponse) request.GetResponse();
            return response.ToString();
        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.Message);
            request.Abort();
            return string.Empty;
        }
    }
}

This code differs only slightly from that in the VS 2013 app, in these ways:

(a) Above/not working:

sb.Append(line); 
sb.Append("\r\n");

Below/working:

sb.AppendLine(line);

(b) Above/not working:

request.Timeout = timeout;

Below/working:

request.ReadWriteTimeout = timeout;
request.Timeout = timeout;

(c) Above/not working:

HttpWebResponse response = (HttpWebResponse) request.GetResponse();
return response.ToString();

Below/working:

using (var response = (HttpWebResponse)request.GetResponse())
{
    return response.ToString();
}

VS 2013 code that works:

public static string SendXMLFile(string xmlFilepath, string uri, int timeout)
{
    HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri);

    request.KeepAlive = false;
    request.ProtocolVersion = HttpVersion.Version10;
    request.ContentType = "application/xml";
    request.Method = "POST";

    StringBuilder sb = new StringBuilder();
    using (StreamReader sr = new StreamReader(xmlFilepath))
    {
        String line;
        while ((line = sr.ReadLine()) != null)
        {
            sb.AppendLine(line);
        }
        byte[] postBytes = Encoding.UTF8.GetBytes(sb.ToString());

        if (timeout < 0)
        {
            request.ReadWriteTimeout = timeout;
            request.Timeout = timeout;
        }

        request.ContentLength = postBytes.Length;
        request.KeepAlive = false;

        request.ContentType = "application/x-www-form-urlencoded"; // not "text/xml" correct?

        try
        {
            Stream requestStream = request.GetRequestStream();

            requestStream.Write(postBytes, 0, postBytes.Length);
            requestStream.Close();

            using (var response = (HttpWebResponse)request.GetResponse())
            {
                return response.ToString();
            }
        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.Message);
            request.Abort();
            return string.Empty;
        }
    }
}

The working code (no err msgs, and the file is saved to the hard drive) passes this to SendXMLFile():

xmlFilepath == "C:\\HoldingTank\\Bla123456789.xml"
uri == http://localhost:21608/api/inventory/sendXML/woodrow/gus/Bla123456789
timeout == 500

The failing code (err msg, file is created and saved, but it is empty) passes:

xmlFilepath == "Bla123456789.xml" 
uri == http://SHANNON2:21608/api/inventory/sendXML/woodrow/gus/Bla123456789
timeout == 500

(the ".xml" is stripped out of xmlFilePath before passing that string to the server on the URI)

As to whether the file in xmlFilePath exists in the failing code, I've got this code:

public static bool WriteIt2( string fileName, string data, long fsize )
{
    bool         retVal      = false;
    long bytRd = 0;
    string       the_Msg     = "";

    if (File.Exists(fileName))
        File.Delete(fileName);
    using (FileStream fs = File.Create(@fileName))
    {
        Byte[] info = new UTF8Encoding(true).GetBytes(data);
        fs.Write(info, 0, info.Length);
        fs.Flush();
    }
    if (!File.Exists(fileName))
    {
        MessageBox.Show(String.Format("{0} does not seem to exist", fileName));
    }
    else
    {
        MessageBox.Show(String.Format("{0} DOES seem to exist", fileName));
    }

    string justFileName = Path.GetFileNameWithoutExtension(fileName);

    String uri = String.Format(@"http://PLATYPUS:21608/api/inventory/sendXML/woodrow/gus/{0}", fileName);
    . . .

...and I do see the "...DOES seem to exist" affirmation message.

Does the filename need to have "\" (or something else) prepended to it?

Is the file writing (FileStream) code wrong?

UPDATE

I tried it with slightly different FileStream code:

Byte[] info = Encoding.ASCII.GetBytes(data);
using (FileStream fileTest = File.Open(fileName, FileMode.CreateNew)) 
{
    fileTest.Write(info, 0, info.Length);
    fileTest.Flush();
}
. . .

...but still get the same "400" error.

UPDATE 2

Also with a UTF8 byte array instead of an ASCII byte array:

Byte[] info = Encoding.UTF8.GetBytes(data);

...still get the same err...

UPDATE 3

I realized I was making a boo-boo here:

string justFileName = Path.GetFileNameWithoutExtension(fileName);
. . .
SendXMLFile(fileName, uri, 500);

...and so changed it to:

SendXMLFile(justFileName, uri, 500);

...and now I get a "File not found" exception.

How can it pass the File.Exists test and then not be found?

UPDATE 4

Okay, something really crazy is going on, because I copied a file to the handheld device, into the folder where the .exe/.dll are located, and assigned its name to "justFileName"; it still says the file cannot be found.

Alright, Fiddler here I come...

UPDATE 5

Okay, here's what I see in Fiddler with the server running and then I try to send the file from the handheld device:

enter image description here

Not much appears in Fiddler before the attempt to send the file fails/aborts, and what does display in Fiddler doesn't seem overly helpful.

I wonder if it's not even getting to the point of sending any Http traffic from the handheld? Since I get "File not Found" there's a good chance that's true - why would it try to send it, if it can't find it?

UPDATE 6

As far as a possible header difference (still don't see anything related to my HTTP traffic in Fiddler), I would think I would think I might get a report from Fiddler about that if it was a problem, because I got this due to yahoo Ads bad acting (apparently):

enter image description here

UPDATE 7

I fixed the problem with the file not being found, but that takes me back to the "400" err. Odder yet, I have a breakpoint on the server code (on the "String saveLoc = " line), but it is not getting reached...???

[Route("api/inventory/sendXML/{userId}/{pwd}/{filename}")] 
public async void SendInventoryXML(String userId, String pwd, String fileName)
{
    XDocument doc = XDocument.Load(await Request.Content.ReadAsStreamAsync());
    String saveLoc = String.Format(@"C:\HDP\{0}.xml", fileName); // this line has a breakpoint on it, but Rip Van Winkle is not getting poked.
    doc.Save(saveLoc);
}

So the err returned from the server is happening even prior to that (breakpointed) line...???

UPDATE 8

In an attempt to understand why the server method is not being reached and I get the "error (400)" msg, I added a bunch of debug strings to see the values of the HttpWebRequest, like so:

HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri);
. . .
request.ContentLength = postBytes.Length;
String str;

if (null != request.Address)
{
    String str = String.Format("request.Address == {0}", request.Address.ToString());
    MessageBox.Show(str);
}
if (null != request.Connection)
{
    str = String.Format("connection == {0}", request.Connection.ToString());
    MessageBox.Show(str);
}
. . .
if (null != request.ContentLength.ToString())
{
    str = String.Format("contentLength == {0}", request.ContentLength.ToString());
    MessageBox.Show(str);
}

I added these debug strings for the following "request" (HttpWebRequest) properties:

Address
Connection
ContentType
Expect
MediaType
Referer // Referrer (don't fear the spell-checker)
RequestUri
TransferEncoding
UserAgent
ContentLength

The only ones that display (are not null) are:

Address
ContentType
RequestUri
ContentLength

So the others being null - is that possibly a/the problem?

In the interests of full disclosure, the values displayed are:

Address == http://PLATYPUS:21608/api/Inventory/sendXML/gus/woodrow/INV_0000003_08272014175010
ContentType == application/xml
RequestUri == [same as Address]
ContentLength == 11457215

Note: I still get the "400" err msg following the display of these four values...

UPDATE 9

Should this:

request.KeepAlive = false;

...be set to true instead (or simply left out altogether, as it is apparently true by default?

UPDATE 10

Please see Update 2 here.

Community
  • 1
  • 1
B. Clay Shannon-B. Crow Raven
  • 8,547
  • 144
  • 472
  • 862
  • 1
    Bust out Fiddler and compare the working request from the PC and the failing request from the device. It's probably something simple like a header difference, but that will certainly find it quickly. – ctacke Aug 26 '14 at 22:45
  • 1
    To pick up the traffic from the handheld device you'll need to configure fiddler as a remote proxy on the web server. You can read more about it [here](http://stackoverflow.com/questions/4428680/how-do-i-monitor-all-incoming-http-requests) – Aaron Carlson Aug 26 '14 at 23:43
  • It's not hitting a web server per se, it calls a Web API app that's running on the PC to which the handheld is connected. – B. Clay Shannon-B. Crow Raven Aug 26 '14 at 23:51
  • 1
    It's still a web server. Wireshark might pick it up as well. – ctacke Aug 27 '14 at 02:25
  • 1
    What happens if you use the actual IP address of the PC and not the host name "PLATYPUS"? – ctacke Aug 27 '14 at 22:37
  • @ctacke: The same thing happens either way; is the IP Address preferable to the host name? – B. Clay Shannon-B. Crow Raven Aug 27 '14 at 22:54
  • Using an IP eliminates the possibility that it's a DNS resolution problem. What error do you see if the web server/PC app piece isn't running at all? Is it the same? – ctacke Aug 29 '14 at 14:40
  • @ctacke: I'll test that again and let you know. Would prepending the URI with a "@" (making it a verbatim string) make any difference one way or the other. I've tested with all permutations (with "@", without "@", using "localhost", using host name, and using the IP Address), but I'll test again... – B. Clay Shannon-B. Crow Raven Aug 29 '14 at 15:11
  • I just realized what the problem might be and will test that first: on the handheld device, the .exe is from the "releases" branch, which targets .NET 1.1. The .dll I'm working with is from the "development" branch, which targets .NET 3.5. Perhaps this mismatch is the cause of the mayhem. – B. Clay Shannon-B. Crow Raven Aug 29 '14 at 15:47
  • @ctacke: To follow your suggestion and answer your question, I changed the URL to use the raw IP address, and left the server not running. I got, "An existing connection was forcibly closed by the remote host." What existing connection, I wonder? – B. Clay Shannon-B. Crow Raven Aug 29 '14 at 20:56
  • @ctakce: And with the server running, even though the version of the .exe now matches the .dll, I am back to getting the "400" error...and according to Fiddler 2, no HTTP is being sent. – B. Clay Shannon-B. Crow Raven Aug 29 '14 at 21:07

0 Answers0