如何从对象类型创建SOAP请求?

时间:2016-11-30 19:37:28

标签: c# web-services soap service soaphttpclientprotocol

首先让我描述一下我的意图,然后再回答我的问题。

我正在尝试构建一个与SOAP服务通信的系统,其中SOAP请求在运行时有些未知。最终我需要做的是从未知对象生成SOAP请求。我将使用适当的属性和属性从头开始动态创建对象,然后将其传递给我的服务“request”方法以发送到SOAP服务。这是我一直在使用的代码,然后是我收到的错误。

SOAP客户端:

/// <summary>
/// GOSService proxy class
/// </summary>
[DebuggerStepThroughAttribute()]
[DesignerCategoryAttribute("code")]
[WebServiceBindingAttribute(Name = "ServiceSoapBinding", Namespace = "service.domain.com", ConformsTo = WsiProfiles.None)]
[SoapRpcService(RoutingStyle = SoapServiceRoutingStyle.RequestElement)]
public partial class TestService : SoapHttpClientProtocol
{
    /// <summary>
    /// Initializes a new instance of the TestService class.
    /// </summary>
    public TestService()
    {
        this.Url = "https://restsv01.domain.com/ServiceTest/services/TestService";
        ServicePointManager.Expect100Continue = true;
        ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3;
        ServicePointManager.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback(OnRemoteCertificateValidationCallback);
    }

    /// <summary>
    /// Verifies the remote Secure Sockets Layer (SSL) certificate used for authentication.
    /// </summary>
    /// <param name="sender">An object that contains state information for this validation.</param>
    /// <param name="certificate">The certificate used to authenticate the remote party.</param>
    /// <param name="chain">The chain of certificate authorities associated with the remote certificate.</param>
    /// <param name="sslPolicyErrors">One or more errors associated with the remote certificate.</param>
    /// <returns>A Boolean value that determines whether the specified certificate is accepted for authentication.</returns>
    private bool OnRemoteCertificateValidationCallback(Object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
    {
        return true;
    }

    /// <summary>
    /// 
    /// </summary>
    /// <param name="order"></param>
    /// <returns></returns>
    [SoapRpcMethodAttribute("", RequestNamespace = "service.domain.com", ResponseNamespace = "service.domain.com")]
    [SampleSoap.LoggerSoapExtensionAttribute]
    [return: SoapElementAttribute("requestReturn")]
    public object request(object parm)
    {
        object[] results = this.Invoke("request", new object[] { parm });
        return ((object)(results[0]));
    }}

测试模型: (不会有任何预先定义的模型,它们将动态生成。但出于测试目的,我使用此模型进行测试)

    [SerializableAttribute()]
    [DebuggerStepThroughAttribute()]
    [DesignerCategoryAttribute("code")]
    [SoapTypeAttribute(Namespace = "http://entity.domain.com")]
    public class ParentNode
    {
        private string nameField = "1";
        [SoapElementAttribute(IsNullable = true)]
        public string Name
        {
            get { return this.nameField; }
            set { this.nameField = value; }
        }
    }

测试呼叫代码:

        Services.Soap.Models.ParentNode parent = new Services.Soap.Models.ParentNode();
        parent.Name = "John Doe";
        Services.Soap.TestService service = new Services.Soap.TestService();
        object resp = service.request(parent);

运行此代码时,此行发生错误:

object[] results = this.Invoke("request", new object[] { parm });

这是错误:

  

不期望使用Services.Soap.Models + ParentNode类型。使用   XmlInclude或SoapInclude属性指定不是的类型   静态地知道。

现在,如果我将服务“request”方法的参数更改为强类型,请求构建正常并传递给SOAP服务,就像这样。

public object request(ParentNode parm)

我已经尝试了50项工作,包括将Type作为参数传递给请求方法并创建要传递的对象的“动态”实例。

    public object request(object parm, Type t)
    {
        dynamic converted = Convert.ChangeType(parm, t);

        object[] results = this.Invoke("request", new object[] { converted });
        return ((object)(results[0]));
    } 

这不起作用,因为“转换”仍被视为对象类型。

我也试过拦截“GetWriterForMessage”方法中的soap信封,这样我就可以构建自己的信封,但是我无法使用它。

所以我的问题是,如何使用参数类型的对象成功构建SOAP请求?是否可能采取另一种方法来使我的架构正常工作?

1 个答案:

答案 0 :(得分:1)

您对系统的描述对我来说并不十分清楚。你提到你会发送 &#34;动态&#34;请求到SOAP服务器?或者您是否正在创建一些服务&#34; dynamic&#34;操作。这些细节对我来说有点混乱,但是我潦草地写下了一些想法。

简而言之,如果您想在SOAP中执行此操作,那么您将为自己打开一个痛苦的世界。 REST可能更适合,因为它没有WSDL,但如果您使用WADL,RAML和这些新兴标准,您的milage可能会有所不同。我不打算尝试甚至回答你的技术问题,但试着让你明白为什么这是维持地狱的单程票。

这种实现确实打破了SOA概念(特别是标准化服务契约),这可能不适用于您的情况,因为仅实现具有未知内容的动态WSDL会使体系结构不合格为非SOA。这也与拥有WSDL的整个观点相矛盾。 WSDL是XML中的接口定义。因此,动态服务需要动态接口,然后将其限定为非接口。因此,当您使用对象类型作为参数时,WSDL和接口不匹配。

当其他系统使用您的SOAP服务时,它们将基于已发布的WSDL执行此操作。如果WSDL更改其程序将因为定义或WSDL与它们生成的数据类型不匹配而中断。在HTTP上工作并获取请求并发送回复但没有WSDL的服务不是SOAP服务,而是使用HTTP端口的基于XML的服务。它们根本不同。您的服务提供商,即您要求数据的SOAP服务是否没有WSDL?如果不是这些不是您正在寻找的机器人:)

接口是应用程序可用于查询服务的约定合同。基本上,您在谈论结构化与非结构化数据对象(至少在运行时)。

如果你想要这种类型的模式,你需要查看一个像MQTT这样轻量级的发布订阅体系结构,或者另一个例子是带有主题的JMS。

如果您正在使用您提到的Web服务,那么您的.Net应用程序可以使用WSDL来生成数据类型和关联的C#类。这些类将包括正在传输的数据和在服务上公开的操作。

在官方SOAP世界中,没有动态服务这样的东西,因为它打破了我们同意作为服务器和客户端在操作期间通过这种形式的XML进行通信的整个范例。