我怎样才能消费的传统SOAP服务时创建自定义XML命名空间的属性? [英] How can I create custom XML namespace attributes when consuming a legacy SOAP service?

查看:152
本文介绍了我怎样才能消费的传统SOAP服务时创建自定义XML命名空间的属性?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个传统的Tibco SOAP服务,我需要从中获取一些数据。不幸的是这种服务是非常讲究的请求消息中的XML命名空间属性。我也碰到这样的问题,从消费仁科服务时( https://en.wikipedia.org/维基/的PeopleCode )。

I have a legacy Tibco SOAP service that I need to get some data from. Unfortunately this service is very particular about the XML namespace attributes on the request message. I have also run into this sort of problem when consuming services from PeopleSoft (https://en.wikipedia.org/wiki/PeopleCode).

我从服务的.wsdl并创建了服务的参考。

I got the .wsdl from the service and created a service reference.

开箱即用,即净生成XML请求消息是:

Out of the box, the XML request message that .Net produces is:

<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
    <s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
        <getLocation xmlns="http://customNamespaceHere">
            <context>
                <source>SysAdmin</source>
            </context>
            <Address>
                <address1>123 Main St</address1>
                <city>New York</city>
                <state>NY</state>
                <country>US</country>
            </Address>
        </getLocation>
    </s:Body>
</s:Envelope>



什么是真正的工作原理是(我想通了这一点,使用了SoapUI):

What actually works is (I figured this out using SoapUI):

<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
    <s:Body>
        <getLocation xmlns="http://customNamespaceHere">
            <context>
                <source>SysAdmin</source>
            </context>
            <Address>
                <address1>123 Main St</address1>
                <city>New York</city>
                <state>NY</state>
                <country>US</country>
            </Address>
        </getLocation>
    </s:Body>
</s:Envelope>



注意没有body标签内的XSI和XSD前缀。

Notice the absence of the xsi and xsd prefixes within the body tag.

问:我怎样才能得到净送手的正确XML短期滚动XML文档,并手动将其发送到服务

推荐答案

答:我能够通过实施IClientMessageInspector它发送之前修改XML请求

首先,我不得不通过实施IClientMessageInspector延长WCF。这让我来访问请求对象和修改XML请求消息。这些类并不需要在你的解决方案中的任何特定位置(据我所知)。

First I had to extend WCF by implementing IClientMessageInspector. This allowed me to gain access to the request object and modify the XML request message. These classes don't need to be in any particular location within you solution (as far as I know).

public class ExtendedClientMessageInspector : IClientMessageInspector
{
    // Here we can alter the xml request body before it gets sent out.
    public object BeforeSendRequest(ref Message request, IClientChannel channel)
    {
        return TibcoService.ModifyGetLocationRequest(ref request);

    } // end

    public void AfterReceiveReply(ref Message reply, object correlationState)
    {
        return;

    } //end

} // end class

public class ExtendedEndpointBehavior : IEndpointBehavior
{
    public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)
    {
        return;

    } // end

    public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)
    {
        clientRuntime.MessageInspectors.Add(new ExtendedClientMessageInspector());

    } // end

    public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
    {
        return;

    } // end

    public void Validate(ServiceEndpoint endpoint)
    {
        return;

    } // end

} // end class

public class EndpointBehaviorExtensionElement : BehaviorExtensionElement
{
    protected override object CreateBehavior()
    {
        return new ExtendedEndpointBehavior();

    } // end

    public override Type BehaviorType
    {
        get
        {
            return typeof(ExtendedEndpointBehavior);
        }

    } // end

} // end class

我没把那个在在同一类为服务这个服务的XML专门处理方法:

I did put the method that specifically deals with the XML in this service in the same class as the service:

public static Message ModifyGetLocationRequest(ref Message request)
{
    // Initialize objects
    var xmlDocument = new XmlDocument();
    var memoryStream = new MemoryStream();
    var xmlWriter = XmlWriter.Create(memoryStream);
    var xmlAttribute = xmlDocument.CreateAttribute("xmlns", "api", "http://www.w3.org/2000/xmlns/");

    xmlAttribute.Value = "http://customNamespaceHere";

    // Write the xml request message into the memory stream
    request.WriteMessage(xmlWriter);

    // Clear the xmlWriter
    xmlWriter.Flush();

    // Place the pointer in the memoryStream to the beginning 
    memoryStream.Position = 0;

    // Load the memory stream into the xmlDocument
    xmlDocument.Load(memoryStream);

    // Remove the attributes from the second node down form the top
    xmlDocument.ChildNodes[1].ChildNodes[1].Attributes.RemoveAll();

    // Reset the memoryStream object - essentially nulls it out
    memoryStream.SetLength(0);

    // ReInitialize the xmlWriter
    xmlWriter = XmlWriter.Create(memoryStream);

    // Write the modified xml request message (xmlDocument) to the memoryStream in the xmlWriter
    xmlDocument.WriteTo(xmlWriter);

    // Clear the xmlWriter
    xmlWriter.Flush();

    // Place the pointer in the memoryStream to the beginning 
    memoryStream.Position = 0;

    // Create a new xmlReader with the memoryStream that contains the xmlDocument
    var xmlReader = XmlReader.Create(memoryStream);

    // Create a new request message with the modified xmlDocument
    request = Message.CreateMessage(xmlReader, int.MaxValue, request.Version);

    return request;

} // end

要得到这一切工作的时候服务是叫你将需要修改你的web.config或app.config中。在您的端点声明中,您将需要指定,像这样一个behaviorConfiguration元素:

To get this all to work when the service is called you will need to modify your web.config or app.config. On your endpoint declaration you will need to specify a behaviorConfiguration element like so:

<client>
    <endpoint address="http://1.2.3.4:1234/InventoryBinding"
          binding="basicHttpBinding" bindingConfiguration="HttpSoapBinding"
          contract="TibcoSvc.InventoryPort" name="InventoryPort" 
          behaviorConfiguration="clientInspectorsAdded" />    
</client>

您还需要指定的延伸和行为,以及:

You will also need to specify the extension and the behavior as well:

<system.serviceModel>

    <extensions>
        <behaviorExtensions>
            <add name="ExtendedEndpointBehavior" type="Sample.Integrations.EndpointBehaviorExtensionElement, Sample.Integrations, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null" />
        </behaviorExtensions>
    </extensions>

    <behaviors>
        <endpointBehaviors>
            <behavior name="clientInspectorsAdded">
                <ExtendedEndpointBehavior />
            </behavior>
        </endpointBehaviors>
    </behaviors>

</system.serviceModel>

请注意这里说的扩展名必须是正是由返回:

Note here that the extension name needs to be exactly what is returned by:

var foo = typeof(<PutYourNamespaceHereNoAngleBrackets>.EndpointBehaviorExtensionElement).AssemblyQualifiedName; 

下面是我发现的有用几个环节:

Here are a few links that I found helpful:

https://social.msdn.microsoft.com/Forums/vstudio/en-US/01440583-d406-4426-8667-63c6eda431fa/remove ?-xmlnsxsi和-xmlnsxsd - 从皂请求体标签-ASPNET论坛= WCF

HTTPS://social.msdn。 microsoft.com/Forums/vstudio/en-US/51547537-fdae-4837-9bd1-30e445d378e9/removing-xmlnsxsihttpwwww3org2001xmlschemainstance-and?forum=wcf

http://weblogs.asp.net/paolopia/writing-a-wcf -message巡视员

https://msdn.microsoft.com/en-us/library/system.servicemodel.dispatcher.iclientmessageinspector(v = VS.100)的.aspx

这篇关于我怎样才能消费的传统SOAP服务时创建自定义XML命名空间的属性?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