【发布时间】:2020-07-15 23:50:27
【问题描述】:
谁能给我举个例子,如何将SOAP 请求发布到WCF 服务并返回 SOAP 响应?基本上,Travel 客户端发送带有搜索参数的 SOAP 请求,WCF 服务检查数据库,然后发送适当的假期。
我一直收到这个错误,我使用的方法是:“远程服务器返回错误:(400) 错误请求”
【问题讨论】:
标签: wcf
谁能给我举个例子,如何将SOAP 请求发布到WCF 服务并返回 SOAP 响应?基本上,Travel 客户端发送带有搜索参数的 SOAP 请求,WCF 服务检查数据库,然后发送适当的假期。
我一直收到这个错误,我使用的方法是:“远程服务器返回错误:(400) 错误请求”
【问题讨论】:
标签: wcf
你得到的错误是因为服务器不理解 HTTP 请求。 可能是您配置的绑定或客户端级别的服务代理不正确。
或者您定义的服务需要 HTTP GET 而不是 HTTP POST。有时,添加服务引用可能不会为某些 [WebGet] 属性操作生成正确的 HTTP 谓词。客户端操作可能需要手动添加[WebGet]。
【讨论】:
要么查看SoapUI,要么找到隐藏在Visual Studio 文件夹深处的WcfTestClient (C:\Program Files\Microsoft Visual Studio 9.0\Common7\IDE)。
两者都可以连接到 WCF 服务并发送/接收 SOAP 消息。
或者创建你自己的小客户端,使用svcutil.exe:
svcutil.exe (service URL)
将为您创建一个小 *.cs 文件和一个 *.config 文件,然后您可以使用它们来调用服务。
马克
【讨论】:
您没有详细说明您在服务方面的进展情况,因此很难说。
如果这是对服务的第一次命中,则如果 WCF 未在 IIS 中正确注册,则可能会发生此错误。具体来说,.svc 扩展名需要映射到 ASP.NET ISAPI 模块。
【讨论】:
感谢您抽出时间回答这个问题。 该服务工作正常,如果客户端创建对我的 WCF 服务的引用并进行方法调用,则会发送适当的响应。
我忘了补充,我的客户端正在向我的 WCF 服务发送一个 HTTP Post 请求。 然后创建适当的响应并将其返回给客户端。
我可以读取 HTTP 请求,但是当我尝试访问 HTTP 响应时,我收到错误 -“远程服务器返回错误:(400) 错误请求”强>
当代码到达这一行时发生错误:
// Get the response.
HttpWebResponse response = request.GetResponse() as HttpWebResponse;
见下面的代码:
private void CreateMessage()
{
// Create a request using a URL that can receive a post.
WebRequest request = WebRequest.Create("http://www.XXXX.com/Feeds");
string postData = "<airport>Heathrow</airport>";
// 用户函数 request.Method = "POST";
byte[] byteArray = Encoding.UTF8.GetBytes(postData);
request.ContentType = "application/soap+xml; charset=utf-8";
request.ContentLength = byteArray.Length;
Stream dataStream = request.GetRequestStream();
dataStream.Write(byteArray, 0, byteArray.Length);
dataStream.Close();
// Get the response.
HttpWebResponse response = request.GetResponse() as HttpWebResponse;
// Display the status.
HttpContext.Current.Response.Write(((HttpWebResponse)response).StatusDescription);
// Get the stream containing content returned by the server.
dataStream = response.GetResponseStream();
// Open the stream using a StreamReader for easy access.
StreamReader reader = new StreamReader(dataStream);
// Read the content.
string responseFromServer = reader.ReadToEnd();
// Display the content.
HttpContext.Current.Response.Write(responseFromServer);
// Clean up the streams.
reader.Close();
dataStream.Close();
response.Close();
}
问候
小乔
【讨论】:
从其他 .NET 应用程序访问 WCF 服务的推荐方法是使用“连接的服务”参考。下面我将描述如何以更加手动(不建议用于生产代码)的方式创建和发送 SOAP 请求。
你需要:
Content-Type: text/xml; charset=utf-8标头SOAPAction: http://tempuri.org/YourServiceClass/YourAction标头让我们以 WCF 服务应用程序脚手架为例。
[ServiceContract]
public interface IService1
{
[OperationContract]
string GetData(int value);
}
public class Service1 : IService1
{
public string GetData(int value)
{
return string.Format("You entered: {0}", value);
}
}
使用 Wireshark,我发现默认方式(连接服务引用)的请求包含 Content-Type: text/xml; charset=utf-8 和 SOAPAction: http://tempuri.org/IService1/GetData 标头和以下 SOAP 信封:
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Body>
<GetData xmlns="http://tempuri.org/"> <!-- Action name -->
<value>123</value> <!-- Parameters -->
</GetData>
</s:Body>
</s:Envelope>
使用 Insomnia,我测试了它是我们使请求成功通过所需要的,所以现在只需要将它移植到 C#:
// netcoreapp3.1
static async Task<string> SendHttpRequest(string serviceUrl, int value)
{
// Example params:
// serviceUrl: "http://localhost:53045/Service1.svc"
// value: 123
using var client = new HttpClient();
var message = new HttpRequestMessage(HttpMethod.Post, serviceUrl);
message.Headers.Add("SOAPAction", "http://tempuri.org/IService1/GetData"); // url might need to be wrapped in ""
var requestContent = @$"
<s:Envelope xmlns:s=""http://schemas.xmlsoap.org/soap/envelope/"">
<s:Body>
<GetData xmlns=""http://tempuri.org/"">
<value>{value}</value>
</GetData>
</s:Body>
</s:Envelope>
";
message.Content = new StringContent(requestContent, System.Text.Encoding.UTF8, "text/xml");
var response = await client.SendAsync(message);
if (!response.IsSuccessStatusCode)
throw new Exception("Request failed.");
var responseContent = await response.Content.ReadAsStringAsync();
/*
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Body>
<GetDataResponse xmlns="http://tempuri.org/">
<GetDataResult>You entered: {value}</GetDataResult>
</GetDataResponse>
</s:Body>
</s:Envelope>
*/
// Just a really ugly regex
var regex = new Regex(@"(<GetDataResult>)(.*)(<\/GetDataResult>)");
var responseValue = regex.Match(responseContent).Groups[2].Value;
return responseValue;
}
你可以。如果愿意,请使用 WebClient 而不是 HttpClient。
【讨论】: