我使用这里的代码尝试从 Compact Framework 客户端调用 Web API 服务器应用程序上的 REST 控制器方法:
public static void SendXMLFile3(string uri, string data)
{
WebRequest request = WebRequest.Create (uri);
request.Method = "POST";
string postData = data;
byte[] byteArray = Encoding.UTF8.GetBytes (postData);
request.ContentType = "application/x-www-form-urlencoded";
request.ContentLength = byteArray.Length;
Stream dataStream = request.GetRequestStream ();
dataStream.Write (byteArray, 0, byteArray.Length);
dataStream.Close ();
WebResponse response = request.GetResponse ();
MessageBox.Show(((HttpWebResponse) response).StatusDescription);
dataStream = response.GetResponseStream ();
StreamReader reader = new StreamReader (dataStream);
string responseFromServer = reader.ReadToEnd();
MessageBox.Show(responseFromServer);
reader.Close ();
dataStream.Close ();
response.Close ();
}
...我之前尝试过这段代码,我从“Microsoft .NET Compact Framework”一书中得到:
public static void SendXMLFile2(string uri, string data)
{
WebRequest req = WebRequest.Create(uri);
req.Method = "Post";
req.ContentType = "text/plain; charset=utf-8";
byte[] encodedBytes = Encoding.UTF8.GetBytes(data);
req.ContentLength = encodedBytes.Length;
Stream requestStream = req.GetRequestStream();
requestStream.Write(encodedBytes, 0, encodedBytes.Length);
requestStream.Close();
WebResponse result = req.GetResponse();
MessageBox.Show(result.ToString());
}
...但我得到“400 - 错误请求”的新(以及旧)代码。
我最初的尝试也不起作用,结果相同(400):
public static string SendXMLFile(string xmlFilepath, string uri, int timeout)
{
HttpWebRequest myHttpWebRequest=(HttpWebRequest)WebRequest.Create(uri);
myHttpWebRequest.AllowWriteStreamBuffering=false;
string postData = "<Command><DSD><line_id>1</line_id><invoice_no>david_dsd</invoice_no>. . .</DSD></Command>"; // TODO: if this works, replace it with the real data
myHttpWebRequest.Method="POST";
UTF8Encoding encodedData = new UTF8Encoding();
byte[] byteArray=encodedData.GetBytes(postData);
myHttpWebRequest.ContentType = "application/xml";
myHttpWebRequest.ContentLength=byteArray.Length;
Stream newStream=myHttpWebRequest.GetRequestStream();
newStream.Write(byteArray,0,byteArray.Length);
newStream.Close();
HttpWebResponse myHttpWebResponse=(HttpWebResponse)myHttpWebRequest.GetResponse();
return myHttpWebResponse.StatusDescription;
}
还有更多关于我在这里尝试过的大量变化,我已经达到了我的帖子长度限制。
更新
请注意,服务器代码不知道/不在乎文件是 XML:
[HttpPost]
[Route("api/inventory/sendXML/{userId}/{pwd}/{filename}")]
public async Task SendInventoryXML(String userId, String pwd, String fileName)
{
Task task = Request.Content.ReadAsStreamAsync().ContinueWith(t =>
{
var stream = t.Result;
using (FileStream fileStream = File.Create(String.Format(@"C:\HDP\{0}.xml", fileName), (int)stream.Length))
{
byte[] bytesInStream = new byte[stream.Length];
stream.Read(bytesInStream, 0, (int)bytesInStream.Length);
fileStream.Write(bytesInStream, 0, bytesInStream.Length);
}
});
}
更新 2
我试着让 Charles 看看它是否会接收本地 HTTP 流量,但它也对这种情况充耳不闻(就像 Fiddler,无论如何都没有特殊的服务)。这是 Charles 在收到“400 - Bad Request”错误后的样子:
更新 3
我在某个地方找到了这个建议,让 Fiddler 显示本地 HTTP 流量:
Tools--> Fiddler Options. Choose Connections tab. Check the 'USe PAC Script' option.
...但它不起作用 - 在收到“400(错误请求)”消息时,我仍然看不到 HTTP 流量。
更新 4
我现在也在 Fiddler 2 中看到“400(错误请求)”;为了得到它,我在 Postman 中输入以下任何内容(从 CE/CF/手持应用程序调用时,在 Fiddler 中看不到这个):
http://SHANNON2:21608/api/inventory/sendXML/su/su/blablee // Hostname
http://SHANNON2.:21608/api/inventory/sendXML/su/su/blablee // Hostname with Fiddler-fooler appended "."
http://192.168.125.50:21608/api/inventory/sendXML/su/su/blablee // IP Address
(如果我用“localhost”替换主机名或 IP 地址,Fiddler 不会捕获任何内容)
注意:对于 Postman 中的这些 URL,我选择了“Post”(而不是 GET 等),并附加了一个 XML 文件。
Fiddler 中的 Inspectors.Headers 显示:
POST /api/inventory/sendXML/su/su/blablee HTTP/1.1
尽管我认为这是一次小小的调试胜利,但我仍然不明白为什么会出现“400”错误。
Fiddler 在 Inspectors.WebView 窗格中告诉我:
Bad Request - Invalid Hostname
--------------------------------------------------------------------------------
HTTP Error 400. The request hostname is invalid.
这个怎么可能?当我从 Postman 运行它时,我在服务器中打断点 - 如果主机名无效,为什么会到达它?
更新 5
测试来自 Fiddler Composer 和 Postman 的调用,我可以到达服务器代码中的断点的唯一方法是使用“localhost” - 用 PC 的 IPAddress (192.168.125.50) 或 HostName (SHANON2) 替换它不会到达断点。虽然“有趣”,但从手持设备调用“localhost”显然不是一种选择。
更新 6
相关的新问题在这里。
更新 7
饼干的关键是在命令提示符下添加以下内容:
netsh http add urlacl url=http://shannon2:80/ user=everyone
...或这个:
netsh http add urlacl url=http://shannon2:8080/ user=everyone
有关详细信息,请参阅此处的更新 5