Encoding 为什么HttpWebRequest正文val在“0”之后为空;穿越卢比孔;?

Encoding 为什么HttpWebRequest正文val在“0”之后为空;穿越卢比孔;?,encoding,asp.net-web-api,httpwebrequest,fiddler,frombodyattribute,Encoding,Asp.net Web Api,Httpwebrequest,Fiddler,Frombodyattribute,我正在尝试将XML文件的内容从手持设备(Compact Framework/Windows CE)发送到我的服务器应用程序中的Web API方法,如(客户端代码): …serialNum和siteNum参数与预期一致(包含有效的预期值),但正文(stringifiedXML)为空。为什么? 更新 我在客户端中也添加了以下内容: request.ContentLength = postBytes.Length; // Did the sb get into the byte array? Mess

我正在尝试将XML文件的内容从手持设备(Compact Framework/Windows CE)发送到我的服务器应用程序中的Web API方法,如(客户端代码):

…serialNum和siteNum参数与预期一致(包含有效的预期值),但正文(stringifiedXML)为空。为什么?

更新 我在客户端中也添加了以下内容:

request.ContentLength = postBytes.Length;
// Did the sb get into the byte array?
MessageBox.Show(request.ContentLength.ToString());
…字节数组确实包含数据,如图“112”(XML文件非常小)

更新2 现在,我添加了另一个调试消息:

try
{
    Stream requestStream = request.GetRequestStream();
    // now test this:
    MessageBox.Show(string.Format("requestStream length is {0}", requestStream.Length.ToString()));
    requestStream.Write(postBytes, 0, postBytes.Length);
    requestStream.Close();

    using (var response = (HttpWebResponse)request.GetResponse())
    {
        return response.ToString();
    }
}
catch (Exception ex)
{
    MessageBox.Show("SendXMLFile exception " + ex.Message);
    request.Abort();
    return string.Empty;
}
…我甚至没有看到“requestStream length is”消息;相反,我看到,“SendXMLFileException不支持Exception”

更新3 我想这是山楂效应或类似效应的一个例子。一旦我注释掉了debug(MessageBox.Show())语句,我就回到了服务器应用程序中,但是[FromBody]val为null

然后,客户端收到消息“无法从传输连接读取数据”

更新4 stringifiedXML在此处仍然为空:

public async void PostArgsAndXMLFileAsStr([FromBody] string stringifiedXML, string serialNum, string siteNum)
{
    string beginningInvoiceNum = string.Empty;
    string endingInvoiceNum = string.Empty;

    XDocument doc = XDocument.Parse(stringifiedXML);
…即使在我根据类似的响应修改了客户端中的代码之后:

我试图获得堆栈跟踪,如下所示:

catch (Exception ex)
{
    MessageBox.Show(string.Format("Msg = {0}; StackTrace = {1)", ex.Message, ex.StackTrace));
    request.Abort();
    return string.Empty;
}
…但现在我只看到,“请求提交后无法执行此操作。”

更新6 我将方法签名更改为:

public static HttpWebResponse SendXMLFile(string xmlFilepath, string uri)
try
{
    using (var response = (HttpWebResponse)request.GetResponse())
    {
        return response;
    }
}
catch (Exception ex)
{
    MessageBox.Show(string.Format("Msg = {0}; StackTrace = {1)", ex.Message, ex.StackTrace));
    request.Abort();
    return null;
}
…以及与此对应的代码:

public static HttpWebResponse SendXMLFile(string xmlFilepath, string uri)
try
{
    using (var response = (HttpWebResponse)request.GetResponse())
    {
        return response;
    }
}
catch (Exception ex)
{
    MessageBox.Show(string.Format("Msg = {0}; StackTrace = {1)", ex.Message, ex.StackTrace));
    request.Abort();
    return null;
}
…但这并没有什么区别(而且我看不到“StackTrave=”消息,所以它一定是失败了)

更新7 我将两个调试字符串放入:

0)

1) 在SendXMLFile()中:

…我看到:

…但在第二个服务器有机会向我展示血淋淋的详细信息之前,服务器接收到空的body值,然后崩溃,然后客户端发出相同的“提交请求后无法执行此操作”投诉

更新8 作为对建议的回应,“我怀疑如果在CreateRequest调用后删除KeepAlive和ProtocolVersion的设置,异常将消失。”我更改了以下代码:

    HttpWebRequest request = CreateRequestNoCredentials(uri, HttpMethods.POST, strData, "application/xml");

    //test:
    MessageBox.Show(string.Format("After calling CreateRequestNoCredentials(), request contentLen = {0}, headers = {1}, requestUri = {2}", 
        request.ContentLength, request.Headers, request.RequestUri));

    request.KeepAlive = false;
    request.ProtocolVersion = HttpVersion.Version10;


public static HttpWebRequest CreateRequestNoCredentials(string uri, HttpMethods method, string data, string contentType)
{
    //test:
    MessageBox.Show(string.Format("In CreateRequestNoCredentials(); data passed in = {0}", data));

    WebRequest request = HttpWebRequest.Create(uri);
    request.Method = Enum.ToObject(typeof(HttpMethods), method).ToString();
    request.ContentType = contentType;
    ((HttpWebRequest)request).Accept = contentType;

    if (method != HttpMethods.GET && method != HttpMethods.DELETE)
    {
        Encoding encoding = Encoding.UTF8;
        request.ContentLength = encoding.GetByteCount(data);
        request.ContentType = contentType;
        request.GetRequestStream().Write(
          encoding.GetBytes(data), 0, (int)request.ContentLength);
        request.GetRequestStream().Close();
    }
    else
    {
        // If we're doing a GET or DELETE don't bother with this 
        request.ContentLength = 0;
    }
    // Finally, return the newly created request to the caller. 
    return request as HttpWebRequest;
}
……为此:

    HttpWebRequest request = CreateRequestNoCredentials(uri, HttpMethods.POST, strData, "application/xml");

    //test:
    MessageBox.Show(string.Format("After calling CreateRequestNoCredentials(), request contentLen = {0}, headers = {1}, requestUri = {2}", 
        request.ContentLength, request.Headers, request.RequestUri));

public static HttpWebRequest CreateRequestNoCredentials(string uri, HttpMethods method, string data, string contentType)
{
    //test:
    MessageBox.Show(string.Format("In CreateRequestNoCredentials(); data passed in = {0}", data));

    WebRequest request = HttpWebRequest.Create(uri);
    request.Method = Enum.ToObject(typeof(HttpMethods), method).ToString();
    request.ContentType = contentType;
    ((HttpWebRequest)request).Accept = contentType;
    // moved from elsewhere to here:
    ((HttpWebRequest)request).KeepAlive = false;
    ((HttpWebRequest)request).ProtocolVersion = HttpVersion.Version10;

    if (method != HttpMethods.GET && method != HttpMethods.DELETE)
    {
        Encoding encoding = Encoding.UTF8;
        request.ContentLength = encoding.GetByteCount(data);
        request.ContentType = contentType;
        request.GetRequestStream().Write(
          encoding.GetBytes(data), 0, (int)request.ContentLength);
        request.GetRequestStream().Close();
    }
    else
    {
        // If we're doing a GET or DELETE don't bother with this 
        request.ContentLength = 0;
    }
    // Finally, return the newly created request to the caller. 
    return request as HttpWebRequest;
}
string strData = @sb.ToString(); // GetDataFromXMLFile();
string body = String.Format("\"{0}\"", strData);
HttpWebRequest request = CreateRequestNoCredentials(uri, HttpMethods.POST, body, "application/json"); 
…但我仍然收到相同的错误消息(“在提交请求后无法执行此操作”),stringifiedXML在到达服务器时仍然为null

更新9 以下是我通过Fiddler 2发送我理解为应该发送的内容时得到的信息(如果您没有视觉超能力,请右键单击图像并在新选项卡中打开):

…但我不知道我在看什么…有用吗?失败了吗?“body==0”列让我暂停/让我认为它失败了,然而“204”似乎意味着“服务器成功地处理了请求,但没有返回任何内容”

更新10 这是修复uri后的Fiddler尖叫镜头,我确实在服务器应用程序中到达了断点,并发送了良好的数据:

更新11 更改此代码时:

string strData = sb.ToString();
HttpWebRequest request = CreateRequestNoCredentials(uri, HttpMethods.POST, strData, "application/xml");
public async void PostArgsAndXMLFileAsStr([FromBody] string stringifiedXML, string serialNum, string siteNum)
{
    XDocument doc = XDocument.Parse(await Request.Content.ReadAsStringAsync()); 
……为此:

    HttpWebRequest request = CreateRequestNoCredentials(uri, HttpMethods.POST, strData, "application/xml");

    //test:
    MessageBox.Show(string.Format("After calling CreateRequestNoCredentials(), request contentLen = {0}, headers = {1}, requestUri = {2}", 
        request.ContentLength, request.Headers, request.RequestUri));

public static HttpWebRequest CreateRequestNoCredentials(string uri, HttpMethods method, string data, string contentType)
{
    //test:
    MessageBox.Show(string.Format("In CreateRequestNoCredentials(); data passed in = {0}", data));

    WebRequest request = HttpWebRequest.Create(uri);
    request.Method = Enum.ToObject(typeof(HttpMethods), method).ToString();
    request.ContentType = contentType;
    ((HttpWebRequest)request).Accept = contentType;
    // moved from elsewhere to here:
    ((HttpWebRequest)request).KeepAlive = false;
    ((HttpWebRequest)request).ProtocolVersion = HttpVersion.Version10;

    if (method != HttpMethods.GET && method != HttpMethods.DELETE)
    {
        Encoding encoding = Encoding.UTF8;
        request.ContentLength = encoding.GetByteCount(data);
        request.ContentType = contentType;
        request.GetRequestStream().Write(
          encoding.GetBytes(data), 0, (int)request.ContentLength);
        request.GetRequestStream().Close();
    }
    else
    {
        // If we're doing a GET or DELETE don't bother with this 
        request.ContentLength = 0;
    }
    // Finally, return the newly created request to the caller. 
    return request as HttpWebRequest;
}
string strData = @sb.ToString(); // GetDataFromXMLFile();
string body = String.Format("\"{0}\"", strData);
HttpWebRequest request = CreateRequestNoCredentials(uri, HttpMethods.POST, body, "application/json"); 
…我现在在stringifiedXML中得到这个: …所以我现在得到了:“System.Xml.XmlException没有被用户代码处理 HResult=-2146232000 Message=发生意外的文件结尾。第1行,位置15…”

无论如何,这是一个进步

更新12 根据Fiddle中作为“Request Body”传递的字符串的确切组成/格式,结果会有很大的不同

作为请求机构:

<?xml version="1.0"?><LocateAndLaunch><Tasks></Tasks><Locations></Locations></LocateAndLaunch>
"<?xml version=1.0?><LocateAndLaunch><Tasks></Tasks><Locations></Locations></LocateAndLaunch>"
"<?xml version="1.0"?><LocateAndLaunch><Tasks></Tasks><Locations></Locations></LocateAndLaunch>"
"<?xml version=\"1.0\"?><LocateAndLaunch><Tasks></Tasks><Locations></Locations></LocateAndLaunch>"
……或者:

…XDocument doc=XDocument.Load(wait Request.Content.ReadAsStreamAsync())

…这将作为传入的stringifiedXML:

XDocument doc = XDocument.Parse(stringifiedXML);
“某些任务某些位置”

…我得到一个例外: “System.Xml.XmlException未由用户代码处理 HResult=-2146232000 消息=缺少根元素。“

使用此代码(相同的stringifiedXML):

…我得到,“System.InvalidOperationException未由用户代码处理 HResult=-2146233079 Message=序列不包含任何元素 Source=System.Core 堆栈跟踪: 在System.Linq.Enumerable.First[TSource](IEnumerable`1 source)处 位于c:\HandheldServer\HandheldServer中的HandheldServer.Controllers.DeliveryItemsController.d_u2.MoveNext() \Controllers\DeliveryItemsController.cs:第109行 内部异常:“

根据我解析传入字符串的方式,我会得到“根元素丢失”或“序列不包含元素”


什么是Deuce McAlistair MacLean Virginia Weeper?!?“
”不是根元素吗?不是“一些任务”和“一些位置”元素吗?

对于这样的操作方法

public async void PostArgsAndXMLFileAsStr([FromBody] string stringifiedXML,
                                              string serialNum, string siteNum)
{}
请求消息必须是这样的。我在这里使用JSON

POST http://localhost:port/api/values/PostArgsAndXMLFileAsStr?serialNum=1&siteNum=2 HTTP/1.1
Content-Type: application/json
Host: localhost:port
Content-Length: 94

"<?xml version=1.0?><LocateAndLaunch><Tasks></Tasks><Locations></Locations></LocateAndLaunch>"

在更改客户端代码之前,请使用Fiddler发送类似于上述内容的帖子,以确保其在web API端工作。之后,更改客户端以确保其输出的请求仅与Fiddler的工作请求相同。

堆栈跟踪是什么?此处没有足够的信息。首先,请说出“serialNum”和“siteNum“args与预期的一样。我不知道它们从何而来。它们是否以某种方式来自请求?此外,返回
response.ToString()
不会给您任何有用的信息。返回
response.GetResponseStream().ToString()也不会给您任何有用的信息
。如果要返回文本,必须从响应流中创建一个
StreamReader
,并读取数据。查看
StreamReader.ReadToEnd
方法,该方法将读取并返回字符串中的全部内容。显示协议冲突异常的完整堆栈跟踪,并告诉我们发生在哪一行。更好的是,你的代码可以单独识别问题。你可以考虑获取小提琴手并查看从客户机流出的数据。如果POST数据在请求中(正如我猜想的那样)。,则问题出在服务器上。当然,您必须将更改还原到客户端,或者找出如何破坏它。可能是因为您正在设置请求的属性而引发异常
XDocument doc = XDocument.Parse(stringifiedXML);
public async void PostArgsAndXMLFileAsStr([FromBody] string stringifiedXML,
                                              string serialNum, string siteNum)
{}
POST http://localhost:port/api/values/PostArgsAndXMLFileAsStr?serialNum=1&siteNum=2 HTTP/1.1
Content-Type: application/json
Host: localhost:port
Content-Length: 94

"<?xml version=1.0?><LocateAndLaunch><Tasks></Tasks><Locations></Locations></LocateAndLaunch>"
string content = @"<?xml version=1.0?><LocateAndLaunch><Tasks></Tasks><Locations></Locations></LocateAndLaunch>";
string body = String.Format("\"{0}\"", content);