我正在尝试用新的WCF服务替换旧的SOAP 1.1 Web服务。
现有客户很多,改变它们是不可行的。
我已经成功创建了一项服务,它为大多数客户提供了一个令人烦恼的例外。
由于旧服务是SOAP 1.1,我尝试使用basicHttpBinding,如:
<bindings>
<basicHttpBinding>
<binding name="Whatever" />
</basicHttpBinding>
</bindings>
我的大多数入站邮件都类似于以下示例,一切正常:
POST http://MySoapWebServiceUrl/Service.svc HTTP/1.1
SOAPAction: DoSomething
Content-Type: text/xml;charset=UTF-8
Content-Length: 1234
Host: MySoapWebServiceUrl
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/">
<soap:Body soap:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<xml:InputStuffHere />
</soap:Body>
</soap:Envelope>
我的问题是,除了标题中包含'application / xml'的Content-Type之外,有几个调用者正在发送完全相同的消息,并收到此错误:
错误:415无法处理消息,因为内容类型“application / xml”不是预期类型“text / xml”。
我已尝试切换为与wsHttpBinding
或webHttpBinding
绑定。
但是,我找不到这些绑定中任何一个的设置组合,这些绑定允许“application / xml”和“text / xml”的内容类型以及标头中的SOAP 1.1样式“SOAPAction”寻址。
我还尝试实现自定义文本消息编码器,从Microsoft的WCF示例CustomTextMessageEncodingElement
开始。
但是,使用自定义文本消息编码器,我可以将MediaType
设置为'application / xml'或'text / xml'。但是,毫不奇怪,发送指定Content-Type的客户端成功,但使用其他Content-Type的客户端失败。
我还试图将MediaType
设置为包含'*/xml'
之类的通配符,但这对所有来电者来说都是失败的。
有没有办法创建WCF绑定,以便服务接受“application / xml”或“text / xml”的内容类型?
答案 0 :(得分:2)
我相信我想做的事情根本不可能。
我得出的结论是,WCF是一种不适当的技术,用于实现传统SOAP Web服务的向后兼容替换,允许标头中包含各种Content-Type值。
相反,我使用System.Web.IHttpModule实现了自定义HttpModule。
基本的实施细节如下:对于那些发现自己陷入困境并需要出路的人来说。
代码:
public class MyCustomHttpModule : IHttpModule
{
public void Init(HttpApplication context)
{
context.BeginRequest += OnBegin;
}
private void OnBegin(object sender, EventArgs e)
{
var app = (HttpApplication) sender;
var context = app.Context;
if (context.Request.HttpMethod == "POST")
{
string soapActionHeader = context.Request.Headers["SOAPAction"];
byte[] buffer = new byte[context.Request.InputStream.Length];
context.Request.InputStream.Read(buffer, 0, buffer.Length);
context.Request.InputStream.Position = 0;
string rawRequest = Encoding.ASCII.GetString(buffer);
var soapEnvelope = new XmlDocument();
soapEnvelope.LoadXml(rawRequest);
string response = DoSomeMagic(soapActionHeader, soapEnvelope);
context.Response.ContentType = "text/xml";
context.Response.ContentEncoding = Encoding.UTF8;
context.Response.Write(response);
}
else
{
//do something else
//returning a WSDL file for an appropriate GET request is nice
}
context.Response.Flush();
context.Response.SuppressContent = true;
context.ApplicationInstance.CompleteRequest();
}
private string DoSomeMagic(string soapActionHeader, XmlDocument soapEnvelope)
{
//magic happens here
}
public void Dispose()
{
//nothing happens here
//a Dispose() implementation is required by the IHttpModule interface
}
}
的web.config:
<system.webServer>
<modules runAllManagedModulesForAllRequests="true">
<add name="MyCustomHttpModule" type="AppropriateNamespace.MyCustomHttpModule"/>
</modules>
</system.webServer>