2016-11-30 56 views
1

让我先描述一下我的意图,然后进入我的问题。如何从对象类型创建SOAP请求?

我试图构建一个SOAP服务所在的SOAP请求在运行时有点未知通信的系统。最终,我需要做的是从未知对象生成SOAP请求。我将用适当的属性和属性从头开始动态创建对象,然后将其传递给我的服务“请求”方法以发送到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 }); 

这是错误:在该行中出现n错误

The type Services.Soap.Models+ParentNode was not expected. Use the XmlInclude or SoapInclude attribute to specify types that are not known statically.

现在,如果我更改服务的参数“请求”的方法,以一个很强的类型,请求建立精细和传递给SOAP服务,就像这样。

public object request(ParentNode parm) 

我试过大概50事情得到这个工作,包括通过类型作为参数传递给请求方法和创建对象的“动态”的实例来传递。

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])); 
    } 

这没有效果,因为“转换”仍然被视为对象类型。

我还试图拦截SOAP信封中的“GetWriterForMessage”方法,这样我就可以建立自己的信封,但我没能充分利用这一点。

所以我的问题是,如何才能得到SOAP请求到带有参数类型的对象成功打造?我可以采取另一种方法让我的架构正常工作吗?

+0

只是将我的评论移至答案。见下文。 – Namphibian

回答

0

你对你正在执行的系统的描述对我来说不是很清楚。你提到你将发送 “动态”请求到SOAP服务器?或者你正在用“动态”操作创建一些服务。这些细节对我来说有点浑浊,但是我潦草地写下了一些想法。

总之,如果你想在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应用程序可以使用它来生成数据类型和关联的C#类。这些类将包括正在传输的数据和服务中暴露的操作。

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

+0

我感谢您的评论和您在这里提供的信息。我明白,SOAP服务器和客户端之间的动态是,并且应该符合合同,它不符合我试图实现的设计。在这一天结束时,我的意图是为管理员提供一个前端界面,以“设置”与各种第三方实体进行通信所需的合同属性。我正在寻找通过前端界面管理服务合同的能力,因此,改变路线并不需要开发人员改变和编译合同的时间。 – Samurai2083

+0

我们的客户需要我们提供给他们的门户与第三方服务沟通。填写在我们门户上的表格通过SOAP发送到这些第三方服务。我们的想法是,我们的门户网站不关心这些其他服务是谁或是什么,相信管理方将正确构建正确建立合同规则的服务配置文件。然后,当提交表单时,后端将与填充表单数据的必要模型构建合同,然后提交给服务。这就是为什么'对象'是需要的。没有什么是强类型的。 – Samurai2083

+0

您需要一个完全基于它的ESB服务器。忘记动态的想法解耦。研究ESB和企业集成模式。这个问题已经得到解决,并有开源和商业产品可用,将做你想要实现的。一旦我的感冒消退后,将详细编辑我的答案。我爱和恨我的孩子... – Namphibian