Wednesday, April 23, 2008

Unable to evaluate expression because the code is optimized or a native frame is on top of the call stack

Recently, I got a weird error in my ASP.NET page:
Unable to evaluate expression because the code is optimized or a native frame is on top of the call stack
This is what I was trying to do:

protected override void Page_Load(object sender, EventArgs e)
{
try
{
..
..
if (! IsUserAuthorized(i))
{
RedirectToParentPage();
return;
}
..
..
}
catch (Exception ex)
{
//Do something
..
}
}


private void RedirectToParentPage()

{

Response.Redirect(nextpage.aspx);

}
As usual, I googled and found a few related articles. There is one that I found on Microsoft support site http://support.microsoft.com/kb/312629/EN-US/. It states that both Response.Redirect and Server.Transfer methods call Response.End internally. The Response.End method ends the page execution and shifts the execution to the Application_EndRequest event in the application's event pipeline. The line of code that follows Response.End is not executed. This results in a ThreadAbortException exception. This clearly explains why the above piece of code resulted in this exception.
The article suggests that we use an overload of Response.Redirect Response.Redirect(String url, bool endResponse) that passes false for the endResponse parameter to suppress the internal call to Response.End.
For example:
Response.Redirect(nextpage.aspx, false);
Also, I noticed that this problem occurred only if the Response.Redirect was enclosed in a try-catch block since I had a similar piece of code somewhere else, but which was not exclosed in a try-catch block. I couldn’t remove the try-catch block since it was required for some existing code written there.
One more option would be enclose the Response.Redirect in a specific try-catch block that caught ThreadAbortException exception and do nothing in catch block. This is certainly not the right way to code.

Hence, I modified the above code as shown below:

protected override void Page_Load(object sender, EventArgs e)

{
try
{
..
..
if (! IsUserAuthorized(i))
{
RedirectToParentPage();
return;
}
..
..
}
catch (Exception ex)
{
//Do something
..
}
}

private void RedirectToParentPage()
{

/* Use an overload of Response.Redirect to suppress the call to Response.End method. The Response.End method ends the page execution and shifts the execution to the Application_EndRequest event in the application's event piipeline. The line of code that follows Response.End is not executed. This results in a ThreadAbortException exception. */

Response.Redirect(nextpage.aspx);

/* Call CompleteRequest method to to bypass the code execution to the Application_EndRequest event. */
HttpContext.Current.ApplicationInstance.CompleteRequest();
}
}





An introduction to InfoPath 2003

I got an opportunity to work on InfoPath 2003 about 2 years back. It was for a very short time, but a few months back we, by we I mean, me and a colleague of mine were asked to share our experience on the same at the organization level as a part of knowledge sharing exercise. That is when I started digging into it again. It wasn’t a very matured technology at the time we worked on it, we wouldn’t get enough resources on the internet too in case of issues and troubleshooting. That also led to applying some tricks to achieve some of the functionalities (I’ll discuss some of these in my next article); nonetheless, it was a very exciting experience working on InfoPath. You can view the presentation below:

Tuesday, April 22, 2008

Interesting stuff about BizTalk Server 2006 Business Rules Engine

I came across some interesting stuff about BizTalk Business Rules Engine and thought that I could consolidate my findings here with appropriate references. I have tried to list all references as far as possible, but it could be possible that I have missed out some since I had done this research quite a long time back.

Inserting xml nodes using Business rules
The Microsoft.RuleEngine assembly that ships with Microsoft BizTalk Server 2006 has a class named XmlHelper, which allows you to insert nodes into an XML document from an action in a business rule and set their values.

You can find a sample here.

Usage of static .NET objects in Business Rules
You can build business rules that only require stateful objects to be passed in as facts, and leave helper functions, lookups and the like as static objects.
For example, using standard "DateTime.Now" function contained in the mscorlib assembly, without passing an instance of that object into the rule as a fact.
The following key is required in the registry to use static objects in Business rules: HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\BusinessRules\3.0\StaticSupport (DWORD)

There are three valid values for this key:
0 - This is the default key, and pretty much mimics the behavior of BizTalk Server 2004 where an instance of an object is always required as an input fact, and the method is only called when the rule is evaluated or executed.
1 - An instance of the object is NOT required, and the static method is called whenever the rule is evaluated or executed
2 - An instance of the object is NOT required, but the static method will be called at rule translation time (only if the parameters are constants). This is primarily meant as a performance optimization. However, note that static members used as actions will NOT be executed at translation time, but static methods used as parameters may be.

Select 1. Restart machine after adding the registry entry.

Reference:
http://www.topxml.com/rbnews/BizTalk-Rule-Engine/re-21606_BizTalk-Server-2006-Business-Rules-and-Static-Methods.aspx

Parameter list does not appear inside the "Call Rules" shapes "Configure Policy" dialogue box with in the Orchestration

