当前位置: 首页 > 知识库问答 >
问题:

WCF用“application/xml”和“text/xml”内容类型绑定SOAP 1.1请求

养学
2023-03-14

现有的客户端很多,改变它们是不可行的。

我已经成功地创建了一个服务,它在大多数客户机上都有一个令人烦恼的异常。

因为旧的服务是SOAP1.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”和“text/xml”的内容类型,并在标题中使用SOAP1.1样式的“soapaction”寻址。

我还尝试实现一个自定义文本消息编码器,从Microsoft的WCF示例CustomTextMessageEncodingElement开始。

但是,使用自定义文本消息编码器,我可以将mediatype设置为'application/xml'或'Text/xml'。但是,毫不奇怪,发送指定内容类型的客户端成功,而使用其他内容类型的客户端失败。

共有1个答案

简培
2023-03-14

我相信我想做的是根本不可能的。

我得出的结论是,WCF对于实现向后兼容替换遗留SOAP web服务来说是一种不合适的技术,遗留SOAP web服务允许在头部中包含各种内容类型值。

相反,我使用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
    }
}
<system.webServer>
    <modules runAllManagedModulesForAllRequests="true">
        <add name="MyCustomHttpModule" type="AppropriateNamespace.MyCustomHttpModule"/>
    </modules>
</system.webServer>
 类似资料: