问题
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:
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):
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.
来源:https://stackoverflow.com/questions/25516012/why-would-i-get-the-remote-server-returned-an-error-400-bad-request-with-t