Interesting tech stuff I come across day-to-day. Mainly around Biztalk and .NET 3.0

BizTalk 2006 R2 - consume an .ASMX webservice using WCF-BasicHttp adapter

Thursday, May 31, 2007

Normally when we need to consume a .asmx web service in BizTalk 2004/2006 (NOT R2) inside an orchestration, we add a web reference, which will create all the multi-part message and web port type required to consume the orchestration. You construct the orchestration and configure the SOAP adapter in the send port to consume the web service. I suppose that's the normal route any BizTalk developer will take when you are put under a circumstance to consume an .asmx webservice using WCF-BasicHttp adapter.

But when you are going to use the WCF-BasicHttp adapter, "Add Web Reference" is not going to work, and we need to take advantage of the hidden "Consume WCF Service" wizard, which comes as part of BizTalk 2006 R2. The wizard will generate required schemas, multi-part messages, orchestration port types, and also binding files for both basicHttp and custom binding. I'll put the steps here to consume a basic .asmx webservice in BizTalk 2006 R2 with WCF-BasicHttp adapter.

The sample webservice we are going to use contains a very simple webmethod as shown below.

[WebMethod]
public string ConcatName(string firstName, string lastName)
{
return firstName + " " + lastName;
}

The below walk-through is based on the sample webservice, which comes as part of the download.

  1. Create a blank BizTalk Project
  2. Right-Click on the project and select Add->Add Generated Items->Consume WCF Service
  3. Select the option "Metadata file (WSDL and XSD)", Click "Next"
  4. Open an instance of a browser and navigate to your ".asmx?WSDL" file and save it somewhere in your harddrive (Example: c:\Service.wsdl).
  5. Click on the "Add" button (next step in the wizard after the one shown above), browse to the .WSDL file you saved in Step 4, Click "Next" (Accept defaults), Click "Import" and then Click "Finish" to complete the wizard.
  6. Once you click "Finish" the following files will be added to your project (File name will depend on the name of the .WSDL file you selected)
    Service.BindingInfo.xml
    Service.odx
    Service_Custom.BindingInfo.xml
    Service.tempuri_org.xsd
  7. Open the Service.odx file, inside the orchestration view create 2 messages as shown below
    WSRequest - Multi-part Message Type - ConsumeWebService.ConcatNameSoapIn
    WSResponse - Multi-part Message Type - ConsumeWebService.ConcatNameSoapOut
  8. Right-Click on the orchestration "Port Surface", Click "Next", In the port properties page Click "Next", In the "Select a Port Type" page select "Use an existing Port Type" and select "ConsumeWebService.ServiceSoap", In port binding page select "I'll be sending a request and receiving a response." for port direction and "Specify later" for port binding. Click "Next" and then "Finish".
  9. Construct an orchestration as shown in the below figure
    Receive_1 -> Activate=true, Message= WSRequest
    Send_1 -> Message = WSRequest
    Receive_2 -> Message = WSResponse
    Send_2 -> Message = WSResponse
  10. I created a FILE Receive and FILE Send (Specify Now) port binding for port_2 and port_3
  11. Assign a key file to the project and set the "Application Name" to "ConsumeWebService". Build and Deploy the project.
    Open BizTalk Administration Console, Right-Click on the application and select "Import Binding". Browse to the auto generated binding file "Service.BindingInfo.xml" and select it.
  12. Bind your Orchestration to the correct ports and host. For the .asmx webservice logical port, select the auto generated "WcfSendPort_Service_ServiceSoap". (Start the application)
  13. Create a sample message by right-clicking on "Service_tempuri_org.xsd" file and clicking "Generate Instance". Drop the message in the folder you configured for port_2 in the orchestration, you should see the output result in folder you configured for port_3 in your orchestration.

Download the sample here

Nandri!

Saravana

Labels: ,




BizTalk 2006, WCF (basicHttpBinding), Adding Web Reference will go in end less loop.

Tuesday, May 29, 2007

When I tried to add a "Web Reference" to a WCF service (basicHttpBinding), I encountered following behaviors

