Localization Update for the BizTalk Server 2006 Documentation

German: http://www.microsoft.com/downloads/details.aspx?displaylang=de&FamilyID=3294ddaf-9f67-409f-a92d-2f6070dc0d1a


French: http://www.microsoft.com/downloads/details.aspx?displaylang=fr&FamilyID=3294ddaf-9f67-409f-a92d-2f6070dc0d1a


Italian: http://www.microsoft.com/downloads/details.aspx?displaylang=it&FamilyID=3294ddaf-9f67-409f-a92d-2f6070dc0d1a


Spanish: http://www.microsoft.com/downloads/details.aspx?displaylang=es&FamilyID=3294ddaf-9f67-409f-a92d-2f6070dc0d1a


Japanese: http://www.microsoft.com/downloads/details.aspx?displaylang=ja&FamilyID=3294ddaf-9f67-409f-a92d-2f6070dc0d1a


Korean: http://www.microsoft.com/downloads/details.aspx?displaylang=ko&FamilyID=3294ddaf-9f67-409f-a92d-2f6070dc0d1a


Chinese (Simplified): http://www.microsoft.com/downloads/details.aspx?displaylang=zh-cn&FamilyID=3294ddaf-9f67-409f-a92d-2f6070dc0d1a


Chinese (Traditional): http://www.microsoft.com/downloads/details.aspx?displaylang=zh-tw&FamilyID=3294ddaf-9f67-409f-a92d-2f6070dc0d1a

Fixing "SOAP / Envelope Schema" Error In BizTalk


I was stuck with a shockingly frustrating error message in BizTalk, but thanks to an obscure tweak identified in the BizTalk Developer’s Troubleshooting Guide, all is right with the world.


The error I kept getting was Document type does not match any of the given schemas. How did this come about? I receive a batch message into BizTalk, and want each item in the batch to process through the orchestration individually. No problem, just use the standard XML Receive Pipeline and an envelope schema, and *poof* you have debatching. Worked fine with a FILE adapter. Once I created a web service input channel (doing an “expose schema as web service” since the orchestration accepts an individual message, but BizTalk itself must accept the full batch) I started getting the error above. What was mind-boggling was that the schema was indeed deployed and listed in the server repository. I even ran SELECT * FROM bt_documentspec ORDER BY msgtype DESC against the MessageBox database to ensure that my namespace#root was a visible object to BizTalk. Clearly something in the generated web service was hosing me, but everything looked fine to me.


So, how did I fix this? The newsgroups were no help, as I never found anyone who got an answer to this question. After banging my head for a few hours, I took a break to read the BizTalk Developer’s Troubleshooting Guide. I see the question in the document which says Why do I receive errors when publishing my envelope schema? Hey, that’s MY problem! The solution was:

To modify the generated Web project for envelope schemas


  1. Open the .asmx.cs file.

  2. Edit the file and change bodyTypeAssemblyQualifiedName = <dll.name.version> to bodyTypeAssemblyQualifiedName = null

As soon as I did that, and reset IIS, my error went away. I’ve never seen that documented anywhere, which is odd given that this scenario doesn’t seen that outlandish. Hopefully this helps some poor soul in the future.


Technorati Tags: BizTalk

Fixing &quot;SOAP / Envelope Schema&quot; Error In BizTalk

I was stuck with a shockingly frustrating error message in BizTalk, but thanks to an obscure tweak identified in the

BizTalk Developer’s Troubleshooting Guide, all is right with the world.

The error I kept getting was Document type does not match any of the given schemas. How did this come about? I receive a batch
message into BizTalk, and want each item in the batch to process through the orchestration individually. No problem, just use
the standard XML Receive Pipeline and an envelope schema, and *poof* you have debatching. Worked fine with a FILE adapter. Once I created a
web service input channel (doing an “expose schema as web service” since the orchestration accepts an individual message, but BizTalk itself must
accept the full batch) I started getting the error above. What was mind-boggling was that the schema was indeed deployed and listed in the
server repository. I even ran SELECT * FROM bt_documentspec ORDER BY msgtype DESC against the MessageBox database to ensure that my namespace#root
was a visible object to BizTalk. Clearly something in the generated web service was hosing me, but everything looked fine to me.

So, how did I fix this? The newsgroups were no help, as I never found anyone who got an answer to this question. After banging
my head for a few hours, I took a break to read the
BizTalk Developer’s Troubleshooting Guide. I see the question in the document which says Why do I receive errors when publishing my envelope schema? Hey,
that’s MY problem! The solution was:

To modify the generated Web project for envelope schemas

  1. Open the .asmx.cs file.
  2. Edit the file and change bodyTypeAssemblyQualifiedName = <dll.name.version> to bodyTypeAssemblyQualifiedName = null

As soon as I did that, and reset IIS, my error went away. I’ve never seen that documented anywhere, which is odd given that this scenario
doesn’t seen that outlandish. Hopefully this helps some poor soul in the future.

Technorati Tags: BizTalk

Tracking Rules Execution in Windows Workflow

In my previous blog entry on

Tracking and the TrackingExtract functionality
I talked about the ability to
track the rules that fired.  As part of this functionality I needed to
capture the rules that fired as well as to capture an XML representation of the
object state (this is where the TrackingExtract functionality came in) to the
database so that reporting systems could look at the data.  When I first
started researching to find out if this functionality existed I came across a
great tracking
sample
on Moustafa Ahmed’s blog. 
This sample shows how you can use the standard tracking infrastructure to track
the rules. 

Unfortunately, the standard tracking functionality didn’t do exactly what I
was looking for.  First, the data is written to the UserEvent table in the
UserData_Blob field and shows up as
0x0001000000FFFFFFFF01000000000000000C020000005D53797374656D2E576F726B66…….,
which, represented the serialized object, but was somewhat unreadable. Next, I
would need to deserialize this data and cast it to a RuleActionTrackingEvent
type in order to work with it for reporting.  And lastly, I wanted to store
additional data that was not part of the UserEvent table.

So, I needed to augment the standard functionality with my functionality. 
I started by creating two new tables that would live in the tracking database. 
The first was the RulesTrackingData table and the second was the
UserTrackingData table.  They were defined as

CREATE TABLE
[dbo].[RulesTrackingData](
    [id] [bigint]

IDENTITY(1,1)
NOT NULL
,
    [ComputerName] [varchar](25)

NOT NULL,
    [ActivityType] [varchar](50)

NOT NULL,
    [InstanceID] [varchar](40)

NOT NULL,
    [EventDateTime] [varchar](50)

NOT NULL,
    [PolicyName] [varchar](50)

NOT NULL,
    [RuleName] [varchar](40)

NOT NULL,
    [ConditionResult] [varchar](10)

NOT NULL,
    [TrackingRecord] [varchar](500)

NOT NULL
)

and

CREATE TABLE
[dbo].[UserTrackingData](
    [id] [bigint]

IDENTITY(1,1)
NOT NULL,
    [ComputerName] [varchar](25)

NOT NULL,
    [ActivityType] [varchar](50)

NOT NULL,
    [InstanceID] [varchar](40)

NOT NULL,
    [EventDateTime] [varchar](50)

NOT NULL,
    [TrackingRecord] [varchar](500)

NOT NULL

)

The RulesTrackingData table will hold the tracking data for each rules that
runs while the UserTrackingData will hold the state of the object after all of
the rules have run.

After the database had been setup it was time to work on the code.  I
created a custom tracking service for the Workflow Runtime.  As part of my
RuleTrackingService I created a RuleTrackingChannel class which inherited from
TrackingChannel and a RuleTrackingService class which inherited from
TrackingService.  To find out more about the RuleTrackingService take a
look at my previous blog entry on

Tracking and the TrackingExtract functionality
.  Right now we are just
going to focus on the RuleTrackingChannel class since this is where we get to
grab the tracking data and write it the way we want to the database. 

So the code looked like this:


public
class

RuleTrackingChannel : TrackingChannel

