Dynamic custom service parameters

Topics: Developer Forum
Apr 2, 2009 at 8:37 PM
Is there a way to send custom service parameters in the message header from the client?

I am able to create them in the message envelope on the client, but they are not there in the service.  It appears the service is reading the header portion from configuration instead.  Is that right?

Here's how I had the client inject custom parameters:

        private void invokeService(ProcessMsgClient client)
        {
                ESBMessage request = new ESBMessage();

                // Create request message.
                XmlDocument reqXML = new System.Xml.XmlDocument();
                reqXML.InnerXml = txtPayload.Text;
                createCustomParameters(reqXML, "productABC", "MN");
                request.EnvelopeXML = reqXML.DocumentElement;

                // Submit request.
                AsyncCallback resultHandler = new AsyncCallback(ServiceCompleted);
                client.BeginProcessMsgSync(request,resultHandler,null);
        }

        private void createCustomParameters(XmlDocument reqXML, String aProductId, String aStateCd)
        {
            XmlNamespaceManager nsmgr = new XmlNamespaceManager(reqXML.NameTable);

            XmlElement root = reqXML.DocumentElement;
            nsmgr.AddNamespace("df", root.NamespaceURI);  // Add a default namespace reference.

            XmlNode customServiceNode = root.SelectSingleNode("./df:header/df:service/df:custom", nsmgr);
            if (customServiceNode == null)
            {
                XmlNode serviceNode = root.SelectSingleNode("./df:header/df:service", nsmgr);
                customServiceNode = reqXML.CreateNode(XmlNodeType.Element, "custom", serviceNode.NamespaceURI);
                serviceNode.AppendChild(customServiceNode);
            }

            // Add product id parameter.
            XmlNode productIdNode = reqXML.CreateNode(XmlNodeType.Element, "productId", serviceNode.NamespaceURI);
            productIdNode.InnerText = aProductId;
            customServiceNode.AppendChild(productIdNode);

            // Add state parameter.
            XmlNode stateNode = reqXML.CreateNode(XmlNodeType.Element, "stateCd", serviceNode.NamespaceURI);
            stateNode.InnerText = aStateCd;
            customServiceNode.AppendChild(stateNode);
        }







Coordinator
Apr 3, 2009 at 11:05 AM
Edited Apr 3, 2009 at 10:12 PM

Hi Brian,
TIP:
As a general reference, you can use the ESB Management Console code as Client-Side sample code. 

For what you want - a simple name/value pair...,

there's a 1-liner you can use to set the value...

           oEnv.SetCustomParam("productABC", "MN")

...and send the request...

        oServer.ProcessMsgSync(oEnv.XML, sXMLResponse)

...and to get the value in your handler...
    sProdABCValue =  oEnv.GetCustomParam("productABC")

Here's an excerpt from the ESB Management Console:


Dim oServer As New ESB.Core.Adaptors.Transport.RequestHandlerProxy.Sender(Session("SendUrl"), Session("TransportType"), Session("TransportClientEndPointName"))
Dim oTimer As New ESB.Core.Util.Timer
oTimer.StartTimer()
Dim sXMLResponse As String
'Add in a Custom Parameter which tells the Send Transport Adaptors (if they choose to honour it...)
'how many times to execute this request at their level
'Note that they run their own loop, independent of the one in here.
'That ensures all connection and data setup times are removed from those timings
'Use the GetBaseContext.m_sExecutionTime to get those timings...

Dim
oEnv As New ESB.Core.XMLSchemaClasses.ESBEnvelope.Envelope
oEnv.XML = txtXMLRequest.Text

oEnv.SetCustomParam(ESBConstants.C_sClientNumExecutionTimes, txtNumExecutionTimesAdaptor.Text)

'++Make the call
For nExecutionTimes As Integer = 1 To txtNumExecutionTimes.Text

 oServer.ProcessMsgSync(oEnv.XML, sXMLResponse)

 

'--Make the call
Next
oTimer.StopTimer()
txtXMLResponse.Text = sXMLResponse
Dim oXMLUtil As New ESB.Core.XMLSchemaClasses.XMLUtil
txtXMLResponse.Text = oXMLUtil.PrettyFormatXML(sXMLResponse)
txtResponseTime.Text = oTimer.Duration() &
";" & GetBaseContext.m_sExecutionTime   


 

 

 

Also, for Configured Services, in the Service Pipeline Configuration, you can specify a Custom Parameter for your handlers [these are in the Multi-Level-Overrides, so you can take advantage of the Data Inheritance feature here too...]
The example below specifies a handler [used for stubbing out the service implementation for clients during the dev. process] that returns a particular file.
So, you can define your service [in config only], have it return a payload from a file by configuring a standard handler, and specify for that particular service, which payload to return.
The next service you define [or use the context in the request envelope to vary the responses based upon a set of context strings used for testing etc.] can use the same config code, just change the file to be returned...


 

 

 

 <PipelineMapSection name="Testing - Generic SOAP Transport Adaptor"
<
PipelineEntry> <ResolveNameEntry> <ContextEntry
<Context>http://ESB.Keystroke.com.au/ESB/wsdl/.ProcessMsgSync</Context> <ResolveName>ProcessMsgSync</ResolveName> <PipelineID>1</PipelineID> <ProcessInParallel>0</ProcessInParallel> <ResponseIsRequestForNextPipelineItem>1</ResponseIsRequestForNextPipelineItem
<
MultiLevelOverrides
<TransactionComponent>ESB.Testing.TestTxns.ReturnSpecifiedFileHandler</TransactionComponent> <ComponentServer suffix="yes">Base\Solutions\Main\Testing\ESB.Testing.TestTxn\bin\ESB.Testing.TestTxns.dll</ComponentServer>
<
Custom> <ParamName>ReturnSpecifiedFile</ParamName>
<
ParamValue>C:\ESB\DevServer2\Source\ESB\Base\Solutions\Main\Management\ESB.Management.Portal\Testing\XMLRequests\ESBCore\ESBTest15_Sync.xml</ParamValue>
</
Custom>
</
MultiLevelOverrides> .....