从 Compact Framework 客户端进行 REST 调用时,如何避免“错误请求 - 无效主机名”错误?

B. *_*non 4 c# compact-framework webrequest webresponse stream

我用这个代码在这里尝试调用REST控制器方法从一个Compact Framework的客户端的Web API的服务器应用程序:

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 ();
}
Run Code Online (Sandbox Code Playgroud)

...我早些时候曾尝试过这段代码,这是我从“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());
}
Run Code Online (Sandbox Code Playgroud)

...但我收到“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;
}
Run Code Online (Sandbox Code Playgroud)

还有更多关于我在这里尝试过的大量变体,我已经达到了我的帖子长度限制。

更新

请注意,服务器代码不知道/关心文件是 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);
        }
    });
}
Run Code Online (Sandbox Code Playgroud)

更新 2

我试过 Charles 看看它是否会接收本地 HTTP 流量,但它也对这种情况充耳不闻(就像 Fiddler,无论如何都没有特殊的服务)。这是 Charles 在收到“400 - Bad Request”错误后的样子:

在此处输入图片说明

更新 3

我在某处找到了这个建议,让 Fiddler 显示本地 HTTP 流量:

Tools--> Fiddler Options. Choose Connections tab. Check the 'USe PAC Script' option.
Run Code Online (Sandbox Code Playgroud)

...但它不起作用 - 在收到“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
Run Code Online (Sandbox Code Playgroud)

(如果我用“localhost”替换主机名或 IP 地址,Fiddler 不会捕获任何内容)

注意:对于 Postman 中的这些 URL,我选择了“Post”(而不是 GET 等),并附加了一个 XML 文件。

Fiddler 中的 Inspectors.Headers 显示:

POST /api/inventory/sendXML/su/su/blablee HTTP/1.1
Run Code Online (Sandbox Code Playgroud)

虽然我认为这是一个小小的调试胜利,但我仍然不明白为什么我会收到“400”错误。

Fiddler 在 Inspectors.WebView 窗格中告诉我:

Bad Request - Invalid Hostname

--------------------------------------------------------------------------------

HTTP Error 400. The request hostname is invalid.
Run Code Online (Sandbox Code Playgroud)

怎么可能?当我从 Postman 运行它时,我遇到了服务器中的断点 - 如果主机名无效,为什么会到达它?

更新 5

测试来自 Fiddler Composer 和 Postman 的调用,我可以在服务器代码中到达断点的唯一方法是使用“localhost” - 将其替换为 PC 的 IP 地址 (192.168.125.50) 或主机名 (SHANNON2) 不会到达断点。虽然“有趣”,但从手持设备调用“localhost”显然不是一种选择。

更新 6

相关的新问题在这里。

更新 7

饼干的关键是在命令提示符下添加:

netsh http add urlacl url=http://shannon2:80/ user=everyone
Run Code Online (Sandbox Code Playgroud)

...或这个:

netsh http add urlacl url=http://shannon2:8080/ user=everyone
Run Code Online (Sandbox Code Playgroud)

有关更多详细信息,请参阅此处的更新 5

Kus*_*eth 9

添加我的观察,如果您在从 Postman 调用 API 时遇到问题Bad Request - Invalid Hostname。像这样的东西。

在此处输入图片说明

考虑在 Headers 中添加Host,它会起作用。

在此处输入图片说明


B. *_*non 0

饼干的关键是在命令提示符下添加以下内容:

netsh http add urlacl url=http://shannon2:80/ user=everyone
Run Code Online (Sandbox Code Playgroud)

...或这个:

netsh http add urlacl url=http://shannon2:8080/ user=everyone
Run Code Online (Sandbox Code Playgroud)

请参阅此处的更新 5了解更多详细信息