{
…………
 


public
RuleTrackingChannel(……..
)
{
}

//This is what it all comes down to!

protected
override
void

Send(TrackingRecord record)
{

   
if
(record
is

UserTrackingRecord)

{
DetermineTrackingRecordType((UserTrackingRecord)record);
}

}


private
void

DetermineTrackingRecordType(UserTrackingRecord userTrackingRecord)
{

   
if
(userTrackingRecord.UserData
is

RuleActionTrackingEvent)

{
WriteRuleTrackingRecord((RuleActionTrackingEvent)userTrackingRecord.UserData,
userTrackingRecord);
}

   
else

{
WriteUserTrackingRecord(userTrackingRecord);
}

}

//
This method writes a record to the database for each rule that fires. This
record represents the data before the rule fired.

private
void

WriteRuleTrackingRecord(RuleActionTrackingEvent ruleActionTrackingEvent,
UserTrackingRecord userTrackingRecord)
{


string
PropXml =
string.Empty;


if
(
this._trackedProperties
!=
null
)

{
PropXml = CreateXmlFragment(userTrackingRecord, "RuleTrackingSnapshot");
}

//At some
point we might want to change this to a stored proc
SqlCommand command =
new
SqlCommand();
command.Connection =

new
SqlConnection(_connectionString);

command.Connection.Open();
SqlDataAdapter adapter =

new
SqlDataAdapter();
StringBuilder commandString =

new
StringBuilder();

commandString.Append
("INSERT INTO TrackingStore..RulesTrackingData ");
commandString.Append("(ComputerName, ActivityType, InstanceID, EventDateTime,
PolicyName, RuleName, ConditionResult, TrackingRecord)");
commandString.Append(String.Format("VALUES
(‘{0}’,'{1}’,'{2}’,'{3}’,'{4}’,'{5}’,'{6}’,'{7}’)",
System.Environment.MachineName,
userTrackingRecord.ActivityType.FullName.ToString(),

this._instanceID
,System.DateTime.Now, userTrackingRecord.QualifiedName.ToString(),
ruleActionTrackingEvent.RuleName.ToString(),
ruleActionTrackingEvent.ConditionResult.ToString(), PropXml));


command.CommandText = commandString.ToString();
command.ExecuteNonQuery();
command.Connection.Close();
}
 


private
string
CreateXmlFragment(UserTrackingRecord userTrackingRecord,

string

rootNodeName)
{

XmlDocument doc =
new
XmlDocument();

XmlDocumentFragment doctype;
doctype = doc.CreateDocumentFragment();
doc.AppendChild(doctype);
doc.AppendChild(doc.CreateElement(rootNodeName));
XmlNode root = doc.DocumentElement;


for(int

i = 0; i < userTrackingRecord.Body.Count; i++)
{

XmlElement elem =
doc.CreateElement(userTrackingRecord.Body[i].FieldName.ToString());
elem.InnerText = userTrackingRecord.Body[i].Data.ToString();
root.AppendChild(elem);

}

   
return
doc.InnerXml;

}

 

In the Send method I make sure that I am only grabbing UserTrackingRecord
objects and then I check to determine if I have a RuleActionTrackingEvent
object.  If so then I am ready to start writing to the RulesTrackingData
table.  In the WriteRuleTrackingRecord method I create the XML snapshot of
the object state and then create my SQL insert statement.  Once the Send
method is called I can start to grab data from the RuleActionTrackingEvent
object and the UserTrackingRecord object to fill in the table with the data we
need.  I have included the computer name as one of the fields since the
rules run on the client side I need to make sure that I can determine where the
rules ran.  Since this is a snapshot of code, I have left out some other
functionality and did not take time to refactor the code for this example and
could have consolidated it a bit.  Anyways, once this code runs and data is
written into the RuleTrackingData table it will look like the following (I will
let you compare the fields with the table structure above (I put a : as a field
separator to make it easier to read)):

4 : WFTEST : System.Workflow.Activities.PolicyActivity :
4091dc04-43fe-4dde-8b80-ba837c9cc9a0 : 8/30/2006 7:03:37 AM :
simpleDiscountPolicy : ResidentialDiscountRule : True : <RuleTrackingSnapshot><orderValue>600</orderValue><discount>2</discount></RuleTrackingSnapshot>
 

As you look at all of the data written to the database you should pay close
attention to the ConditionResult field (which gets populated from
 ruleActionTrackingEvent.ConditionResult)
.  This will show ‘true’ for each rule in which the predicates match and
the condition is executed.  This column will show ‘false’ for a rule where
the predicates do not match and the else condition was executed.  For a
rules in which the predicates do not match and there is no else condition then a
record will not be written to the database table.  In addition, the data
that is available to track contains the state of the object before the rules
execute and therefore the database contains the before snapshot.  When many
rules run it becomes quite easy to select the rules and look to see what rules
had what affect.  The problem is that we also needed to have a snapshot of
the object after all of the rules ran.  In the code able there is a call to
a method that I didn’t include called WriteUserTrackingRecord.  This method
is very similar to the WriteRuleTrackingRecord method but only contains enough
data to join to the data in the RulesTrackingData table and to contain an XML
representation of the end state.  What makes this different is that in
order to get this final state I needed to place a Code Activity after my Policy
Activity.  In the Code Activity I included the following line of code:

this.TrackData("WholeObject",
crr);

where crr is the object that I passed into the rules engine.

The TrackData takes the object and passes it as a UserTrackingRecord which
when I receive it I call the WriteUserTrackingRecord method.  Since I am
taking this snapshot after the policy runs I will get one of these database
entries whereas I will get as many database entries as the number of rules that
run in the RulesTrackingData table.

 

 

 

 

Multiple SOAP Ports dont seem to be called based on CBR

Seems like it’s the night for a braindump over the last couple of weeks…..

Hotfix 923632 will do the job.

Also
be sure to follow these steps after applying hotfix 923632:

 
1.  Open regedit and go to HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\BTSSvc$<HostName>

 
Make sure host name is the name of the BizTalk host which is publishing messages which
are routed to multiple req/resp subscribers.

 
2.  At that key, add the DWORD value AllowMultipleResponses and set it to a value
of 1.

3. 
Restart the host service after making this change.

Installing BizTalk 2006 Server on multiple servers

Installation
and config guides, including multi-server are here:

http://www.microsoft.com/downloads/details.aspx?FamilyId=B273269C-97E0-411D-8849-5A8070698E4A&displaylang=en

Planning
for High Availability here –
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/BTS06CoreDocs/html/16feada0-b0b1-4e58-9477-fbd1aae2f51e.asp?frame=true

 I
keep needing these so I thought I’d store them some place handy 🙂