1. Either it will throw an exception showing "Failed to add Web Reference" and no more clue anywhere, OR

2. Message saying "This page is accessing information that is not under its control. This poses a security risk. Do you want to continue?" it wont wait for your reply, it will go on endless loop until you click "NO" (then you need to close some 50 or windows), OR

3. It will throw an exception message saying, "Could not generate BizTalk files. Index was out of range. Must be non-negative and less than the size of the collection. Parameter name: index"

I attached following screen shots for reference:

(OR)

Tweaking the WCF config file with different setting didn't give me any luck. At last I figured out the issue is due to the namespace declaration for the WCF service. Just removing the namespace declaration and defaulting it to use "http://tempuri.org/" (which is not the best practice) solved the problem.

Before:

[ServiceContract(Name = "BackOfficeServices", Namespace = http://companyurl/Service/BackOffice)]

After:

[ServiceContract(Name = "BackOfficeServices"]

I can't really justify the reason, but I guess it will help someone.

Nandri!

Saravana

Labels: ,




Pipeline Component, XmlSerialization and Performance

I'm basically replying to Yossi's post here. I tried to leave it as a comment in his post but for some reasons my comments are not getting posted in his blog.

Myself and Yossi used to work together in a big public sector Healthcare BizTalk project for nearly 1.5 years.

First off all I need to thank Yossi for his complement about my white paper "Understanding Design-Time Properties for Custom Pipeline Components in BizTalk Server". Yossi mentioned in his post about the potential performance problem in using XmlSerializer inside pipeline component. Until now I thought his point is valid, but after reading the very first chapter from Professional BizTalk Server 2006 by (DJ, KS and EF) , where Darren explains about Serialization and performance hit, its clear there is NO PERFORMANCE HIT by using XmlSerialization in a BizTalk solution.

I thought the explanation will be helpful for readers to make the decision. The following extract is from the book (Page 11):

"When you first use the XmlSerializer in your application against a given type, a dynamic class is created and compiled on the fly to represent the serialized class. This has an obvious performance over head, but it will be cached for susbsequent requests

This cache is maintained per AppDomain, which is fine for applications like BizTalk, as there is by default only one AppDomain per BizTalk host.
"
.

So, eventually by using XmlSerialization inside the pipeline component, you'll hit the penalty only once during the lifetime of the component. That's until some one restarts the host.

Nandri!,
Saravana

Labels:




Create SQL Receive Locations Programmatically.

Friday, May 25, 2007

One of our recent projects involved creating an orchestration, which was bound to a physical one way receive port polling data from SQL server.  There will be multiple SQL receive locations for the same receive port. The receive locations will have different polling conditions based on the customer. Our requirement was to create one receive location per customer. So, we'll be adding more SQL receive locations as the customer base increases.  For that reason I created this function (part of a bigger client application) which create SQL receive location programmatically, which uses BizTalk Catalogue explorer object (no WMI). Hope this will be helpful to some one, because there is minor things to take care of.
 
You can download the .CS file from here.
 
The below figure shows a SQL receive location created with help of the above function.

How To Execute it:

Here is the sample code, which is used to run the function.

string server "SK_WORKSTATION";
string 
database "ORDER_POLLING";
string 
address "SQL://" + server + "/" + database + "/" + Guid.NewGuid().ToString();

CreateAndConfigureSQLReceiveLocation(
  
"Receive.SQL.Autogenerated.SK1"
"Receive.Sch.Orders.Internal.SQL.1Way.AllPollingService.ActivationMessages"
, address
"False"
"Minutes"
"10"
"DocumentRootElement"
"http://www.digitaldeposit.net/samples/SQL/schema"
"exec [GetSQLActivationMessage] @AccountNumber='007'"
"Provider=SQLOLEDB.1;Integrated Security=SSPI;Persist Security Info=False;User ID=sa;Initial Catalog=ORDER_POLLING;Data Source=SK_WORKSTATION"
"Data Source=(local);Initial Catalog=BiztalkMgmtDb;Integrated Security=true;Trusted_Connection=True"
);

NOTE: The function assumes you already got a "Receive Port" (which you pass as second argument to the function), but its not hard to create it inside the function.

Nandri!
Saravana

Labels:




Output custom formatted message from Orchestration.

Thursday, May 24, 2007

Have you ever wanted to create a custom formatted message. For example if you define a message of type System.String inside your orchestration and output it via an adapter the result will be as shown below

<?xml version="1.0" ?>
<string>Hello there</string>

this is because of the default serialization behavior of .NET base types within BizTalk. If in case you wanted to output the message as a simple string, in our case "Hello there" without any xml tags and processing instruction, you need to create your own .NET type with custom serialization and use it instead of System.String . In this post I'll explain how you can achieve this seamlessly with a similar sample by creating your own class with your own custom formatting serialization technique to create a sample email text message from an XML message. The sample solution contains full working sample and the code is self explanatory.

Orchestration:

We got a simple orchestration which takes an input XML message and produces the output in text format.

 

MSG_TEXT_EMAIL  is a message created from a custom .NET class called FormattedTextEmail.

The message assignment shape got the following one line code, which assigns a .NET type to the Orchestration XLang message MSG_TEXT_EMAIL.

MSG_TEXT_EMAIL = new FormattedEmail.FormattedTextEmail(MSG_XML_EMAIL.From, MSG_XML_EMAIL.To,MSG_XML_EMAIL.Subject, MSG_XML_EMAIL.Body);

As you can see there is no MAP's involved to do the transformation.

Input:

<ns0:EmailMessage xmlns:ns0="http://www.digitaldeposit.net/sample/schema">
  
<From>sk@email.com</From>
  
<To>gow@biz.com</To>
  
<Subject>Hey are you alrigh</Subject>
  
<Body>I found this sample really cool</Body>
</ns0:EmailMessage>

Output:

From : sk@email.com
To : gow@biz.com
Subject : Hey are you alrigh
Body : I found this sample really cool

Download Sample: CustomEmailFormat

Executing the sample:

1. Extract the solution to C:\BTSSamples

2. Open the visual studio solution, build and deploy it

3. Open BizTalk administration console, Open application "CustomEmailFormat",  Bind orchestration and Start the application

4. Drop the sample message inside the folder "C:\BTSSamples\CustomEmailFormat\FileDrop\In"

5. You should see the text output inside the folder "C:\BTSSamples\CustomEmailFormat\FileDrop\Out"

Related Reading:

http://msdn2.microsoft.com/en-us/library/bb418739.aspx

Nandri!

Saravana

Labels:




Can't see Debug statements in DebugView?

First of all to see debug statements inside DebugView you need to compile your assemblies in "Debug" mode. For optimization reasons if you compile your assemblies in "Release" mode all the System.Diagnostics.Debug.WriteLine statements will be ignored by the compiler and you won't see any output in the DebugView.

When it comes to BizTalk project sometimes even though the tool bar will say the build is "Debug" as shown in the figure

 

When you actually look into the properties of the BizTalk project it may be configured for "Deployment", which is equivalent to the "Release" build and it won't emit any debug symbols.

So, in this case you need to set the configuration to "Development", which is equivalent to "Debug" build.

Nandri!

Saravana

Labels:




ASP .NET Treeview Control, weird problem when you Programmatically expand the nodes.

Wednesday, May 23, 2007

One of my supporting project required building a web site using TreeView control to show hierarchical data. I used "NavigateUrl" property while data binding, so that every node in the tree view will have proper link something like http://abc.com/bts/default.aspx instead of Javascript:__doPostBack. Even though all of my pages are going to have the treeview control on the left, I'll lose the expanded status because the control will be navigated to a brand new page and whole page will be loaded from scratch. So, my requirement is to set the treeview expanded status programmatically.

What do you think of this line of code?

TreeView1.FindNode("BizTalk Server|Planning and Architecture|Patterns").Expand();

("|" is the path separator)

Perfectly alright right? But, the output will only expand the node till "Planning and Architecture", I tried different things like putting the code in different event handlers like page_prerender, treeview_databound, navigating to the node via Nodes and ChildNodes property etc, etc. Whatsoever I couldn't make it work. Google search revealed similar problems but no solution. At last I managed to find the solution from the book "Professional ASP .NET 2.0" (Page: 525) the code should be written this way:

TreeView1.FindNode("BizTalk Server").Expand();

TreeView1.FindNode("BizTalk Server|Planning and Architecture").Expand();

TreeView1.FindNode("BizTalk Server|Planning and Architecture|Patterns").Expand();

Extract from the book:

"Note that you had to expand each of the nodes individually until you got to the "Planning and Architecture" node, If you simply used TreeView1.FindNode("BizTalk Server|Planning and Architecture|Patterns").Expand(); in the treeview1_DataBound method, the "Pattern" node would indeed be expanded, but the parent nodes above it ("Planning and Architecture" and "BizTalk Server") would not have been expanded and you wouldn't see the expanded "Patterns" node when invoking the page. (Try it; it's interesting.)"

What a weird programming style they have adapted for this? Is it not just common sense the control should expand all its parent node to show itself? The last sentence "Try it; it's interesting" is actually present in the book. I was almost about to buy a commercial product, just thinking there is a huge bug in the ASP .NET 2.0 Treeview control.

Nandri!

Saravana

Labels:




BizTalk, MSDTC, SSO and Cluster

Monday, May 21, 2007

Last night (BTW it was a Sunday) around 8PM I received a call from my ex-boss and good friend Mike Prager who is working as a Senior architect in one of the major retail project in UK, saying "Hey! SK, we had a power failure this afternoon in our data center and after the servers came back all our receive locations are disabled and send ports are not started. When I try to access them via the admin console, I'm receiving the error

"Cannot retrieve list of objects due to a WMI provider failure"

have you experienced this before."

Well, I've seen this error in the past, but there are tons of things which can cause this error in BizTalk, we tried few things like checking whether all the SSO services are health on all the machines, MSDTC is running and configured correctly on each box, correct SSO master secret server is configured on the BizTalk group, etc, etc.

At last, I left Mike with the option to try DtcPing, since I'm not physically there. I couldn't assist much.

This morning I received a call from enthusiastic Mike, saying "Hey! I solved the problem, the error is due to the race condition (dependency) between the DTC and SSO service in the SQL cluster. When the SSO service starts before the DTC, there is an issue. You get the WMI error. But if the DTC starts before SSO, everything is well and good."

The reason I'm blogging it is I never experienced this before and it's one of those strange things which we'll never think about. I hope this will solve someone hours of troubleshooting time.

Thanks Mike, for sharing this information.

Nandri!

Saravana

Labels:




Create safe File Name from string using .NET 2.0

Saturday, May 19, 2007

Recently for one of my weekend project I wanted to create a safe file name from a string. In the past people used to do lot of regular expressions and conditional testing to meet this requirement. Still the filename won't be safe across multiple environments (Windows 2000/XP/2003 etc). But with .NET 2.0 using couple of inbuild functions (Path.GetInvalidFileNameChars and Path.GetInvalidPathChars) you can create safe filenames. Hope this piece of code will be useful to someone.

private string CreateValidFileName(string title, string extension)
{
string validFileName = title.Trim();

foreach (char invalChar in Path.GetInvalidFileNameChars())
{
validFileName = validFileName.Replace(invalChar.ToString(), "");
}
foreach (char invalChar in Path.GetInvalidPathChars())
{
validFileName = validFileName.Replace(invalChar.ToString(), "");
}

if (validFileName.Length > 160) //safe value threshold is 260
validFileName = validFileName.Remove(156) + "..."

return validFileName + "." + extension;
}

Nandri!

Saravana

Labels:




BizTalk Map - Suppress Element if Attribute is not required.

Friday, May 18, 2007

Scenario: The following question is taken from BizTalk.General NewsGroup (altered slightly for readability purpose)

"I'm mapping an element in the source schema to an attribute in the destination schema.  The element  does not exist in the source schema, but when I run the map it creates the element in the destination schema that houses the attribute I am mapping to.  The attribute does not show up in the result of the map, just the empty element. I need to have it not create the empty element if it is not going to put a value in the attribute."

Here is the solution:

Thanks goes to my collegue Matthew Johnstone and same technique was explained by Kiran Pabba in the newsgroup. I know for sure Matthew worked out this sample himself :-)

Labels:




BizTalk - Strange Exception Messages and Corresponding Fixes.

Thursday, May 17, 2007

During our BizTalk development we come across some really strange error message, which normally doesn't reflect the real cause. I always wanted to consolidate everything in one place. After seeing couple of errors that's being raised in the news groups, I thought this is the right time to materialize it. If you have come across any strange errors and willing to share please let me know via my contact page.

========================================================

Exception: 'System.Xml.XmlDocument' does not contain a definition for 'Status'

========================================================

Cause:

System.Diagnostics.Debug.WriteLine(PO_SOURCE.Status.ToString());

Resolution:

status = PO_SOURCE.Status;
System.Diagnostics.Debug.WriteLine(status.ToString());

where "status" is a variable of type System.String.

Credit: Tim

Remark: When you try to do the conversion directly on the context property, the above exception is raised. You can easily fix it by first assigning the context property to a local variable and then doing the conversion.

Date Logged: 17th May 2007 (BizTalk 2006)

========================================================

ERROR: The BAM deployment failed.
A connection cannot be made. Ensure that the server is running.
No connection could be made because the target machine actively refused it

========================================================

Credit: Saravana Kumar

Remark:

If you receive the following error when you try to deploy BAM activities using bm.exe tool

The error information doesn't reflect on the actual cause. Make sure, "SQL Server Analysis Services" is started.

Date Logged: 26th April 2007 (BizTalk 2006)

========================================================

A connection was successfully established with the server, but then an error occurred during the login process. (provider: Named Pipes Provider, error: 0 - No process is on the other end of the pipe.)

========================================================

Remark:

Make sure you Visual Studio project is pointing to the correct management server (Project Properties -> Deployment -> Server (BizTalk Group).

Date Logged: 29th May 2007 (BizTalk 2004/2006).

Nandri!

Saravana

Labels:




Orchestration - Handle SOAP Exception and deal with Suspended (resumable) messages

Wednesday, May 16, 2007

The main reason for this blog post is due to this newsgroup post

Download Sample from here.

Step #1: Catching SOAP Exception:

Whenever you call a Web service it's a good practice to handle the SOAP exception specifically rather than just leaving the orchestration to throw an un-handled exception which will result in orchestration service instance and all the referenced message instances being suspended. As shown in the following Orchestration diagram, handling a  SOAP exception is straight forward. Place your "Send" shape inside a "Scope" and add an Exception Handler with "Exception Object Type" configured to System.Web.Services.Protocols.SoapException (You need to add reference to "System.Web.Services"). The "Message Assignment" shape  inside the catch block got this simple statement

SOAP_EXCEPTION_MESSAGE = soapException.Detail.InnerXml;

Where SOAP_EXCEPTION_MESSAGE is an Orchestration message of type System.String and soapException is the "Exception object name" we assigned for the exception handler. So, with the following setup, whenever there is an exception a message similar to the one shown below will be generated and send across the wire with configured adapter (FILE, SMTP etc).

<string><ns0:NACK Type="NACK" xmlns:ns0="http://schema.microsoft.com/BizTalk/2003/NACKMessage.xsd"><NAckID>{2DA185D7-40E7-4279-9F6E-ADCEB6EF599B}</NAckID><ErrorCode>0xc0c01f07</ErrorCode><ErrorCategory>0</ErrorCategory><ErrorDescription>SoapException: System.Web.Services.Protocols.SoapException: Purposely raised this exception for testing at CustomerProcessing.Get500InternalSoapException(String yourName) </ErrorDescription></ns0:NACK></string>

Step #2: suspended(resumable) messages:

Even though you handled the SOAP exception using an exception handler in STEP #1, it's only going to complete the orchestration gracefully but it's going to leave the original request message you posted to the web services in a suspended(resumable) state. Bear in mind the SOAP exception will be raised inside the orchestration only after the send port has exhausted all the retries.  During this period the messaging instance and orchestration service instance will be in the dehydrated state as shown below.

After all the retries, the SOAP exception will be raised inside the orchestration and corresponding SOAP request message will be suspended with resumable state as shown below. This will help the administrator to either resume or terminate the message later.

 

But at some scenario we don't wont to leave the suspended (resumable) messages in the messagebox, instead move them to a different location (either to file system location or a remote server via HTTP etc, etc). Before BizTalk 2006 the only way to archive this behavior is by writing some WMI scripts, which is OK but doesn't really fit with the message flow infrastructure. But with BizTalk 2006 we can take advantage of "Failed Message routing" capability and make this task seamless.

All you have to do is, on your SOAP send port check the check box "Enable routing for failed messages" (as shown in the following figure) and also you can set optionally the "Retry Count" value to "0" if you want to raise the SOAP exception straight away.

Then configure a "Send Port"  (or an orchestration, if you want to do more business logic with the suspended messages) with following filter condition

ErrorReport.ErrorType == "FailedMessage"

ErrorReport.OutboundTransportLocation ==  http://localhost:47653/SOAPExceptionHandler.WebService/CustomerProcessing.asmx

The above filter condition will make sure you are dealing only with SOAP exception raised due to messages posted to that particular web service (CustomerProcessing.asmx). There are quite a bit of promoted properties that comes along with "ErrorReport" you can take advantage of to cater your situation as listed below.

  • Description
  • ErrorType
  • FailureCategory
  • FailureCode
  • InboundTransportLocation
  • MessageType
  • OutboundTransportLocation
  • ReceivePortName
  • RoutingFailureReportID
  • SendPortName

Related Reading:

http://blogs.conchango.com/matthall/archive/2005/07/28/1894.aspx

http://objectsharp.com/cs/blogs/matt/archive/2006/11/01/4110.aspx

Nandri!

Saravana 

Labels:




Data Tracking and Activity (DTA) Architecture

Tuesday, May 15, 2007

The following picture will tell you all about the DTA architecture in BizTalk server

I came across this picture in MSDN (http://msdn2.microsoft.com/en-us/library/aa559554.aspx) , very simple and elegant explanation of DTA architecture. I thought it's worth keeping it for reference. Visit the above link for details about each step.

Nandri!

Saravana Kumar

Labels:




Are you going to create new schema (.xsd file) from existing one? Here is the quick tip for BizTalk beginners.

Step #1: Within Visual Studio copy the schema (.xsd file) and Paste it. Rename the file to appropriate name.

Step #2: Click on the <Schema> node and change the "Target Namespace" property in the properties window as shown below. (NOTE: This step is required only if you want to change the target namespace, else you can ignore and go to Step #3)

Step #3: Click on the Root node and change "Node Name" property in the properties window as shown below. Changing the "Node Name" property will automatically change "RootNode TypeName". Make sure they are the same.

Step #4: Click on the .xsd file in the solution explorer and click F4 (or make sure the properties window is visible, when you select the .xsd file). Set Appropriate name (usually the root node of your schema) to the "Type Name" as shown in the below figure. This is crucial, since all the schemas contained inside the project will be compiled into typed objects, derived from corresponding BizTalk artifact classes. (Example: If you look at the compiled "dll" of this sample project,  using Reflector, the class definition will be public sealed class PO_Target : SchemaBase).

That's all, your new schema is ready to be used now. Apart from all the properties windows we have seen there is one more property window for the schemas (can be seen by right clicking on the .xsd file and selecting "Properties" from the context menu) as shown in the below figure

You configure things like "Output Instance filename" which will be used when you generate a sample file from schema, "Input Instance file" which will be used when you want to validate a message against a schema etc.

Nandri!

Saravana 

Labels:




Now, I'm a "MCPD - Enterprise Application Developer for .NET 2.0"

I recently obtained my MCPD (Enterprise Applications Developer) credentials. I'll admit probably this is one thing which stayed in my TODO list for more than a year. Microsoft re-organised their certification program after the release of Visual Studio 2005, .NET 2.0 and SQL Server 2005. Not everyone is aware of this new certification model and its requires some explanation here.

According to new certification model, the two main categories of certification for people on Software development falls under either

Microsoft Certified Technology Specialist (MCTS), and eventually upgrading to Microsoft Certified Professional Developer (MCPD)

Microsoft Certified Technology Specialist (MCTS)

MCTS are targeted to specific technology so that you can demonstrate your expertise in that area. You can get your MCTS credentials in one of the following areas.

MCTS: .NET Framework 2.0 Web Applications
MCTS: .NET Framework 2.0 Windows Applications
MCTS: .NET Framework 2.0 Distributed Applications

In addition to the above credentials, which applies to all the .NET 2.0 developers based on their choosen field (Windows, Web and Distributed), developers can also obtain MCTS credential for some of the server products example:

MCTS: SQL Server 2005

MCTS: BizTalk Server 2006

Microsoft Certified Professional Developer: Enterprise Applications Developer (MCPD):

MCPD demonstrates comprehensive skills that are required to perform the job successfully, and must remain current in best practices and technologies. It also demonstrates that you have the comprehensive skills required to build n-tier solutions targeting both Web and rich-client user experiences. In order to obtain MCPD: Enterprise Applications Developer candidates must first meet the requirements for the following three Microsoft Certified Technology Specialist (MCTS) credentials for the Microsoft .NET Framework 2.0.

MCTS: .NET Framework 2.0 Web Applications
MCTS: .NET Framework 2.0 Windows Applications
MCTS: .NET Framework 2.0 Distributed Applications

In addition the candiate also required to pass a design paper "PRO: Designing and Developing Enterprise Applications by Using the Microsoft .NET Framework"

--Saravana

Labels:




Detect CLR version under which your BizTalk service is running.

Saturday, May 12, 2007

It's becoming more and more eminent to understand under which CLR version (1.0, 1.1 or 2.0) the BizTalk runtime, In-Process host is running. I've explained in my previous post the various factors that influence loading appropriate CLR versions and also how you can make use of the config file to force a specific version of CLR is always loaded.

There is one more query raised, what happens if you install .NET Framework 3.0 on your BizTalk server (both 2004 and 2006)? The effect of installing .NET 3.0 doesn't introduce that much behavior difference when compared to installing .NET 2.0 on a BizTalk 2004 machine (built using .NET 1.1 with CLR 1.0). Because .NET 3.0 is still based on .NET 2.0 and shares the same compilers and Common Language Runtime (CLR 2.0). See the following posts from Somasegar and Jason Zanders (comments are more interesting on the both the posts)to see the effect of .NET 3.0.

With all this confusions around different versions of .NET and different versions of BizTalk and different Service Packs, there will certainly be a situation where developers and administrators need to figure out the version of CLR under which the BizTalk Runtime is running. This is where Process Explorer comes to our rescue.

Process explorer's top window shows a list of currently active processes, and the bottom windows shows either the handles opened by the selected  process or it shows the DLL's and memory mapped files that the selected process has loaded. You need to set the appropriate mode from the menu item "View-> Lower Pane View". In our case we need to figure out the version of Common Language Runtime core dll (mscorwks.dll) loaded into the BizTalk runtime process (BtsNtSvc.exe). So, we'll set the "Lower Pane View" to DLL's (or Ctrl + D).

Also, make sure the following columns are visible Description, Image Path, and Version. To do so, click on "View" menu and select "Select Columns" and in the "Process Image" tab select appropriate columns.

 The following screen shot is taken from a machine running BizTalk 2006. You can see clearly from the bottom pane the version of CLR running is 2.0 and physical dll is loaded from the location "C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\mscorwks.dll". BTW, .NET 3.0 is installed in this particular machine, which also proves .NET 3.0 still uses CLR 2.0. In BizTalk 2006 box its quite straight forward it's all .NET 2.0. Things will become more interesting in BizTalk 2004 scenario.

Nandri!

Saravana

Labels:




BizTalk 2004 and .NET 2.0

Tuesday, May 08, 2007

Under which version of .NET Framework my code is going to run?
I came across this interesting question in BizTalk newsgroup, "I am just wondering though how my local computer knows which CLR to load for the BizTalk Server 2004 Orchestrations when there is no entry in the BTSNTSvc.exe.config file to specifically point to the .NET 1.1 Framework when .NET 1.1 and 2.0 Frameworks are loaded to my computer. ".

Here is my explanation:

Applications that do not carry a configuration file or at least the supportedRuntime element in their configuration files (unconfigured applications) execute with the version of the framework that was used to build the application, provided that version of the Framework is installed on the local system. The version of the Framework with which the application was built is contained in the header (MANIFEST) of the application (assembly). Executing the following line of code against  Microsoft.XLANGs.BizTalk.Engine.dll in a BizTalk 2004 environment will output the result as v1.1.4322. The same piece of code in BizTalk 2006 environment will output v2.0.50727.

Console.WriteLine(System.Reflection.Assembly.LoadFile(@"C:\Program Files\ Microsoft BizTalk Server 2006\ Microsoft.XLANGs.BizTalk.Engine.dll").ImageRuntimeVersion);

There are two important things which drives what version of framework will be used at runtime :
1. When the expected version of the Framework is not available, the CLR uses a later version of the Framework in its place. In other words, an unconfigured assembly built with Framework 1.1 executes with 1.1 on a system that has both 1.1 and 2.0 installed. That same assembly executes with the 2.0 Framework on a system with only the 2.0 Framework installed.
2. When it comes to interop scenarios the default behavior of CLR is to load the latest framework. This is because unless the managed assemblies, unmanaged assemblies lack the information in their header that describes the version of the framework (as we seen with the code snippet earlier) the code in question was build with; this leaves the CLR with no choice other than to load the latest available version of the framework.

Some of the assemblies used by BizTalk (both 2004 and 2006) runtime components falls under the second category (interop assemblies), which leaves CLR to load the latest available framework.  If you need to override these default behavior, you can set the supportedRuntime/requiredRunTime in the .config file (BtsNtSvc.exe.config for In-Process host and corresponding IIS config file based on version 5.0 or 6.0 either dllhost.exe.config or w3wp.exe.config for isolated host)  for the process as shown below, which forces to use .NET framework 1.1.

<configuration>

<startup>
<supportedRuntime version="v1.1.4322" />
</startup>

</configuration>

Ultimately, this means all managed components called by a particular application (BizTalk 2004) runs on the same version of the Framework.

New Assembly, Old .NET

It's advisable to build your custom assemblies against the same version of .NET that you will be running them against. i.e .NET 1.1 for BizTalk 2004 and .NET 2.0 for BizTalk 2006. That way you'll have correct references and avoid surprises from behavior difference between builds.

Custom components that are written to use the .NET Framework 2.0 will not work in BizTalk Server 2004. These components include adaptors, pipeline components, functoids, and user code that may be referenced from orchestration or rules policies. This is because new assemblies cannot be opened on older CLR, just because they don't understand them, and the runtime will throw BadImageFormatException.

References:

http://support.microsoft.com/kb/841405

http://blogs.msdn.com/suzcook/archive/2003/06/20/57191.aspx

http://blogs.msdn.com/suzcook/archive/2005/01/26/new-assembly-old-net-and-vice-versa.aspx

http://msdn2.microsoft.com/en-us/library/ms994410.aspx

Nandri!

Saravana

Labels: