2016-11-30 92 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