为什么在“穿越Rubicon”之后,HttpWebRequest正文会为空? [英] Why is the HttpWebRequest body val null after "crossing the Rubicon"?

查看:313
本文介绍了为什么在“穿越Rubicon”之后,HttpWebRequest正文会为空?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

  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)
{
//测试查看是否找到任何行
//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();

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

正如你在注释掉代码(< =工作正常),我已经测试了,我想要的数据被添加到StringBuilder。没有异常被抛出(我看不到SendXMLFile异常)。



但是,当调用相应的服务器代码时:

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

XDocument doc = XDocument.Parse(stringifiedXML);

...serialNum和siteNum参数符合预期(包含有效期望值)但是body(stringifiedXML)为null。为什么?



更新



我也在客户端添加了这个:

  request.ContentLength = postBytes.Length; 
// sb是否进入字节数组?
MessageBox.Show(request.ContentLength.ToString());

...并且字节数组确实有数据,因为它显示112( XML文件很小)



更新2



现在我添加了另一个调试msg:

  try 
{
Stream requestStream = request.GetRequestStream();
//现在测试这个:
MessageBox.Show(string.Format(requestStream length is {0},requestStream.Length.ToString()));
requestStream.Write(postBytes,0,postBytes.Length);
requestStream.Close();

使用(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... ???



更新3



我猜这是山楂效应或类似的例子。一旦我注释掉了这个调试(MessageBox.Show())语句,我回到了将其作为服务器应用程序,但是使用[FromBody] val null。



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



更新4



stringifiedXML在这里仍然为空:

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

XDocument doc = XDocument.Parse(stringifiedXML);

...即使在对这个问题如下所示:

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

私有静态字符串GetDataFromXMLFile()
{
//测试数据 - 如果它可以工作,得到(相同的,现在)来自文件的数据
return @<?xml version = 1.0?>< LocateAndLaunch>< Tasks>< / Tasks>< Locations>< / Locations>< / LocateAndLaunch>; //必须从版本号$ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ b public static HttpWebRequest CreateRequest(string uri,HttpMethods方法,字符串数据,string contentType)
{
WebRequest request = HttpWebRequest.Create(uri);
request.Method = Enum.ToObject(typeof (HttpMethods),方法).ToString();
request.ContentType = contentType;
((HttpWebRequest)请求).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
{
//如果w我要做一个GET或DELETE,不要麻烦这个
request.ContentLength = 0;
}
//最后,将新创建的请求返回给调用者。
返回请求作为HttpWebRequest;
}

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



System.Net。 ProtocolVi ...
在请求提交后无法执行此操作。



更新5



对于想要堆栈跟踪的人,& c:



serNum和siteNum是简单的值,可以像这样连接到uri:

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

我试图得到这样的堆栈跟踪:

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

...但现在我只看到,这个操作不能在请求提交后执行。



更新6



我将方法签名更改为: / p>

  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();
返回null;
}

...但没有任何区别(我看不到StackTrave = 消息,所以它必须是失败的erstwheres)



更新7



我把两个调试字符串: / p>

0)

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

1)在SendXMLFile()中:

  // test:
MessageBox.Show(string.Format(调用CreateRequestNoCredentials()后,请求contentLen = {0},headers = {1},requestUri = {2 },
request.ContentLength,request.Headers,request.RequestUri));

...我看到这样:





...但是在第二个获得机会向我显示血腥细节之前,服务器会收到空值,因此崩溃,然后客户端用相同的旧的ges。该请求之后无法执行此操作已提交投诉。



更新8



为了回应这个建议,我怀疑如果您在CreateRequest调用后删除KeepAlive和ProtocolVersion的设置,则异常将会消失。,我更改了我的代码:

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

// test:
MessageBox.Show(string.Format(调用CreateRequestNoCredentials()后,请求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方法,字符串数据,string contentType)
{
// test:
MessageBox.Show string.Format(In CreateRequestNoCredentials(); data in in = {0},data));

WebRequest request = HttpWebRequest.Create(uri);
request.Method = Enum.ToObject(typeof(HttpMethods),方法).ToString();
request.ContentType = contentType;
((HttpWebRequest)请求).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
{
//如果我们正在做一个GET或DELETE,不要麻烦这个
request.ContentLength = 0;
}
//最后,将新创建的请求返回给调用者。
返回请求作为HttpWebRequest;
}

...至此:

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

// test:
MessageBox.Show(string.Format(调用CreateRequestNoCredentials()后,请求contentLen = {0},headers = {1},requestUri = {2} ,
request.ContentLength,request.Headers,request.RequestUri));

public static HttpWebRequest CreateRequestNoCredentials(string uri,HttpMethods方法,字符串数据,string contentType)
{
// test:
MessageBox.Show(string.Format 在CreateRequestNoCredentials();数据传入= {0},数据));

WebRequest request = HttpWebRequest.Create(uri);
request.Method = Enum.ToObject(typeof(HttpMethods),方法).ToString();
request.ContentType = contentType;
((HttpWebRequest)请求).Accept = contentType;
//从别处移到这里:
((HttpWebRequest))).KeepAlive = false;
((HttpWebRequest)请求).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
{
//如果我们正在做一个GET或DELETE,不要麻烦这个
request.ContentLength = 0;
}
//最后,将新创建的请求返回给调用者。
返回请求作为HttpWebRequest;
}

