Monday, 23 October 2006
Hi!

Recently a couple of different question askers at the microsoft.public.biztalk.something newsgroups have been asking questions about how to expose a BizTalk orchestration that takes an System.Xml.XmlDocument as input and also returnes a System.Xml.XmlDocument.

Basically, it is straight forward:
  1. You define two messages in your orchestration as being of the type "System.Xml.XmlDocument"
  2. You add a receive shape that accepts one of the messages
  3. You add a construct shape that constructs the return message
  4. You add a send shape that sends the output message
  5. You add a public request-response port and connect the receive- and send shapes to this port.
  6. You publish the orchestration using the Web Services Publishing Wizard.
A couple of issues:
  1. If you are deploying the web service to the same web site as your Windows SharePoint Services is running on, you have to exclude the path to the new web service, so that WSS wont try to take over the calls to the web service. This is done like this:
    • Administrative Tools
    • SharePoint Central Administration
    • Configure Virtual Server Settings
    • Choose the web site you have extended with WSS and to which you now want to deploy a web service
    • Define Managed Paths
    • Under "Add new Path", add your path and click "excluded path" and "OK"
  2. The virtual directory that is created by the wizard must run under an application pool that is running under a user that is a member of the "BizTalk Isolated Host Users". Otherwise you will get a SOAP exception when trying to call the web service.
And another thing that someone had dificulty with: When writing a small application to test the published web service, he got an error that said:
Compilation error:

            Error    1    The best overloaded method match for
'UNTTest.ws.UntypedWebService_Orchestration_That_Receives_and_Sends_XML_InputOutputPort.SendXMLAndGetAnswer(ref
System.Xml.XmlNode)' has some invalid arguments    C:\Documents and
Settings\simon.brooks\My Documents\UNTTest\Form1.cs    25    13    UNTTest

            Error    2    Argument '1': cannot convert from 'ref
System.Xml.XmlDocument' to 'ref System.Xml.XmlNode'    C:\Documents and
Settings\simon.brooks\My Documents\UNTTest\Form1.cs    25    41    UNTTest

Basically, the web service doesn't take an XmlDocument as a parameter, as one would have expected, but an XmlNode instead.

So after creating an XmlDocument to send to the web service, define an XmlNode object, and set it to point to the DocumentElement property of the XmlDcoument, and send that instead.
Like this:
            XmlDocument xmldoc = new XmlDocument();
            xmldoc.LoadXml("<rootnode><element1>value1</element1></rootnode>");
            XmlNode node = xmldoc.DocumentElement;
            WebserviceReference ws = new WebserviceReference();
            ws.Operation_1(ref node);

I hope this helps.

My sampel BizTalk project can be found here: UntypedWebService.zip (102.58 KB)

Should you have any comments, feel free to post them.

--
eliasen
Monday, 23 October 2006 00:01:48 (Romance Daylight Time, UTC+02:00)  #    Comments [0]  | 
Friday, 13 October 2006

Hi

Every now and then, I come across the need of adding a node to the output of a BizTalk map.

Now, if I just want to add some node which isn't dependent on the input, I can just use a custom scripting functoid which is an XSLT template that just craeted the node for me, like this:

Use the "Inline XSLT Call Template" instead, if you need parameters to your XSLT.

BUT, sometimes I need to add a node to a list of existing nodes. One example of this I came across was the need to have a log inside the XML structure that was updated every time BizTalk touched the document. So there would be a structure inside the XML like this:

<TheLog>
<LogEntry>This is the first log entry and it was added by Jan</LogEntry>
<LogEntry>This is the second entry and it was added by BizTalk</LogEntry>
</TheLog>

So BizTalk needed to add a line to TheLog when BizTalk mapped the document.

Another example is a guy on the microsoft.public.biztalk.general newsgroup that needs to add an OrderItem to an existing list of OrderItems.

To do this, I have only found one solution, which is a custom xslt script that does the whole thing.

My example input schema:

My example output schema:

In both schemas, the "Order"-element can occur multiple times.

The map looks like this:

Basically, just one scripting functoid. Note that no links go from the source document. The scripting functoid is a "Inline XSLT" type, and the source is this:

<xsl:for-each select="//Orders/Order">
<xsl:element name="Order">
<xsl:element name="Ordernumber"><xsl:value-of select="Ordernumber" /></xsl:element>
<xsl:element name="OrderAmount"><xsl:value-of select="Amount" /></xsl:element>
</xsl:element>
</xsl:for-each>

<xsl:element name="Order">
    <xsl:element name="Ordernumber">400</xsl:element>
    <xsl:element name="OrderAmount">40</xsl:element>
</xsl:element>

Basically, the for-each creates line in the output according to the input XML document. And the xsl:element after the for-each creates the new node.

You can find my BizTalk 2006 project here: AddingANode.zip (16,89 KB) - it should work with BizTalk 2004 as well.

I hope this has helped someone. Comments are welcome.

--

eliasen

Friday, 13 October 2006 23:26:57 (Romance Daylight Time, UTC+02:00)  #    Comments [3]  | 

Hi

A user in the microsoft.public.biztalk.general newsgroup has a challenge he'd like solved.

Basically, he has this structure:

<Root>
  <Employee>
     <EmployeeID>1</EmployeeID>
     <JobsAssigned>10</JobsAssigned>
  </Employee>
  <Employee>
     <EmployeeID>2</EmployeeID>
     <JobsAssigned>5</JobsAssigned>
  </Employee>
  <Employee>
     <EmployeeID>3</EmployeeID>
     <JobsAssigned>8</JobsAssigned>
  </Employee>
</Root>

And he needs to find the EmployeeID of the employee that has the least jobs assigned to him/her. In this case, he needs the value "2".

This is a case, where the "Cumulative Minimum" functoid can be used.

So, I have this input schema:

and I have this fictitious output schema:

To do the task, I use this map:

Basically, I just map the fields, and then I make sure the "MinValues"-record is only created when the JobsAssigned value is equal to the cumulative minimum of the JobsAssigned.

The "Cumulative Minimum" functoid will return the smallest number of all the numbers it is given as input.

So, given the above mentioned input instance, the output of this map will be:

<ns0:OutputRoot xmlns:ns0="http://CumulativeMinimum.OutputSchema">
<MinValues>
  <Employee>2</Employee>
  <JobsAssigned>5</JobsAssigned> 
</MinValues>
</ns0:OutputRoot>

which, luckily, was what we needed :-)

Given an instance with more than one Employee hacing the same number of JobsAssigned and if this number is the minimum, the map will actually create a node for each.

As I don't know more of what the question-asker wants, I will let this be enough for now. Should it not be ok to return more than one EmployeeID in the output, the map will need to be changed.

I hope this has helped someone.

You can find a BizTalk 2006 project here: CumulativeMinimum.zip (4,51 KB)

The same will work for BizTalk 2004 - I just haven't been bothered creating the example. Let me know if you need it.

--

eliasen

Friday, 13 October 2006 22:23:30 (Romance Daylight Time, UTC+02:00)  #    Comments [0]  | 
Thursday, 12 October 2006

Hi

It so really annoys me whenever I have to change my ways of doing things because some people insist that it is okay to bother others.

Spam is a great example - the mere fact that I can't write my email address in a public place without receiving spam the next day. Sigh.

Anyway, I, as many others, have disabled trackbacks on my blog, since it was filling up with porno and other stuff.

Should anyone have a good solution for dasBlog, le tme know :-)

--

eliasen

Thursday, 12 October 2006 15:37:36 (Romance Daylight Time, UTC+02:00)  #    Comments [0]  | 

Theme design by Jelle Druyts