[C# Web Services] 如何自定義 SOAP Header

在使用 C# 開發 Web Services 的時候,有時難免客戶的資訊單位會要求在 SOAP 的 Header 中夾帶一些資訊過去,通常可能會拿來做為驗證或者其他用途,這邊筆者簡單的說明一下使用 .NET 如何實作這個部分

在使用 C# 開發 Web Services 的時候,有時難免客戶的資訊單位會要求在 SOAP 的 Header 中夾帶一些資訊過去,通常可能會拿來做為驗證或者其他用途,這邊筆者簡單的說明一下使用 .NET 如何實作這個部分。

(一)、首先,在服務的地方,自定義一個繼承 SoapHeader 的類別,重點是這個類別的變數必須是 public 且在這個 WebService的 Service1 這個類別裡面,並在公開出 [WebMethod] 的那個方法上 SoapHeader 的 Attribute:

   1:      public class Service1 : System.Web.Services.WebService
   2:      {
   3:          public MySoapHeader soapHeader;
   4:  
   5:          [WebMethod]
   6:          [SoapHeader("soapHeader", Direction = SoapHeaderDirection.InOut)]
   7:          public WCO.Address QueryUserInfo()
   8:          {
   9:              //取得使用者資訊
  10:          }
  11:      }
  12:  
  13:      public class MySoapHeader : SoapHeader
  14:      {
  15:          public string ID = string.Empty;
  16:          public string Password = string.Empty;
  17:          public DateTime MakeDate;
  18:      }

 

還有一個重點,Attribute 中的第一個參數必須與店數名稱一模一樣。

公開在 Service1 的 MySoapHeader 會在用戶端所參照的 WSDL 取得相關的資訊供傳遞。

image

 

這時用戶端叫用服務時,在 SOAP Header 都會夾帶這三個欄位至服務端:

   1:  POST /Service1.asmx HTTP/1.1
   2:  Host: localhost
   3:  Content-Type: text/xml; charset=utf-8
   4:  Content-Length: length
   5:  SOAPAction: "http://tempuri.org/QueryUserInfo"
   6:  
   7:  <?xml version="1.0" encoding="utf-8"?>
   8:  <soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
   9:    <soap:Header>
  10:      <MySoapHeader xmlns="http://tempuri.org/">
  11:        <ID>string</ID>
  12:        <Password>string</Password>
  13:        <MakeDate>dateTime</MakeDate>
  14:      </MySoapHeader>
  15:    </soap:Header>
  16:    <soap:Body>
  17:      <QueryUserInfo xmlns="http://tempuri.org/" />
  18:    </soap:Body>
  19:  </soap:Envelope>

 

服務端的程式碼要能夠處理 MySoapHeader 並加以處理,如果取不到定義在 MySoapHeader 中的 ID & Password 則傳回錯誤訊息,以 IE 執行結果如下:

image

實作上面結果的服務端程式碼,首先:

1. 定義迴傳型別 Address

2. 並在回傳的 Address 類別中增加一個 ERR_INFO 欄位存放錯誤訊息

   1:    [Serializable]
   2:    public class Address
   3:    {
   4:        public Address() { }
   5:  
   6:        public string Line { get; set; }
   7:        public string tw_ChineseLine { get; set; }
   8:        [XmlElement("ERROR_MESSAGE")]
   9:        public string ErrInfo { get; set; }
  10:    }

 

3. 撰寫 QueryUserInfo 的 Web Method

   1:    [WebMethod]
   2:    [SoapHeader("soapHeader", Direction = SoapHeaderDirection.InOut)]
   3:    public WCO.Address QueryUserInfo()
   4:    {
   5:        WCO.Address address = null;
   6:        if (soapHeader == null)
   7:        {
   8:            //自訂錯誤訊息:無權限存取
   9:            address = new WCO.Address() { ErrInfo = "錯誤:必須輸入帳號密碼。"};
  10:            return address;
  11:        }
  12:  
  13:        if (soapHeader.ID.Trim() == "" || soapHeader.Password.Trim() == "")
  14:        {
  15:            address = new WCO.Address() { ErrInfo = "錯誤:帳號密碼不可以是空白。" };
  16:            return address;
  17:        }
  18:  
  19:        string ID = soapHeader.ID;
  20:        string password = clsEncryption.DecryptDES(soapHeader.Password);
  21:        //略.......進行(帳密)驗證
  22:        //若驗證通過,則進行後續處理
  23:  
  24:        address = new WCO.Address() { Line="180", tw_ChineseLine="60", ErrInfo = null};
  25:        return address;
  26:    }

 

若驗證通過則端看服務端程式碼後續要做何種商業內容,程式碼筆者只節錄部分,因為程式非常的簡單,我們直接看如何實作呼叫端,並傳遞 MySoapHeader 的帳號密碼至服務端。

 

(二)、實作呼叫端

接下來,就是實作呼叫端,前面提到,在 WSDL 中定義的資訊,在 .NET 參考服務定義後會自動產生 Reference.cs 介面檔,當中就可以使用 MySoapHeader 了。

image

在撰寫呼叫端傳遞 MySoapHeader 也非常地容易,因為直接當引數傳遞即可 (預設會使用 reference 方式傳遞)

image

這時筆者只需撰寫如下程式碼將 ID 與 Password 傳入 Service1SoapClient 的 QueryUserInfo

   1:    private void btnSOAPTest_Click(object sender, EventArgs e)
   2:    {
   3:        Service1SoapClient testSoap = new Service1SoapClient();
   4:        MySoapHeader soapHeader = new MySoapHeader()
   5:            {
   6:                ID = txtID.Text,
   7:                Password = txtPassword.Text!=""?clsEncryption.EncryptDES(txtPassword.Text):"",
   8:                MakeDate = DateTime.Now
   9:            };
  10:        Address result = testSoap.QueryUserInfo(ref soapHeader);
  11:        List<Address> list = new List<Address>() { result};
  12:        dataGridView1.DataSource = list;
  13:    }

 

如上程式,筆者將資料顯示在 DataGridView 中,如下:

image

如果沒有傳入密碼,那麼最後一欄我們會得到錯誤訊息。

image

如上、一個簡單的分享。也許對各位有用。


 

簽名:

學習是一趟奇妙的旅程

這當中,有辛苦、有心酸、也有成果。有時也會有瓶頸。要能夠繼續勇往直前就必須保有一顆最熱誠的心。

軟體開發之路(FB 社團)https://www.facebook.com/groups/361804473860062/

Gelis 程式設計訓練營(粉絲團)https://www.facebook.com/gelis.dev.learning/


 

如果文章對您有用,幫我點一下讚,或是點一下『我要推薦,這會讓我更有動力的為各位讀者撰寫下一篇文章。

非常謝謝各位的支持與愛護,小弟在此位各位說聲謝謝!!! ^_^