One way to check for missing data is to do an xpath count.

The two-step approach (put the xpath in a variable first). Some might find this code cleaner, but you use a variable. Note that you have to use the conversion statement to convert the string result of the xpath to a number, if you need to test that number as I do in the following “if” statement.

 

strCountMessageKeysXPath = "count(//*[local-name()='MessageKey']";

intCountMessageKeys =
System.Convert.ToInt32(
xpath(msgCreateSPServiceOrderAckResp.parameters,strCountMessageKeysXPath)
);

// Yes you can put if statement in expression shapes (but not message assignment shapes) 
if (intCountMessageKeys >= 2) 
{
   strXPath = "//*[local-name()='MessageKey'][2]"; 
   strWebRespMessage2Key = xpath(msgCreateSPServiceOrderAckResp.parameters,"string(" + strXPath + ")"); 
}

 

The one-step approach:

 

strCountMessageKeysXPath = ;

intCountMessageKeys =
System.Convert.ToInt32(
xpath(msgCreateSPServiceOrderAckResp.parameters,"count(//*[local-name()='MessageKey']")
);
// Yes you can put if statement in expression shapes (but not message assignment shapes) 
if (intCountMessageKeys >= 2) 
{
   strXPath = "//*[local-name()='MessageKey'][2]"; 
   strWebRespMessage2Key = xpath(msgCreateSPServiceOrderAckResp.parameters,"string(" + strXPath + ")"); 
}

 

 

NOTE: The reason I have .parameters after the message is that it is a multi-part message.
If you don’t get that correct, you may get the error “The expression you have entered is not valid”, or “An xpath expression must be of the form” if you hover over the error.

 

If you get the error “An xpath expression must be of the form …” (in an expression shape of a BizTalk orchestration), here’s one possible solution.

I was using a multi-part message, so instead of msgCreateSPServiceOrderAckResp, I had had to specify msgCreateSPServiceOrderAckResp.parameters.

The compiler just shows the error “The expression that you have entered is not valid”. But when you find the small red mark, and mouse over it, you see the following:

Here is the corrected version:

 

 

 

Today, I was tasked with upgrading an orchestration from calling one version of a web service (version 3), to a newer version 4.

Fortunately, it was backward compatible, i.e. I didn’t have to remap any fields. However, the schema was renamed, as it actually had the version number in the web service name. So how does one do this in BizTalk?

In this case, I’m sure there are many paths to the same destination, but here are the steps I followed.

1. I opened a new temporary Visual Studio BizTalk project and consumed the new web service (using the “Add Generated Items” / “Consume WCF Service”). The reason I did it in a separate new project is that it creates the dummy orchestration, and the binding files.

2. I then copied the 2 or 3 schema files to my actual project.

3. I checked my map out (from source control), and opened it in NotePad++ and had to do one small surgery. I had to find Reference Location=”..\WebServices\PlaceOrder_V3.xsd” and replace it with “..\WebServices\PlaceOrder_V4.xsd”. I could have tried it in map, but I’ve seen too many cases where you lose all your mappings, so I did it this way. I then opened the map to verify, and all looked good there.

I then removed the old web service schema, and did a Rebuild, just to see what would happen, which lead to the next two steps.

4. I had to reassociate my Multi-part Message types. Since the messages were using multi-part message types, they were okay as is. But I had two messages types (one for the web service request, and one for the response) that were “red” and had to change. So I just had to carefully pick the new .xsd name for each. (Could have done this also by editing the .odx file, if done carefully.)

5. If you had promoted (or distinguished fields) on the web service schema, you would have to redo those, and that was the case in this orchestration. Then, a really weird scenario happened. Every expression shape that was using the distinguished fields was getting an error. There was not red squiggly line under the items, just a compile error. Even closing and reopening Visual Studio did not solve it.

In one case, I re-typed the msg.property_name using Intellisense, and that solved the issue. For another shape, I did the same thing and it wouldn’t go away. I took a wild stab at it, and created a new expression shape, cut and pasted the statements from the old shape to the new shape, then it compiled clean. I cannot explain that part at all!

6. I’m about to change the URL in the SendPort now, and start testing. I’ll update if anything else unusual happens. I did not use the binding files created by the “Add Generated Items” in the first step above.

6a. Things went bad during testing, took me way too long, like 2 hours to get it working. I had to deploy to QA environment, because it was easier to test.
6b. One issue I had forgot was that the SOAP Action Headers needed to change (in the General configuration tab of the SendPort), for example:
<Operation Name=”PlaceOrder” Action=”http://mysite.com/webservices/neworder_v3/2013/01/PlaceOrder” />
<Operation Name=”PlaceOrder” Action=”http://mysite.com/webservices/neworder_v4/2015/11/INewOrder/PlaceOrder” />

6c. For some reason, it still didn’t work. I’m checking with the authors of the webservice if they change anything else. To finally get it to work, I had to take the CustomBindings.xml file, and run it on the QA system, then change my orchestration bindings to use the new SendPort.

While there can probably be many reasons for this error, here’s one that I had:

msgNew() = “http://MySite.com/MyApp/MyService.svc”;

There was not value in the parentheses. For some reason, this does NOT put the red exclamation point on the Message Assignment shape.

 

I had been testing the following, then changed it, and forgot and left it blank

msgNew(BTS.OutboundTransportLocation) = “http://MySite.com/MyApp/MyService.svc”;

 

 

 

 

One of the characteristics that separates the good from the great Biztalk developers and architects, is handling of errors, particularly SOAP errors.  This is often not tested sufficiently.

This blog by Shashidharan Krishnan does a good job of explaining how to catch a SOAP error in a BizTalk Orchestration:
http://blogs.msdn.com/b/biztalknotes/archive/2013/02/12/how-to-handle-fault-message-in-biztalk-server.aspx

I’d like to throw in some ideas that I implemented today.
Based on the blog above, I created the xpath below, a slightly simpler form to grab two of the main SOAP Fields. I only wanted the two most critical, in order to save space (I’ll discuss more about my column size limitations below). I didn’t want all the namespaces and SOAP wrappers, that just cluttered up any error that the user might see.

//SOAPEXECPTION_11 is my 'Exception Object Name' specified in the Catch (of the Scope) Properties 
strSoapFaultcode   = xpath(SOAPEXCEPTION_11, "string(//*[local-name()='faultcode'])");
strSoapFaultstring = xpath(SOAPEXCEPTION_11, "string(//*[local-name()='faultstring'])");

// format my own condensed error consisting of the above two parts 
strValue = "SoapFaultCode=" + strSoapFaultcode + " SoapFaultString=" + strSoapFaultstring; 

// Single quotes cause SQL to blow up, 
// truncate to 1000 (so we can put two fault codes in one DB field 
strValue = strValue.Replace("'","''");
vWebServiceAResponseMessage = strValue.Substring
   (0,System.Math.Min(strValue.Length,vMaxSizeEachSoapError));

The site where I’m working wanted to store the error back in a database table via a web service. Basically, the is a table that represents the canonical schema. A “poller” job extracts data from that table, writing a canonical XML to disk. An orchestration picks it up, and processes it. That same orchestration then calls a web services that was provided to me to update the same row of that table with the success or failure codes. If any webservice or SOAP errors are encountered, an flag is set, and that row can be re-queued to be be polled and processed again later after those errors have been fixed.

The database column for the error was a max of 2000 characters, and was not an XML column, just a varchar2(2000) column in an Oracle database. So if I passed to big of a field, the web service would blow up with a size issue on the SQL column. So it became my job to make sure my errors fit.

Now, to further complicate matters, imagine this scenario. I called WebService-A, then WebService-B. Each could have a SOAP error. Then I call WebService-C to actually update the table. So basically, I had to get a max of 1000 characters of error for each of the WebServices A and B, for a max of 2000. In some cases, you would not even call WebService-B if it were dependent on results from A; but in my case, they wanted to store the error from A into the backend ERP system (which is what WebService-B was updating).

So I was also dealing with a scenario where A could succeed and B could fail, A could fail and B could succeed, both could succeed or both could fail. I did this with just a normal decide shape with 4 or 5 branches. I set string variables there, then had one construct/message assignment afterward, using those string variables to construct the message request for WebService-C.

