为什么使用 HttpWebResponse 时会收到错误请求(代码 400)?
Why do I get a bad request (code 400) with HttpWebReponse?
我正在向 WCF 服务器应用程序发送一条简单的 json 消息。
Json 留言:
{"Name":"Julian", "Id":123}
客户端代码:
public string MakeRequest(string parameters)
{
Console.WriteLine("parameters:" + parameters);
var request = (HttpWebRequest)WebRequest.Create(EndPoint);
request.Method = Method.ToString();
request.ContentLength = 0;
request.ContentType = ContentType;
Console.WriteLine("request: " + request.Headers.ToString());
if (PostData != null && Method == HttpVerb.POST)
{
var encoding = new UTF8Encoding();
var bytes = ObjectToByteArray(PostData);
request.ContentLength = bytes.Length;
Console.WriteLine("Content length: " + request.ContentLength);
using (var writeStream = request.GetRequestStream())
{
writeStream.Write(bytes, 0, bytes.Length);
}
}
try
{
using (var response = (HttpWebResponse)request.GetResponse())
{
var responseValue = string.Empty;
if (response.StatusCode != HttpStatusCode.OK)
{
var message = String.Format("Request failed. Received HTTP {0}", response.StatusCode);
throw new ApplicationException(message);
}
// grab the response
using (var responseStream = response.GetResponseStream())
{
if (responseStream != null)
using (var reader = new StreamReader(responseStream))
{
responseValue = reader.ReadToEnd();
}
}
return responseValue;
}
}
catch (WebException exception)
{
string responseText;
using (var reader = new StreamReader(exception.Response.GetResponseStream()))
{
responseText = reader.ReadToEnd();
return responseText;
}
}
private byte[] ObjectToByteArray(object obj)
{
if (obj == null)
return null;
BinaryFormatter bf = new BinaryFormatter();
using (MemoryStream ms = new MemoryStream())
{
bf.Serialize(ms, obj);
return ms.ToArray();
}
}
服务器端代码:
[WebInvoke(Method = "POST",
ResponseFormat = WebMessageFormat.Json,
RequestFormat =WebMessageFormat.Json,
UriTemplate = "/postdata")]
public Person PostData(Person data)
{
//Return new person with data inputted from json message
return new Person()
{
Id = data.Id,
Name = data.Name
};
}
服务器配置文件
<?xml version="1.0"?>
<configuration>
<system.serviceModel>
<services>
<service name="WcfJsonRestService.Service1" behaviorConfiguration="Metadata">
<host>
<baseAddresses>
<add baseAddress="http://localhost:8732/service1"/>
</baseAddresses>
</host>
<endpoint address="http://localhost:8732/service1"
binding="webHttpBinding"
contract="WcfJsonRestService.IService1"/>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="Metadata">
<serviceMetadata httpGetEnabled="true" policyVersion="Policy15"/>
<serviceDebug includeExceptionDetailInFaults="true"/>
</behavior>
</serviceBehaviors>
<endpointBehaviors>
<behavior>
<webHttp />
</behavior>
</endpointBehaviors>
</behaviors>
</system.serviceModel>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/>
</startup>
</configuration>
关于代码:
- (客户端)MakeRequest方法的输入就是上面显示的json数据。
- (客户端)发布到的 Uri 只是 "localhost:8732/service1/postdata"(是的,包括 http:// 只是不能在这里包含它,因为它算作 link,我只能有显然是两个)
- (服务器端)服务器代码是我在代码项目中找到的此解决方案的实现:
我试过的:
- 我已经使用 Postman POST 将 json 消息发送到上述 uri 并收到了响应(目前它只是 returns 具有相同数据的包裹)所以我很难在 uri 中找到任何问题。
- 我已经使用 JSONLint 验证了 json 包。
- 我添加了各种 try/catch 块来获取更多错误信息,但它们都相当于协议 error/bad 请求错误代码 400。
- 我也曾在脑海里砸过东西(对我的室友来说更便宜也更不用担心)
当前输出:
我从服务器收到错误的请求响应,没有数据。
更新一:
我一定是弄错了数据转换顺序。在我之前:
- 创建了 Person 对象
- 将 Person 对象转换为 json
- 已将 json 传递给 MakeRequest 方法
- (在 MakeRequest 中)创建了将 json 转换为字节数组
的 WebRequest
MakeRequest() 方法(客户端)的第一个 if 语句已更新为使用 json 原样 发出请求的代码段.我现在在 write.Flush() 执行时收到协议违规错误:
更新客户端代码(MakeRequest 方法)
if (PostData != null && Method == HttpVerb.POST)
{
//var encoding = new UTF8Encoding();
//var bytes = ObjectToByteArray(PostData);
//request.ContentLength = bytes.Length;
//Console.WriteLine("Content length: " + request.ContentLength);
//using (var writeStream = request.GetRequestStream())
//{
// writeStream.Write(bytes, 0, bytes.Length);
//}
using (var streamWriter = new StreamWriter(request.GetRequestStream()))
{
streamWriter.Write(json);
streamWriter.Flush();
streamWriter.Close();
}
var httpResponse = (HttpWebResponse)request.GetResponse();
using (var streamReader = new StreamReader(httpResponse.GetResponseStream()))
{
var result = streamReader.ReadToEnd();
}
}
更新二:
streamWriter.Flush() 调用的协议违反错误是因为我没有设置 request.ContentLenth。我现在已将 Content.Length 设置为 json.Length,现在出现此错误:
图片有点小,但错误信息是:
"System.ArgumentException: Stream was not readable."
当你读到一个流的末尾时,你必须从头开始寻找它。
你可以试试这个:
StreamReader sr = new StreamReader(stream);
sr.ReadToEnd();
stream.Seek(0, SeekOrigin.Begin);
sr.ReadToEnd(); // This should work now
我认为问题出在 try 块的第一行。我尝试读取来自 请求对象 的响应 ... 嗯 ... 尽管我确实尝试进一步读取来自 响应对象 的响应下来损坏已经完成。我在下面包含了工作代码以及导致问题的注释掉的代码。我已经用 **** 标记了有问题的 request.GetResponse() 以及您会很高兴听到的正确 response.GetResponseStream(),现在可以自由地完成它的工作了。
希望这可以节省很多人的时间!
MakeRequest方法的所有相关部分:
var request = (HttpWebRequest)WebRequest.Create(EndPoint);
request.Method = Method.ToString();
request.ContentLength = 0;
request.ContentType = ContentType;
Console.WriteLine("request: " + request.Headers.ToString());
if (PostData != null && Method == HttpVerb.POST)
{
Console.WriteLine("json length: " + json.Length);
Console.WriteLine(json);
request.ContentLength = json.Length;
var encoding = new UTF8Encoding();
using (var streamWriter = new StreamWriter(request.GetRequestStream()))
{
streamWriter.Write(json);
streamWriter.Flush();
streamWriter.Close();
}
}
try
{
// **** FIRST READ USING request.GetResponse() ****
//var httpResponse = (HttpWebResponse)request.GetResponse();
//using (var streamReader = new StreamReader(httpResponse.GetResponseStream()))
//{
// streamReader.ReadToEnd();
//}
using (var response = (HttpWebResponse)request.GetResponse())
{
var responseValue = string.Empty;
if (response.StatusCode != HttpStatusCode.OK)
{
var message = String.Format("Request failed. Received HTTP {0}", response.StatusCode);
throw new ApplicationException(message);
}
// grabs the response
using (var responseStream = response.GetResponseStream())
{
if (responseStream != null)
using (var reader = new StreamReader(responseStream))
{
// **** SECOND READ USING response.GetResponseStream() ****
responseValue = reader.ReadToEnd();
}
}
return responseValue;
}
}
我正在向 WCF 服务器应用程序发送一条简单的 json 消息。
Json 留言:
{"Name":"Julian", "Id":123}
客户端代码:
public string MakeRequest(string parameters)
{
Console.WriteLine("parameters:" + parameters);
var request = (HttpWebRequest)WebRequest.Create(EndPoint);
request.Method = Method.ToString();
request.ContentLength = 0;
request.ContentType = ContentType;
Console.WriteLine("request: " + request.Headers.ToString());
if (PostData != null && Method == HttpVerb.POST)
{
var encoding = new UTF8Encoding();
var bytes = ObjectToByteArray(PostData);
request.ContentLength = bytes.Length;
Console.WriteLine("Content length: " + request.ContentLength);
using (var writeStream = request.GetRequestStream())
{
writeStream.Write(bytes, 0, bytes.Length);
}
}
try
{
using (var response = (HttpWebResponse)request.GetResponse())
{
var responseValue = string.Empty;
if (response.StatusCode != HttpStatusCode.OK)
{
var message = String.Format("Request failed. Received HTTP {0}", response.StatusCode);
throw new ApplicationException(message);
}
// grab the response
using (var responseStream = response.GetResponseStream())
{
if (responseStream != null)
using (var reader = new StreamReader(responseStream))
{
responseValue = reader.ReadToEnd();
}
}
return responseValue;
}
}
catch (WebException exception)
{
string responseText;
using (var reader = new StreamReader(exception.Response.GetResponseStream()))
{
responseText = reader.ReadToEnd();
return responseText;
}
}
private byte[] ObjectToByteArray(object obj)
{
if (obj == null)
return null;
BinaryFormatter bf = new BinaryFormatter();
using (MemoryStream ms = new MemoryStream())
{
bf.Serialize(ms, obj);
return ms.ToArray();
}
}
服务器端代码:
[WebInvoke(Method = "POST",
ResponseFormat = WebMessageFormat.Json,
RequestFormat =WebMessageFormat.Json,
UriTemplate = "/postdata")]
public Person PostData(Person data)
{
//Return new person with data inputted from json message
return new Person()
{
Id = data.Id,
Name = data.Name
};
}
服务器配置文件
<?xml version="1.0"?>
<configuration>
<system.serviceModel>
<services>
<service name="WcfJsonRestService.Service1" behaviorConfiguration="Metadata">
<host>
<baseAddresses>
<add baseAddress="http://localhost:8732/service1"/>
</baseAddresses>
</host>
<endpoint address="http://localhost:8732/service1"
binding="webHttpBinding"
contract="WcfJsonRestService.IService1"/>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="Metadata">
<serviceMetadata httpGetEnabled="true" policyVersion="Policy15"/>
<serviceDebug includeExceptionDetailInFaults="true"/>
</behavior>
</serviceBehaviors>
<endpointBehaviors>
<behavior>
<webHttp />
</behavior>
</endpointBehaviors>
</behaviors>
</system.serviceModel>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/>
</startup>
</configuration>
关于代码:
- (客户端)MakeRequest方法的输入就是上面显示的json数据。
- (客户端)发布到的 Uri 只是 "localhost:8732/service1/postdata"(是的,包括 http:// 只是不能在这里包含它,因为它算作 link,我只能有显然是两个)
- (服务器端)服务器代码是我在代码项目中找到的此解决方案的实现:
我试过的:
- 我已经使用 Postman POST 将 json 消息发送到上述 uri 并收到了响应(目前它只是 returns 具有相同数据的包裹)所以我很难在 uri 中找到任何问题。
- 我已经使用 JSONLint 验证了 json 包。
- 我添加了各种 try/catch 块来获取更多错误信息,但它们都相当于协议 error/bad 请求错误代码 400。
- 我也曾在脑海里砸过东西(对我的室友来说更便宜也更不用担心)
当前输出:
我从服务器收到错误的请求响应,没有数据。
更新一:
我一定是弄错了数据转换顺序。在我之前:
- 创建了 Person 对象
- 将 Person 对象转换为 json
- 已将 json 传递给 MakeRequest 方法
- (在 MakeRequest 中)创建了将 json 转换为字节数组 的 WebRequest
MakeRequest() 方法(客户端)的第一个 if 语句已更新为使用 json 原样 发出请求的代码段.我现在在 write.Flush() 执行时收到协议违规错误:
更新客户端代码(MakeRequest 方法)
if (PostData != null && Method == HttpVerb.POST)
{
//var encoding = new UTF8Encoding();
//var bytes = ObjectToByteArray(PostData);
//request.ContentLength = bytes.Length;
//Console.WriteLine("Content length: " + request.ContentLength);
//using (var writeStream = request.GetRequestStream())
//{
// writeStream.Write(bytes, 0, bytes.Length);
//}
using (var streamWriter = new StreamWriter(request.GetRequestStream()))
{
streamWriter.Write(json);
streamWriter.Flush();
streamWriter.Close();
}
var httpResponse = (HttpWebResponse)request.GetResponse();
using (var streamReader = new StreamReader(httpResponse.GetResponseStream()))
{
var result = streamReader.ReadToEnd();
}
}
更新二:
streamWriter.Flush() 调用的协议违反错误是因为我没有设置 request.ContentLenth。我现在已将 Content.Length 设置为 json.Length,现在出现此错误:
图片有点小,但错误信息是:
"System.ArgumentException: Stream was not readable."
当你读到一个流的末尾时,你必须从头开始寻找它。
你可以试试这个:
StreamReader sr = new StreamReader(stream);
sr.ReadToEnd();
stream.Seek(0, SeekOrigin.Begin);
sr.ReadToEnd(); // This should work now
我认为问题出在 try 块的第一行。我尝试读取来自 请求对象 的响应 ... 嗯 ... 尽管我确实尝试进一步读取来自 响应对象 的响应下来损坏已经完成。我在下面包含了工作代码以及导致问题的注释掉的代码。我已经用 **** 标记了有问题的 request.GetResponse() 以及您会很高兴听到的正确 response.GetResponseStream(),现在可以自由地完成它的工作了。
希望这可以节省很多人的时间!
MakeRequest方法的所有相关部分:
var request = (HttpWebRequest)WebRequest.Create(EndPoint);
request.Method = Method.ToString();
request.ContentLength = 0;
request.ContentType = ContentType;
Console.WriteLine("request: " + request.Headers.ToString());
if (PostData != null && Method == HttpVerb.POST)
{
Console.WriteLine("json length: " + json.Length);
Console.WriteLine(json);
request.ContentLength = json.Length;
var encoding = new UTF8Encoding();
using (var streamWriter = new StreamWriter(request.GetRequestStream()))
{
streamWriter.Write(json);
streamWriter.Flush();
streamWriter.Close();
}
}
try
{
// **** FIRST READ USING request.GetResponse() ****
//var httpResponse = (HttpWebResponse)request.GetResponse();
//using (var streamReader = new StreamReader(httpResponse.GetResponseStream()))
//{
// streamReader.ReadToEnd();
//}
using (var response = (HttpWebResponse)request.GetResponse())
{
var responseValue = string.Empty;
if (response.StatusCode != HttpStatusCode.OK)
{
var message = String.Format("Request failed. Received HTTP {0}", response.StatusCode);
throw new ApplicationException(message);
}
// grabs the response
using (var responseStream = response.GetResponseStream())
{
if (responseStream != null)
using (var reader = new StreamReader(responseStream))
{
// **** SECOND READ USING response.GetResponseStream() ****
responseValue = reader.ReadToEnd();
}
}
return responseValue;
}
}