This is one problem that you weface frequently while developing BziTalk applications. When you create a Vocubularty Definition for XML element or attribute, with "Add New Definition" wizard. After selecting the Schema file, you make sure the "Document Type" text box has same namespace as that of the schema. This is not the target namespace of the schema but the namespace of schema file. You can check this namespace in Properties of the schema file.
For example: if the namespace of the Schema is "IFRC.SI.VoiceCallsToCODA.SCH" and schema type name = "GetTelephoneCostDistribution" , then you need to set the "Document Type" value to "IFRC.SI.VoiceCallsToCODA.SCH.GetTelephoneCostDistribution".If you are not doing this step correctly, parameter list won't appear in the "Call Rules", "Configure Policy" dialogue box.

Don't set context properties while in messages while working with Business Rules
BRE actually creates a new message and sends that back to the calling orchestration. Therefore, the existing one really gets overwritten, so, be aware of that when you set context properties. If you set context properties on a message, then pass that message into a business rule, those properties disappear.
An orchestration sets up the SMTP.Subject context property on the message, and then calls a rule to set some additional message fields up. Finally, I send the message out through the SMTP adapter. As expected, the message shows up in my mailbox without a subject (actually, the message GUID was entered as the subject).
If I add a Construct shape after the Call Rules shape and reset the SMTP.Subject, then when the message is sent out through the adapter, the mail shows up in my Inbox with the dynamically set subject line.
So, be careful when setting context properties for dynamic behavior if you are also using the BRE. It's probably a best practice to set context properties as late in the process flow as possible (i.e. directly before a Send shape).

Sorry I do not remember the source for this one, nonetheless, I have found a good article with a sample on Richard Soretor's blog. You will find very interesting articles on his blog for BizTalk Server.

Modifying vocabulary after it is published and used in business rule
It can be quite irritating at times to create and publish a new version of a vocabulary once the previous version is used in a business rule, particularly in development environment. I managed to find a workaround for this by manipulating some records in BizTalkRuleEngineDb tables. But I would strongly recommend that this be tried only in development environment and not in production environment.
  1. Export the existing version of the vocabulary into xml file.
  2. Create a new version of the vocabulary and add/modify the needed definitions.
  3. Export the new version of the vocabulary into xml file.
  4. Copy the modified/added definitions in new version to xml file of the old version.
  5. Go to BizTalkRuleEngineDb database of the BizTalk Server.
  6. Open table re_vocabulary and get nVocabularyID column of your vocabulary.
  7. Open table re_ruleset_to_vocabulary_links and get nReferingRuleset for nVocabularyID fetched in previous step.
  8. Delete all rows in re_ruleset_to_vocabulary_links containing nVocabularyID as your vocabulary id.
  9. Delete entry in re_vocabulary containing nVocabularyID as your vocabulary id.
  10. Import the existing version vocabulary file.
  11. Insert entries into re_ruleset_to_vocabulary_links for all rule sets fetched in step 7 with the new nVocabularyID .

Monday, April 21, 2008

Known Issues with SQL Adapter in BizTalk Server 2006

UnexpectedMessageTypeException
Problem:

Microsoft.XLANGs.Core.UnexpectedMessageTypeException: Received unexpected message type '' does not match expected type '[MESSAGE TYPE]'.
at Microsoft.XLANGs.Core.PortBinding.VerifyMessage(Envelope env, String typeName, Context cxt, OperationInfo op)
at Microsoft.BizTalk.XLANGs.BTXEngine.BTXPortBinding.VerifyMessage(Envelope env, String typeName, Context cxt, OperationInfo op)
at Microsoft.BizTalk.XLANGs.BTXEngine.BTXLogicalPortBinding.VerifyMessage(Envelope env, String typeName, Context cxt, OperationInfo op)
at Microsoft.BizTalk.XLANGs.BTXEngine.BTXPortBase.VerifyTransport(Envelope env, Int32 operationId, Context ctx)
at Microsoft.XLANGs.Core.Subscription.Receive(Segment s, Context ctx, Envelope& env, Boolean topOnly)
at Microsoft.XLANGs.Core.PortBase.GetMessageId(Subscription subscription, Segment currentSegment, Context cxt, Envelope& env, CachedObject location)
at [ORCHESTRATION NAME] (StopConditions stopOn)
at Microsoft.XLANGs.Core.SegmentScheduler.RunASegment(Segment s, StopConditions stopCond, Exception& exp)

Solution:
Make sure that the XML send/receive pipelines have been configured for the physical port.


Passing DateTime value as input parameter to stored procedure
Problem:

The adapter "SQL" raised an error message. Details "HRESULT="0x80040e07" Description="Error converting data type nvarchar to datetime "".

Solution:
Change the data type of the input parameter to string.
If you create the schema for the concerned stored procedure using Add Generated Items wizard, it will create the input parameter with data type as string. Don't change the data type to datetime.

Refer the following link for further information:
http://msdn2.microsoft.com/en-us/library/aa578440.aspx

Refer the following link for
Best Practices for the SQL Adapter