我有一个VB.NET 2008程序,该程序访问由WSDL定义并使用SOAP协议定义的Siebel Web服务。
Siebel Web服务要求将包含用户名,密码和会话类型的标题包含在服务请求中,但是标题未在WSDL中定义。
所以,当我使用SOAPUI实用程序测试WSDL时,WSDL定义的请求如下:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:lov="http://www.siebel.com/xml/LOVService" xmlns:lis="http://www.siebel.com/xml/ListQuery">
<soapenv:Header/>
<soapenv:Body>
<lov:EAILOVGetListOfValues_Input>
<lis:ListsQuery>
<lis:ListQuery>
<lis:Active>Y</lis:Active>
<lis:LanguageCode>ENU</lis:LanguageCode>
<lis:Type>CUT_ACCOUNT_TYPE</lis:Type>
</lis:ListQuery>
</lis:ListsQuery>
</lov:EAILOVGetListOfValues_Input>
</soapenv:Body>
</soapenv:Envelope>
,但以上不起作用,因为它包含一个缺少用户和会话凭据的空标头。仅当我用包含用户名,密码和会话类型的标题手动替换<soapenv:Header/>
时,它才能工作:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:lov="http://www.siebel.com/xml/LOVService" xmlns:lis="http://www.siebel.com/xml/ListQuery">
<soapenv:Header>
<UsernameToken xmlns="http://siebel.com/webservices">TESTUSER</UsernameToken>
<PasswordText xmlns="http://siebel.com/webservices">TESTPASSWORD</PasswordText>
<SessionType xmlns="http://siebel.com/webservices">None</SessionType>
</soapenv:Header>
<soapenv:Body>
<lov:EAILOVGetListOfValues_Input>
<lis:ListsQuery>
<lis:ListQuery>
<lis:Active>Y</lis:Active>
<lis:LanguageCode>ENU</lis:LanguageCode>
<lis:Type>CUT_ACCOUNT_TYPE</lis:Type>
</lis:ListQuery>
</lis:ListsQuery>
</lov:EAILOVGetListOfValues_Input>
</soapenv:Body>
</soapenv:Envelope>
我的问题是我无法整理如何将上述转换为VB.NET 2008代码。
我将WSDL导入Visual Studio 2008,在VB代码中定义服务并引用Web服务方法没有问题。但是,我无法整理如何在VB中定义Web服务,以便在Web服务请求中包含的更新标头而不是空标头中。因此,我来自VB失败的所有服务请求。
我可以定义从Soapheader类继承的类...
Public Class MySoapHeader : Inherits System.Web.Services.Protocols.SoapHeader
Public Username As String
Public Password As String
Public SessionType As String
End Class
...但是如何将此标头包含在VB的肥皂请求中?
我用来测试的示例代码这是一个简单的表单,带有按钮和列表框。
Public Class Form1
Private Sub btnGetLOV_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnGetLOV.Click
Dim MyService As New wsLOV.EAILOVPortClient
Dim MyInput As New wsLOV.EAILOVGetListOfValues_Input
Dim MyParams(0) As wsLOV.ListQuery
Dim temp As New wsLOV.ListQuery
Dim MyResult As New wsLOV.EAILOVGetListOfValues_Output
temp.Active = "Y"
temp.Type = "CUT_ACCOUNT_TYPE"
temp.LanguageCode = "ENU"
MyParams(0) = temp
MyInput.ListsQuery = MyParams
Dim MyRequest As New wsLOV.EAILOVGetListOfValuesRequest(MyInput)
MyResult = MyService.EAILOVGetListOfValues(MyInput)
End Sub
End Class
该代码在子例程的最后一行中失败,并带有一条消息,表明该请求尚未经过身份验证(错误代码:10944642错误消息:错误:Inbound Soap Message Message -Session Soap Message -Session Sopken缺少或无效或已过期)当我离开包含用户名,密码和会话类型的标题时,我会在SOAPUI中遇到的同样错误。
我相信我需要将标题添加到端点(http://msdn.microsoft.com/en-us/library/ms731749.aspx和http://msdn.microsoft.com/en-en-us/library/system.servicemodel.configuration.serviceendpointelement.aspx),但我不确定如何在VB中执行此操作。
这是我们解决此问题的方式。钥匙似乎是用附加的标头实例化端点,并且在端点已经实例化后不尝试添加标头。
Imports System.ServiceModel.Channels
Imports System.ServiceModel
Public Class Form1
Private Sub btnGetOrg_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnGetOrgType.Click
' This example code queries the Siebel web service using the SOAP protocol for a list of
' Account (organization) types stored in a List of Values (LOV). The service request
' requires that a SOAP header be added that contains the username, password, and session
' type. We have to add this header because the WSDL file definition generated by Siebel
' does not include the header definition. The WSDL file was added to the VS2008 project as
' a Service Reference named "wsGetLOV"
' Create address headers for special services and add them to an array
Dim addressHeader1 As AddressHeader = AddressHeader.CreateAddressHeader("UsernameToken", "http://siebel.com/webservices", "TESTUSER")
Dim addressHeader2 As AddressHeader = AddressHeader.CreateAddressHeader("PasswordText", "http://siebel.com/webservices", "TESTPASSWORD")
Dim addressHeader3 As AddressHeader = AddressHeader.CreateAddressHeader("SessionType", "http://siebel.com/webservices", "None")
Dim addressHeaders() As AddressHeader = {addressHeader1, addressHeader2, addressHeader3}
' Endpoint address constructor with URI and address headers
' Replace <servername> in the following line with the name of your Siebel server.
' For example: http://actual-server/eai_enu...
Dim endpointAddressWithHeaders As New EndpointAddress(New Uri("http://<servername>/eai_enu/start.swe?SWEExtSource=WebService&SWEExtCmd=Execute&WSSOAP=1"), addressHeaders)
Dim MyService As New wsGetLOV.EAILOVPortClient("EAILOVPort", endpointAddressWithHeaders)
Dim MyInput As New wsGetLOV.EAILOVGetListOfValues_Input
Dim MyOutput As wsGetLOV.EAILOVGetListOfValues_Output
Dim MyList(0) As wsGetLOV.ListQuery
MyList(0) = New wsGetLOV.ListQuery
MyList(0).Active = "Y"
MyList(0).LanguageCode = "ENU"
MyList(0).Type = "CUT_ACCOUNT_TYPE"
MyInput.ListsQuery = MyList
MyOutput = MyService.EAILOVGetListOfValues(MyInput)
Dim myStrings As New List(Of String)
' We use nested loops because the results returned by the service is a list of
' lists though in our case, the result set is a list with a single item (this item
' being a list of multiple items)
For Each myResultList As wsGetLOV.ListResult In MyOutput.ListsResult
For Each myResultValue As wsGetLOV.ListValueResult In myResultList.ListValuesResult
myStrings.Add(myResultValue.Value)
Next
Next
ListBox1.DataSource = myStrings
End Sub
End Class