Further, if the SOAP message had single quotes in it, that was messing up SQL, so I had turn each single quote into two single quotes. (If you are not familiar with this, the classic case is LastName = O’Brian needs to be treated as O”Brian. Typcially, the database server is set up to handle to consecutive single quotes as one single quote, and helps avoid confusion with the single quotes used in the SQL syntax.

Here are two other thoughts to consider. Should your orchestration be flexible enough to handle SOAP 1.1 and SOAP 1.2 errors? I usually don’t go that far, but the guy I worked with did. It’s nice and flexible, but causes a little extra bloat in the orchestration.

For the final thought, there can be “hard” SOAP errors, or soft business/errors. At this client, the web service typically return a Result that was either set to “Ok” or some error. So in addition to checking the SOAP errors, I had to check that error as well. This is fairly typical.

In other orchestrations that I’ve recently written, I created a common error handler, then threw an internal exception or set an “IsError” variable/flag, so that the common error handler could run once as needed. That way, I could treat SOAP 1.1, SOAP 1.2, or soft/business errors using the same logic. Orchestrations don’t allow easily for re-useable code. You either have to call a sub-orchestration, use direct-binding to call another orchestration, call C# code, or try to create a code block that runs based on flags. Having separate orchestrations can make restart a big pain.

And what do you do when your exception handling webservice itself has an error?  I’ll leave that for you and your architect.  Here, we “pretty print” all XML request/responses that have errors, and email them to a distribution group.

How to cause a SOAP error to Test a BizTalk Orchestration

Changing the URL didn’t do it, that caused an XLANG/s exception, with a service not found exception, as shown below:

Error Description: System.ServiceModel.EndpointNotFoundException: There was no endpoint listening at http://mysite.com/MyService/MyServiceName2.svc that could accept the message. This is often caused by an incorrect address or SOAP action. See InnerException, if present, for more 

 


In the real world, an error like this would be fixed by changing the URL and resuming the orchestration.

One thing I do to force a SOAP exception is to edit the WCF SendPort, and modify the “Action” block on the General tab. I save the original values to NotePad++, then remove or change the values of the: <Operation Name=”value”…
You may have to restart the host instance, then run the test.

This results in the following error:

  a:ActionNotSupported
  The message with Action '&lt;BtsActionMapping xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"&gt;
  &lt;Operation Name="MyMethod" Action="http://tempuri.org/IMyService/MyMethod" /&gt;
&lt;/BtsActionMapping&gt;' cannot be processed at the receiver, due to a ContractFilter mismatch at the EndpointDispatcher. This may be because of either a contract mismatch (mismatched Actions between sender and receiver) or a binding/security mismatch between the sender and the receiver.  Check that sender and receiver have the same contract and the same binding (including security requirements, e.g. Message, Transport, None).

When you are done testing your exceptions, then copy back what you saved in NotePad++.

If you happen to be the author of the webservice (or the author is inclined to work closely with you), you might want to code in a web service exception that will be sent back as SOAP exception. Use some flag or freaky/sneaky set of values to trigger the exception (make sure those values would never occur in the real production environment).

I had this case again today, where I got “Root element is missing”. The code was working, I made some changes, and boom, an existing code path started blowing up. It was actually a trace routine, where I had the following code:

   xmlDoc = msgWhatever;
   //then I passed as a parameter:  
   CallCSharpMethod(xmlDoc.OuterXml)... 

So here is the code I added, above the section that bombed:

   // Avoid compile erorr "Use of unconstructed message 'msgCanonicalErr'
   // in the common error handler after the end of the big Decide Block
   xmlDoc.LoadXml("<Dummy />");
   msgCanonicalErr = xmlDoc;

The simple fix was to create another xmlDoc variable with another name:

   // Avoid compile erorr "Use of unconstructed message 'msgCanonicalErr'
   // in the common error handler after the end of the big Decide Block
   xmlDocInitializer.LoadXml("&lt;Dummy /&gt;");
   msgCanonicalErr = xmlDocInitializer;

I think another solution would have been to reset the xmlDocument variable, but I preferred the above approach:

   xmlDoc = new System.XmlDocument(); 

We all hate to use Atomic Scopes in BizTalk orchestrations when not needed.  I have a static C# Trace routine that normally takes passing an enum of System.Diagnostics.TraceLevel (for Error, Warning, Info, etc…).   In the current project, our web services can return “soft errors” in a common field called “Result”.

So I could have used a Decide shape, but since the code repeats on many webservices, I wanted to us an if/else statement in an expression shape called “GetResults” (in picture below).

if (msgResponse.RESULT == "Ok")
  {
     vTraceLevel = System.Diagnostics.TraceLevel.Info;
  }
else   
  {
     vTraceLevel = System.Diagnostics.TraceLevel.Error;
  }
if (msgResponse.RESULT != "Ok")
{
  strSoapFaultMessage = "2510:msgResponse:" + msgResponse.Message;
  throw new System.ApplicationException(strSoapFaultMessage); 
}

The reason I coded like this is that I had a large orchestration with about 8 web service calls, and I wanted a common error handler for all of them. That Catches a System.ApplicationException, writes to EventLog, and sends an email with the full Request and Response XML of the call/response to/from the web service.

Now all this happens to be in a debatching loop. When I ran it, and had multiple errors, the first one had a blank response in the email, and the second and third ones worked. It seems very inconsistent, but here’s what a colleague and I figured out.

In the picture below, my original shapes are on the left, and the revision is on the right. Scope_C_NonSerializable_TraceLevel was an Atomic Transaction to support the fact that TraceLevel was non-serializeable. So if the orchestration blows up in this Scope, it would have to restart at the beginning of the scope.

My mistake was to include the “Throw” in that scope. Apparently the “Throw” sometimes acts as sort of a Rollback, and clears some or all variables set in that Scope.

In the shape called “TRC 2510”, I had the following, along with a call to my C# trace routine.

xmlDocResp = msgAsurionOrderRoutingResponse; 

So when the Throw happens, at least on the first time through the loop, the xmlDocResp had no value. Simply moving the “Throw” and “Trc 2511” outside the loop seemed to solve the issue.

Orchestration_Scope_Throw_Issue

The Catch you see above is the Captch of the BTS.soap_envelope_1__1.Fault.  It also sets xmlDocResp to the value of the SoapFault, and throws an ApplicationExcpetion so that same error handler can work for both Soap Faults and the “soft” web service errors.

The common error handling had the following in a message assignment shape:

tempStrBuilder.AppendLine("===========================");
tempStrBuilder.AppendLine("Request Message:");
tempStrBuilder.AppendLine(System.Convert.ToString(xmlDocReq.OuterXml));
tempStrBuilder.AppendLine("===========================");
tempStrBuilder.AppendLine("Response Message:");
tempStrBuilder.AppendLine(System.Convert.ToString(xmlDocResp.OuterXml));
tempStrBuilder.AppendLine("===========================");

I’m considering adding a C# formatter to do a “pretty print” on the XML (done) to make the error email look even nicer, probably based on the code on this Stackoverflow page.

Here are some helps for this error that I got today:
Error: a non transactional scope 'unnamed' may not contain a transactional scope 'Transaction_3"

When you click on the error in the Visual Studio Error list, it should take you to one of the scopes involved in the error.

In my case, I had a Scope’s Transaction Type set to “None”, and I needed to change it to “Long Running”.  Inside that Scope, I had a small Atomic scope, that had to be used to have an instances of a class that was not serializeable.

One thing you can do is to make debugging easier is to label your scopes, and manually set the “Transaction Identifier”.

For example: Scope_A_Call_WebService_MyMethod1, then set the “Transaction Identifier” to Transaction_A.
Then when you get the error, you can easily tell which Transaction ties to which Scope.

The scope will be “unnamed” if you set “Transaction Type” to “None”.

You can use the Orchestration Viewer to fairly easily see how the Scopes are nested.

 

 

 

Have you been looking for how to find the string text specified in the BizTalk Terminate Shape?  I hadn’t used this shape in a long long time, and had to check it out again this week.  This blog show you you where the Terminate Shape text goes.

After your orchestration has hit a Terminate statement, you can do the following two steps:

1. In BizTalk Admin, go to the group hub, and click on “Terminated Instances”.

Terminate_TerminatedInstances

2. Find the terminated instance of your orchestration.

Terminate_TerminateMessageText

The text does NOT appear in the application EventLog. You would have to do a System.Diagnostics.Write.EventLog in an “Expression Shape” to do that.

For example:


System.Diagnostics.EventLog.WriteEntry(
vEventSource,
vMessageStr,
System.Diagnostics.EventLogEntryType.Error);

The orchestration is terminated, not suspended, so there is nothing to be seen in the “Suspended” query.

In this blog by Yossi Dahan, he talks about how there should perhaps be an “End” shape that doesn’t imply a termination/error.

By the way, even thow there is a “Throw” shape in BizTalk Orchestrations, there’s nothing to stop you from doing a .NET “Throw” in an “Expression Shape”, for example:


if (vCO_HeaderUpdateResult != "Ok")
{
strSoapFaultMessage = "2240:msgCO_Header_Update_Response:" + vCO_HeaderUpdateMessage;
throw new System.ApplicationException(strSoapFaultMessage);
}

In the program above, I caught a “soft error”, i.e. the I called a web service that completed without a hard Soap error, but it set an error in the variables that it returned. Thus, I raised an error via the “Throw” keyword, then caught the error in the Exception Handler of a scope. This allowed me to have one common error handling routine for the 10 different web services that I was calling in the one orchestration. That common routine wrote to the EventLog, Sends and Email via an email send port, writes to a Trace, and then does ends the orchestration, probably via the Terminate statement (still need to discuss with my colleagues).

I got this error today in a BizTalk orchestration: “Identifier “abc” does not exist in ‘global_NS.AppName”; are you missing an assembly reference?” Basically, the auto-complete (Intellisense) wasn’t giving my .BizTalkComponents namespace after I typed in “AppName.”. So I typed it in anyway, and pressed CNTL-Space-Bar, and that’s when the error occured.

I had typed in AppName.BizTalkComponents, which was a valid namespace in C# program, to which I had made a project reference.

Normally, I follow naming conventions that match the BizTalk Deployment Framework, but in this case, I has an old application, written by a predecessor. I use a Find/Replace Utility to replace the namespace from NewAppname to Appname.
So, the namespace of the orchestration itself was Appname. I should have named it Appname.BizTalk or something similar.

So to fix the issue, I overrode the namespace of the orchestration to Appname to Appname.BizTalk (as shown below):

BizTalk_Orchestration_Namespace