使用 SOAPCore 访问 XML 标头

问题描述

我使用 SoapCore 1.1.0.8 和 .NetCore 3.1

有人知道如何使用 SoapCore 从信封访问 XML 标头吗?

例如像下面这样的信封

    <SOAP:Header xmlns='http://www.acompany.com/gsd'>
        <ns0:AuthenticationInfo xmlns:ns0='http://customheader.com'>
            <ns0:userName>Dummy_User</ns0:userName>
            <ns0:password>Dummy_Pwd</ns0:password>
        </ns0:AuthenticationInfo>
    </SOAP:Header>
    <SOAP:Body xmlns='http://www.acompany.com/gsd'>
        <MsgReq xmlns='http://www.acompany.com/gsd' xmlns:soapenv='http://schemas.xmlsoap.org/soap/envelope/'>
            <MethodName>Identify</MethodName>
            <MethodID>IS_001_01</MethodID>
.
.
        </MsgReq>
    </SOAP:Body>
</SOAP:Envelope>

如何访问用户名和密码元素?

解决方法

您可以使用 IServiceOperationTuner 访问 XML 标头。

public class ServiceOperationTuner : IServiceOperationTuner
    {
        public void Tune(HttpContext httpContext,object serviceInstance,OperationDescription operation)
        {
            if (serviceInstance is YourServiceClass)
            {
                YourServiceClass)service = serviceInstance as YourServiceClass)
                service.SetHttpRequest(httpContext.Request);
            }
        }
    }

然后在 Startup.cs 中注册 ServiceOperationTuner。

        public void ConfigureServices(IServiceCollection services)
        {
...
            services.AddSoapServiceOperationTuner(new ServiceOperationTuner());
...
        }

在您的服务中添加

  private ThreadLocal<HttpRequest> _httpRequest = new() { Value = null };

        public void SetHttpRequest(HttpRequest request)
        {
            _httpRequest.Value = request;
        }

然后你可以从 HttpContext 获取 RAW Soap Header XML

        private XmlNode GetHeaderFromRequest(HttpRequest request)
        {
            var bytes = (request.Body as MemoryStream)?.ToArray();
            if (bytes == null)
            {
                // Body missing from request
                return null;
            }

            var envelope = new XmlDocument();
            envelope.LoadXml(Encoding.UTF8.GetString(bytes));

            return envelope.DocumentElement?.ChildNodes.Cast<XmlNode>().FirstOrDefault(n => n.LocalName == "Header");
        }