为什么HttpWebRequest的身体VAL空后"穿越卢比肯"? [英] Why is the HttpWebRequest body val null after "crossing the Rubicon"?

查看:417
本文介绍了为什么HttpWebRequest的身体VAL空后"穿越卢比肯"?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想从手持设备发送XML文件的内容(Compact Framework中/ Windows CE的)到Web API方法在我的服务器应用程序像这样(客户端code):

I am trying to send the contents of an XML file from a handheld device (Compact Framework/Windows CE) to a Web API method in my server app like so (Client code):

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

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

    request.Method = "POST";

    StringBuilder sb = new StringBuilder();
    using (StreamReader sr = new StreamReader(xmlFilepath))
    {
        String line;
        while ((line = sr.ReadLine()) != null)
        {
            // test to see if it's finding any lines
            //MessageBox.Show(line); <= works fine
            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/xml";

        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("SendXMLFile exception " + ex.Message);
            request.Abort();
            return string.Empty;
        }
    }
}

正如你可以在注释掉code见(&LT; =正常工作),我测试过它,我想要的数据被添加到StringBuilder。没有引发异常(我不明白SendXMLFile例外)。

As you can see in the commented out code ("<= works fine"), I've tested it and the data I want is being added to the StringBuilder. There is no exception being thrown (I don't see "SendXMLFile exception ").

然而,当相应的服务器code被称为:

However, when the corresponding server code is called:

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

    XDocument doc = XDocument.Parse(stringifiedXML);

...在SERIALNUM和siteNumARG游戏如预期(包含有效的预期值),但身体(stringifiedXML)为null。为什么呢?

...the "serialNum" and "siteNum" args are as expected (contain the valid expected values) but the body (stringifiedXML) is null. Why?

我说这也算在客户端:

request.ContentLength = postBytes.Length;
// Did the sb get into the byte array?
MessageBox.Show(request.ContentLength.ToString());

...和字节数组确实有数据,因为它显示了我112(XML文件是相当小)。

...and the byte array does have the data, as it shows me "112" (the XML file is quite small).

现在我添加另一个调试信息:

Now I added yet another debug msg:

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长的消息;相反,我明白了,SendXMLFileException引发NotSupportedException... ???

...and I don't even see the "requestStream length is" message; instead I see, "SendXMLFileException NotSupportedException"...???

我想这是霍桑效应或类似的例子。有一次,我注释掉了调试(MessageBox.Show())语句,我回到使它成为服务器的应用程序,但使用[FromBody] VAL空。

I guess this is an example of the Hawthorn Effect or similar. Once I commented out that debug (MessageBox.Show()) statement, I'm back to making it into the server app, but with the [FromBody] val null.

然后客户有消息的无法读取传输连接的数据

stringifiedXML仍然是空的位置:

stringifiedXML is still null here:

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

    XDocument doc = XDocument.Parse(stringifiedXML);

...我修改了客户端code即使下面的响应,以<一个href=\"http://stackoverflow.com/questions/22360763/does-this-httpwebrequest-httpwebresponse-streamreader-$c$c-even-make-sense\">this问题像这样:

public static string SendXMLFile(string xmlFilepath, string uri)
{
    MessageBox.Show(string.Format("In SendXMLFile() - xmlFilepath == {0}, uri == {1}", xmlFilepath, uri));
    string strData = GetDataFromXMLFile();
    HttpWebRequest request = CreateRequest(uri, HttpMethods.POST, strData, "application/xml");

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

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

private static string GetDataFromXMLFile()
{
    // test data - if it works, get the (same, for now) data from the file
    return @"<?xml version=1.0?><LocateAndLaunch><Tasks></Tasks><Locations></Locations></LocateAndLaunch>";  //had to remove "s from version num
}

// Based on code from Andy Wiggly (the owner of Wiggly Field in Chicago and the Wiggly chewing gum company?)
public static HttpWebRequest CreateRequest(string uri, HttpMethods method, string data, string contentType)
{
    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;
}

注意:我不知道这是否是关闭服务器的只是一个误导性的副作用,但我后来看到这个错误信息在客户机/手持式应用:

Note: I don't know if this is just a misleading side-effect of shutting down the server, but I subsequently saw this err msg in the client/handheld app:

System.Net.ProtocolVi ...
请求已提交后不能执行此操作。

对于那些想要一个堆栈跟踪,和C:

For those wanting a Stack Trace, &c:

SERNUM和siteNum是得到串连成的URI像这样简单的值:

serNum and siteNum are simple values that get concatenated into the uri like so:

string uri = string.Format("http://192.168.125.50:28642/api/FileTransfer/GetHHSetupUpdate?serialNum={0}&clientVersion={1}", serNum, clientVer);

我试图让堆栈跟踪,像这样:

I tried to get the Stack Trace like so:

catch (Exception ex)
{
    MessageBox.Show(string.Format("Msg = {0}; StackTrace = {1)", ex.Message, ex.StackTrace));
    request.Abort();
    return string.Empty;
}

......但现在我只能看到无法在请求已提交后执行此操作。

...but now I'm only seeing, "This operation cannot be performed after the request has been submitted."

我改变了方法签名这样:

I changed the method signature to this:

public static HttpWebResponse SendXMLFile(string xmlFilepath, string uri)

...和相应的code这样:

...and the corresponding code to this:

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 =消息,所以必须失败erstwheres)

...but it made no difference (and I see no "StackTrave = " message, so it must be failing erstwheres)

我把两个调试字符串:

0)

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

1)在SendXMLFile():

1) In SendXMLFile():

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

...我看到以下内容:

...and I see this:

...但随后的第二个得到一个机会展示我的血淋淋的细节之前,服务器接收空体价值,崩溃thuswith,然后在客户whin [G] ES与同老此操作无法该请求已提交后进行投诉。

...but then before the second one gets a chance to show me the gory details, the server receives the null body value, crashes thuswith, and then the client whin[g]es with the same old "This operation cannot be performed after the request has been submitted" complaint.

在应对建议,我怀疑如果你的createRequest电话后删除连接的存活ProtocolVersion的设置,异常会自行消失。的,我改变了我的code从这样的:

In response to the suggestion, "I suspect that if you remove the setting of KeepAlive and ProtocolVersion after the CreateRequest call, the exception will go away.", I changed my code from this:

    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;
}

......,但我仍然得到同样的错误信息(以下简称申请已提交后不能执行此操作),并stringifiedXML仍然是空当它击中服务器。

...and yet I still get that same err msg ("This operation cannot be performed after the request has been submitted") and stringifiedXML is still null when it hits the server.

下面是我所得到的,当我送我的理解通过的提琴手2(右键单击图像并打开一个新标签,如果你没有视觉超级大国)是我应该:

Here is what I get when I send what I understand to be what I should via Fiddler 2 (right-click the image and open in a new tab if you don't have visual superpowers):

...但我不知道我在看......有用吗?它是否失败? 体== 0栏目让我暂停/让我觉得它失败了,但204似乎是指服务器成功处理了请求,但没有返回任何内容...

...but I don't know what I'm looking at...did it work? Did it fail? The "body == 0" column gives me pause/makes me think it failed, yet "204" seems to mean "The server successfully processed the request, but is not returning any content"...

下面是提琴手尖叫拍摄固定URI后,我做达到服务器应用的断点,具有良好的数据发送:

Here is the Fiddler scream shot after fixing the uri, and I do reach the breakpoint in the server app, with good data sent:

通过改变这个code:

With changing this code:

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

...这样:

string strData = @sb.ToString(); // GetDataFromXMLFile();
string body = String.Format("\"{0}\"", strData);
HttpWebRequest request = CreateRequestNoCredentials(uri, HttpMethods.POST, body, "application/json"); 

...我现在stringifiedXML得到这个:

...等我现在越来越: System.Xml.XmlException是由用户code未处理
  的HResult = -2146232000
  发生消息=意外的文件结尾。 1号线,15位...

这是一个进步,反正...

It's an improvement, anyway...

根据为请求体在捣鼓传递的字符串的确切化妆/格式化,结果根本不同。

Depending on the exact makeup/formatting of the string passed as "Request Body" in Fiddle, the results differ radically.

以此为请求正文:

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

... stringifiedXML为空

...stringifiedXML is null

以此为请求正文:

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

... stringifiedXML完全相同()

...stringifiedXML is exactly the same ("")

...但有一个例外:

...but there is an exception:

* System.Xml.XmlException是由用户code未处理
  的HResult = -2146232000
  消息='1.0'是一个意外标记。预期令牌是''或'''1号线,15位。
  来源=的System.Xml
  行号= 1
  LinePosition = 15
  SourceUri =
  堆栈跟踪:
       在System.Xml.XmlTextReaderImpl.Throw(例外五)
       在System.Xml.XmlTextReaderImpl.Throw(字符串资源,字串[] args)
       在System.Xml.XmlTextReaderImpl.ThrowUnexpectedToken(字符串expectedToken1,字符串expectedToken2)
       在System.Xml.XmlTextReaderImpl.ParseXmlDeclaration(布尔isTextDecl)
       在System.Xml.XmlTextReaderImpl.Read()
       在System.Xml.Linq.XDocument.Load(XmlReader中的读者,LoadOptions选项)
       在System.Xml.Linq.XDocument.Parse(字符串文本,LoadOptions选项)
       在System.Xml.Linq.XDocument.Parse(字符串文本)
       在HandheldServer.Controllers.DeliveryItemsController.d__2.MoveNext()在C:\\ HandheldServer \\ HandheldServer
\\ \\控制器DeliveryItemsController.cs:行63
  的InnerException:*

*System.Xml.XmlException was unhandled by user code HResult=-2146232000 Message='1.0' is an unexpected token. The expected token is '"' or '''. Line 1, position 15. Source=System.Xml LineNumber=1 LinePosition=15 SourceUri="" StackTrace: at System.Xml.XmlTextReaderImpl.Throw(Exception e) at System.Xml.XmlTextReaderImpl.Throw(String res, String[] args) at System.Xml.XmlTextReaderImpl.ThrowUnexpectedToken(String expectedToken1, String expectedToken2) at System.Xml.XmlTextReaderImpl.ParseXmlDeclaration(Boolean isTextDecl) at System.Xml.XmlTextReaderImpl.Read() at System.Xml.Linq.XDocument.Load(XmlReader reader, LoadOptions options) at System.Xml.Linq.XDocument.Parse(String text, LoadOptions options) at System.Xml.Linq.XDocument.Parse(String text) at HandheldServer.Controllers.DeliveryItemsController.d__2.MoveNext() in c:\HandheldServer\HandheldServer \Controllers\DeliveryItemsController.cs:line 63 InnerException:*

以此为请求正文:

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

... stringifiedXML是

Penultimately,以此为请求正文:

...stringifiedXML is "

Penultimately, with this as Request Body:

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

... stringifiedXML是完全一样的东西()

...stringifiedXML is exactly the same thing ("")

...但我得到这个异​​常:

...but I get this exception:

* System.InvalidOperationException了用户code未处理
  的HResult = -2146233079
  消息=序列不包含任何元素
  来源= System.Core程序
  堆栈跟踪:
       在System.Linq.Enumerable.First [TSource](IEnumerable`1源)
       在HandheldServer.Controllers.DeliveryItemsController.d__2.MoveNext()在C:\\ HandheldServer \\ HandheldServer \\ \\控制器DeliveryItemsController.cs:109线
  的InnerException:*

*System.InvalidOperationException was unhandled by user code HResult=-2146233079 Message=Sequence contains no elements Source=System.Core StackTrace: at System.Linq.Enumerable.First[TSource](IEnumerable`1 source) at HandheldServer.Controllers.DeliveryItemsController.d__2.MoveNext() in c:\HandheldServer\HandheldServer\Controllers\DeliveryItemsController.cs:line 109 InnerException:*

最后,如果我通过这一点,用(尽管假的)的angulars内丘壑:

And finally, if I pass this, with (albeit bogus) vals within the angulars:

"<?xml version=\"1.0\"?><LocateAndLaunch><Tasks>Some Task</Tasks><Locations>Some Location</Locations></LocateAndLaunch>"

...我仍然获得序列不包含任何元素

...I STILL get "sequence contains no elements"

这方法比瑞秋坎宁更挑剔!它想要什么 - 卵子在其啤酒?!?

This method is more picky than Rachel Canning! What does it want - egg in its beer?!?

有了这个code:

public async void PostArgsAndXMLFileAsStr([FromBody] string stringifiedXML, string serialNum, string siteNum)
{
    XDocument doc = XDocument.Parse(await Request.Content.ReadAsStringAsync()); 

...或本:

。 。 .XDocument DOC = XDocument.Load(等待Request.Content.ReadAsStreamAsync());

. . .XDocument doc = XDocument.Load(await Request.Content.ReadAsStreamAsync());

...和这个作为入stringifiedXML:

...and this as the incoming stringifiedXML:

一些TaskSome位置

...我得到异常:
 的System.Xml.XmlException是由用户code未处理
  的HResult = -2146232000
  消息=缺少根元素。

...I get the exception: "System.Xml.XmlException was unhandled by user code HResult=-2146232000 Message=Root element is missing."

有了这个code(相同stringifiedXML):

With this code (same stringifiedXML):

XDocument doc = XDocument.Parse(stringifiedXML);

...我得到的,* System.InvalidOperationException了用户code未处理
  的HResult = -2146233079
  消息=序列不包含任何元素
  来源= System.Core程序
  堆栈跟踪:
       在System.Linq.Enumerable.First [TSource](IEnumerable`1源)
       在HandheldServer.Controllers.DeliveryItemsController.d__2.MoveNext()在C:\\ HandheldServer \\ HandheldServer
\\ \\控制器DeliveryItemsController.cs:109线
  的InnerException:*

... I get, "*System.InvalidOperationException was unhandled by user code HResult=-2146233079 Message=Sequence contains no elements Source=System.Core StackTrace: at System.Linq.Enumerable.First[TSource](IEnumerable`1 source) at HandheldServer.Controllers.DeliveryItemsController.d__2.MoveNext() in c:\HandheldServer\HandheldServer \Controllers\DeliveryItemsController.cs:line 109 InnerException: "*

IOW,这取决于我如何解析传入的字符串,我得到的不是根元素是缺少或序列不包含任何元素

IOW, depending on how I parse the incoming string, I get either "Root element is missing" or "Sequence contains no elements"

真见鬼McAlistair麦克莱恩弗吉尼亚爱哭鬼?​​!?是不是&LT; LocateAndLaunch >根元素?是不是有些任务和某个位置的元素?

What the Deuce McAlistair MacLean Virginia Weeper?!? Isn't "<LocateAndLaunch>" a root element? Aren't "Some Task" and "Some Location" elements?

推荐答案

对于这样的操作方法

public async void PostArgsAndXMLFileAsStr([FromBody] string stringifiedXML,
                                              string serialNum, string siteNum)
{}

请求消息必须是这样。我在这里使用JSON。

the request message must be like this. I use JSON here.

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>"

请求体需要包含双引号,顺便说一句。有了这个,结合应该正常工作。

The request body needs to contain the double quotes, BTW. With this, binding should work correctly.

所以,张贴与​​内容类型的信息应用程序/ JSON 和格式化身体这个样子。

So, post the message with content type application/json and format the body like this.

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

之前,您更改客户端code什么,使用Fiddler发送类似上面的一个POST以确保它在Web API的一面。在此之后,改变你的客户端,以确保它输出的要求只是提琴手工作要求。

Before, you change anything in the client side code, use Fiddler to send a POST like the one above to ensure it works in the web API side. After that, change your client side to make sure it outputs the request just the working request with Fiddler.

这篇关于为什么HttpWebRequest的身体VAL空后&QUOT;穿越卢比肯&QUOT;?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