...但我仍然得到同样的错误(这个操作



更新9



当我发送我理解为我应该通过Fiddler 2(右键单击图像并在新选项卡中打开,如果你没有视觉超级大国),这是我得到的:





...但我不知道我在看什么...它是否工作?失败了吗body == 0列让我暂停/让我觉得失败,但204似乎意味着服务器成功处理了请求,但没有返回任何内容...



更新10



这是在修复uri之后的Fiddler尖叫声,并且我在服务器应用程序中达到断点,具有良好的数据发送:





更新11



更改此代码:

  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未被用户代码
HResult = -2146232000
消息=发生意外的文件结束。第1行,第15行...



无论如何,这是一个改进...



更新12



根据在小提琴中作为请求身体传递的字符串的确切构成/格式,结果有很大的不同。



作为请求正文:

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

... stringifiedXML为null



以此作为请求正文:

 <?xml version = 1.0?>< LocateAndLaunch>< Tasks>< / Tasks><位置>< / Locations>< / LocateAndLaunch>

... stringifiedXML完全一样()



...但有一个例外:



System.Xml.XmlException未被用户代码
HResult = -2146232000
Message ='1.0'是一个意外的令牌。预期的标记是'''或'''。第1行,第15位
Source = System.Xml
LineNumber = 1
LinePosition = 15
SourceUri =
StackTrace:
at System。 Xml.XmlTextReaderImpl.Throw(Exception e)
在System.Xml.XmlTextReaderImpl.Throw(String res,String [] args)
在System.Xml.XmlTextReaderImpl.ThrowUnexpectedToken(String expectedToken1,String expectedToken2)$在System.Xml.XmlTextReaderImpl.ParseXmlDeclaration(Boolean isTextDecl)上的
System.Xml.XmlTextReaderImpl.Read()中的
System.Xml.Linq.XDocument.Load中的
(XmlReader reader,LoadOptions选项)
在System.Xml.Linq.XDocument.Parse(String text,LoadOptions选项)
在System.Xml.Linq.XDocument.Parse(字符串文本)
在HandheldServer.Controllers.DeliveryItemsController。 d__2.MoveNext()在c:\HandheldServer\HandheldServer
\Controllers\DeliveryItemsController.cs:line 63
InnerException:



以此作为请求B ody:

 <?xml version =1.0?>< LocateAndLaunch>< Tasks>< /任务和GT;<位置>< /地点和GT;< / LocateAndLaunch>中

... stringifiedXML是

最后, as Request Body:

 <?xml version = \1.0\?>< LocateAndLaunch>< ;任务>< / Tasks><位置>< / Locations>< / LocateAndLaunch>

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



...但是我得到这个例外:



System.InvalidOperationException被用户代码未处理
HResult = -2146233079
消息=序列不包含元素
Source = System.Core
StackTrace:
在System.Linq.Enumerable.First [TSource](IEnumerable`1源)
在HandheldServer.Controllers.DeliveryItemsController.d__2.MoveNext()在c:\HandheldServer\HandheldServer\Controllers\DeliveryItemsController .cs:line 109
InnerException:



最后,如果我通过这个,与(有效的假)vales在角度s:

 <?xml version = \1.0\?>< LocateAndLaunch>< Tasks& ;一些任务< / Tasks><位置>一些位置< /位置>< / LocateAndLaunch>

...我STILL得到序列不包含元素



这个方法比Rachel Canning更挑剔!它想要什么 - 蛋在它的啤酒?



更新13



使用以下代码:

  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());



...这个作为传入的stringifiedXML:



某些TaskSome位置



...我得到例外:
System.Xml.XmlException被用户代码未处理
HResult = -2146232000
消息=根元素丢失。



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

  XDocument doc = XDocument.Parse(stringifiedXML); 

...我得到, System.InvalidOperationException未被用户代码
HResult = -2146233079
消息=序列不包含元素
Source = System.Core
StackTrace:
在System.Linq.Enumerable.First [TSource](IEnumerable`1 source )
在HandheldServer.Controllers.DeliveryItemsController.d__2.MoveNext()在c:\HandheldServer\HandheldServer
\Controllers\DeliveryItemsController.cs:行109
InnerException:



IOW,根据我如何解析传入的字符串,我得到根元素丢失或序列不包含元素



麦克莱恩·麦克莱恩·弗吉尼亚·韦伯什么是什么?不是< LocateAndLaunch >根元素?不是一些任务和一些位置元素?

解决方案

对于这样的操作方法

 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 
内容类型:application / json
主机:localhost:port
Content-Length:94

<?xml version = 1.0? >< LocateAndLaunch><任务和GT;< /任务与GT;<位置>< /地点和GT;< / LocateAndLaunch>中

请求体需要包含双引号BTW。因此,绑定应该正常工作。



所以,发布内容类型为 application / json 的消息,并格式化这样的身体。

  string content = @<?xml version = 1.0?>< LocateAndLaunch>< Tasks> ;< /任务与GT;<位置>< /地点和GT;< / LocateAndLaunch>中; 
string body = String.Format(\{0} \,content);

之前,您可以更改客户端代码中的任何内容,使用Fiddler发送如上所述的POST以确保它在Web API方面工作。之后,更改您的客户端,以确保它只向Fiddler的工作请求输出请求。


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

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

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

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

UPDATE

I added this, too, in the client:

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

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

UPDATE 2

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

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

UPDATE 3

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.

Then the client has the message, "Unable to read data from the transport connection"

UPDATE 4

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

...even after I modified the code in the client following a response to this question like so:

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..." "This operation cannot be performed after the request has been submitted."

UPDATE 5

For those wanting a Stack Trace, &c:

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

UPDATE 6

I changed the method signature to this:

public static HttpWebResponse SendXMLFile(string xmlFilepath, string uri)

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

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

UPDATE 7

I put two debug strings in:

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) 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:

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

UPDATE 8

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

...to 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));

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

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

UPDATE 9

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):

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

UPDATE 10

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

UPDATE 11

With changing this code:

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

...to this:

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

...I'm now getting this in stringifiedXML: "

...and so I'm now getting: "System.Xml.XmlException was unhandled by user code HResult=-2146232000 Message=Unexpected end of file has occurred. Line 1, position 15..."

It's an improvement, anyway...

UPDATE 12

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

With this as Request Body:

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

...stringifiedXML is null

With this as Request Body:

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

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

...but there is an exception:

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:

With this as Request Body:

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

...stringifiedXML is "

Penultimately, with this as Request Body:

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

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

...but I get this exception:

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:

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?!?

UPDATE 13

With this code:

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

...or this:

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

...and this as the incoming stringifiedXML:

"Some TaskSome Location"

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

With this code (same stringifiedXML):

XDocument doc = XDocument.Parse(stringifiedXML);

... 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, depending on how I parse the incoming string, I get either "Root element is missing" or "Sequence contains no elements"

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

解决方案

For the action method like this

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

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.

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

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.

这篇关于为什么在“穿越Rubicon”之后,HttpWebRequest正文会为空?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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