Andy's profileAndy's WarholeBlogLists Tools Help

Blog


    Flat File Disassembler

    While I was developing a flat file disassembler flat file component to handle multiple flat file formats, I was completely brought off track by something I found on Gilles’ Weblog: ‘In a pipeline component, some streams are not seekable: Improvements to the Archiver’.

    The confusing text was:

    I should have used BodyPart.Data which in the case of custom pipeline components makes a copy of the inbound message:
    // Get a *copy* of the original input stream
    originalStrm = bodyPart.Data;

    However, when testing my pipeline component the messages seemed to disappear. The message types were determined correctly, the document specification name was determined correctly, but my message did not appear in the output location. After a lot of frustration and time, it finally hit me; maybe the resulting stream was empty. I thought, because of the comment mentioned above, that I was dealing with a copy of the stream, but according to the MSDN:

    In custom pipeline components, Data clones an inbound data stream, whereas GetOriginalDataStream returns the original inbound stream.

    So, instead of dealing with a copy I was dealing with a clone of the stream. Adding the following lines solved the problem, pffff:

    // Preserve the stream position
    long position = dataStream.Position;

    // Restore the stream position
    dataStream.Position = position;

    Failed to access IIS metabase

    Technorati Tags: ,

    Recently I was working with WCF and ran into the following error:

    Server Error in ‘/WCFService’ Application

    Failed to access IIS metabase.

    The solution was simple. Executing the below statement solved the problem.

    aspnet_regiis /i

    The error indicates that the .NET Framework is not registered with IIS. The .NET Framework detects which versions of IIS exist when the .NET Framework is installed, and it automatically registers itself with IIS. If IIS does not exist when .NET Framework is installed, the .NET Framework is not registered with IIS.

    The command with -i switch is used for installing ASP.NET and upgrading all application pools to ASP.NET version which came with the ASP.NET IIS Registration Tool. It will ignore the previous version of application pool.

    See Microsoft: ASP.NET IIS Registration Tool (aspnet_regiis.exe).

    The node to be inserted is from a different document context

     
    Often, when I first try to copy a node from one XML document to another I get the following error:
    The node to be inserted is from a different document context.
    This time it was because I used InsertAfter() incorrectly.
    svcNode.InsertAfter(statsNode, svcNode.SelectSingleNode("Type"));

    When copying a node from one document to another you have to use ImportNode() and then add that node to the document.
    svcNode.InsertAfter(xmlDocInst.ImportNode(statsNode, true), svcNode.SelectSingleNode("Type"));
     
    I have to keep remembering this.

    BizTalk mapping behaviours

    When using the multiplication functoid in the BizTalk mapper I ran into some strange behaviour. In the source schema I had two elements: Price, defined as string, and NumberOfTransactions, also defined as string. I used the multiplication functoid the determine the TotalSalesAmount, again defined as string with restriction ^-?(\d{0,16})(\.\d{1,4})?$, in the destination schema.

    The result surprised me; the price, 0.0340, multiplied by the transctions, 6, resulted in a total amount of 0.20400000000000002. Obviously, the result was not the result I wanted to see.

    So, I tried using a custom scriptoid. The scriptoid contained the following functoin:

    public Double ReturnTotalAmount(string p_noTxn, string p_prcRet)
    {
        // Set to English-United Kingdom meaning period as a decimal
        // indicator and comma and thousand grouping delimiter
        IFormatProvider culture =
                 new System.Globalization.CultureInfo("en-GB", true);
        System.Globalization.NumberStyles styles =
                 System.Globalization.NumberStyles.AllowExponent |
                 System.Globalization.NumberStyles.Number;
        long numTxn = Convert.ToInt64(p_noTxn);
        Double retailPrice = Double.Parse(p_prcRet, styles, culture);
        Double totalAmount =  numTxn * retailPrice;

        return totalAmount;
    }

    The result again did not meet my expectations. The total amount ended up being 0.20400000000000002. After being puzzled for a couple of minutes I found the answer. The above code needed just a little adjustment. The final code is:

    public string ReturnTotalAmount(string p_noTxn, string p_prcRet)
    {
        // Set to English-United Kingdom meaning period as a decimal
        // indicator and comma and thousand grouping delimiter
        IFormatProvider culture =
                 new System.Globalization.CultureInfo("en-GB", true);
        System.Globalization.NumberStyles styles =
                 System.Globalization.NumberStyles.AllowExponent |
                 System.Globalization.NumberStyles.Number;
        long numTxn = Convert.ToInt64(p_noTxn);
        Double retailPrice = Double.Parse(p_prcRet, styles, culture);
        Double totalAmount =  numTxn * retailPrice;

        return totalAmount.ToString(culture);
    }

    I simply had to explicitly convert the result back into the right datatype, i.e. string, using the defined culture. Another valuable leason learned.

    Macros in Send File Adapter

    I always seem to forget the most common macros when using the Send File Adapter in BizTalk, so this is a reminder.

    %datetime% Coordinated Universal Time (UTC) date time in the format YYYY-MM-DDThhmmss.
    %datetime_bts2000% UTC date time in the format YYYYMMDDhhmmsss, where ss means seconds and the last s means hunderds milliseconds.
    %datetime.tz% Local date time plus time zone from GMT in the format YYYY-MM-DDThhmmssTZD.
    %DestinationParty% Name of the destination party. The value comes from message the context property BTS.DestinationParty.
    %DestinationPartyID% Identifier of the destination party (GUID). The value comes from the message context property BTS.DestinationPartyID.
    %DestinationPartyQualifier% Qualifier of the destination party. The value comes from the message context property BTS.DestinationPartyQualifier.
    %MessageID% Globally unique identifier (GUID) of the message in BizTalk Server. The value comes directly from the message context property BTS.MessageID.
    %SourceFileName% Name of the file from where the File adapter read the message. The file name includes extension and excludes the file path. If the context property does not have a value, for example, if message was received on an adapter other than File adapter, then the macro will not be substituted and will remain in the file name as is.
    %SourceParty% Name of the source party from which the File adapter received the message.
    %SourcePartyID% Identifier of the source party (GUID). The value comes from the message context property BTS.SourcePartyID.
    %SourcePartyQualifier% Qualifier of the source party from which the File adapter received the message.
    %time% UTC time in the format hhmmss.
    %time.tz% Local time plus time zone from GMT in the format hhmmssTZD.

    Business Rule Engine tips

    Lately I was making a Proof of Concept including the BRE. After making a vocabulary and some rules I tested the policy. The rules were successfully fired. I then built an orchestration implementing a Call Rules shape. After deploying the orchestration I tested the application. However, the rules did not fire. A couple of hours later I found the ‘problem’.

    So to not forget in the future: Put the Call Rules shape within an Atomic Transaction.

    Pipeline Component:invalid pipeline component assembly

    Ever having trouble adding a custom pipeline component to the BizTalk pipeline Components toolbox?
    Sometimes when trying to add a component to the toolbox you run into to following Pipeline Component Error:

    "You have selected an invalid pipeline component assembly. Please check security settings for the assembly if you are loading it from an UNC path."

    Some hints to resolve this error:

    1. Check that the class is marked as public.
    2. Check the presence of the class attributes.
      [ComponentCategory(CategoryTypes.CATID_PipelineComponent)]
      [System.Runtime.InteropServices.Guid("<new guid>")]
      [ComponentCategory(CategoryTypes.CATID_Decoder)]
      public class <<class>> : Microsoft.BizTalk.Component.Interop.IComponent, IBaseComponent, IPersistPropertyBag, IComponentUI
      {
      ...
      }

    Most of the times the problem occurs when building the component manually. A useful tool is the pipeline component wizard.

    Assigning a Guid to a pipeline component

     
    Lately I have been developing multiple pipeline components. One of the things you have to do when developing such a component is assign it a GUID.
    A quick shortcut is to have this functionality of creating a new GUID available in Visual Studio 2005.
     
    Here is how to achieve that:
     
    In Visual Studio 2005, go to Tools and select External Tools...
    The following Dialog opens
     VS2005 - Open File uuidgen

    Set the fields according to the following picture; the Command field is C:\Program Files\Microsoft Visual Studio 8\Common7\Tools\uuidgen.exe.
     VS2005 - External Tools

    When you know open the Tools menu, a New Guid item is created. When you select and click this item a guid is created in the output window of Visual Studio.
    Very neat.

    Debugging Pipeline Components

     
    There are 2 ways to debug pipeline components; the Attach method and the Tool method

    Attach to process
     
    Build the solution in debug mode and deploy the pipeline component from bin\debug\.
    Make sure the output of the solution (component assembly) is saved to <BizTalk root install>\Pipeline Components.
    This can either be done by changing the output path of the projects build properties or by executing a post-build event.
    The script should look like:
    IF $(ConfigurationName) EQU Release GOTO done
    xcopy "$(ProjectDir)$(Outdir)$(TargetFileName)" "C:\Program Files\Microsoft BizTalk Server 2006\Pipeline Components" /R /Y /F
    IF %ERRORLEVEL% EQU 0 GOTO done
    net stop "BizTalk Service BizTalk Group : BizTalkServerApplication"
    iisreset
    xcopy "$(ProjectDir)$(Outdir)$(TargetFileName)" "C:\Program Files\Microsoft BizTalk Server 2006\Pipeline Components" /R /Y /F
    net start "BizTalk Service BizTalk Group : BizTalkServerApplication"
    :done
    Build and deploy the pipeline.
     
    NB:
    In order to avoid an error saying the output dll is being used by another process;
    - Do not put the pipeline component project and the custom pipeline project in one solution, since the pipeline designer will lock the pipeline component.
    - Stop the BizTalk service (host instance) in order to be able to copy the assembly to the mentioned directory.
     
    Attach a .NET debugger to BTSNTSVC.EXE in the pipeline component project.
    In an earlier post I decribed how to attach to the right service when running multiple host instances.
    If you decide to use the SOAP adapter, you have to attach the debugger to the process of the isolated host; W3WP.EXE.
    Remember that the SOAP adapter runs within the Isolated host and not the in-process host.
     
    Set the breakpoints, most likely in the IBaseMessage Execute method
     
    Drop a message in a recieve location to invoke the pipeline.
    The easiest way is using the FILE adapter.
    The project will enter break mode when a breakpoint hits.
     
    The major advantage of this method is that it resembles the situation as it will be in the acceptance and production environments.
    The major disadvantage is that it is quite hard and complicated.
     

    The pipeline.exe tool
     
    The pipeline.exe tool can be found in <BizTalk root install>\SDK\Utilities\Pipeline Tools. More information about the tool can be found in the MSDN.
     
    Set the output of the solution (custom pipeline component dll) to <BizTalk root install>\Pipeline Components.
    This can be done by changing the output path of the projects build properties.
     
    In the Debug properties of the Visual Studio project, set the Start Action to "Start external program".
    Set the full path to <BizTalk root install>\SDK\Utilities\PipelineTools\Pipeline.exe.
     
    In the Start Options specify the "Command line arguments".
    Most times I use the full path to the pipeline file (.btp), followed by -d and the full path to the flat file to test, -p, to display the promoted context properties, -c, to display the result to the console, and -t, to display elapsed time of components execution.
    The result looks like:
    D:\Project\Pipelines\Receive\Sample.btp -d D:\Project\Pipelines\Receive\Test\test.txt -p -c -t
     
    Set the breakpoints, most likely in the IBaseMessage Execute method
     
    Right the project and Select Debug, Start new instance to start debugging
     
    The major advantage if this method is that it is fast and easy.
    The major disadvantage is that pipeline.exe does not access the BizTalk databases, so some components will not execute properly.

    XML Validator pipeline component error in Send Pipeline

    Technorati Tags: ,, Validator Pipeline Component
     
    The MSDN mentions "The XML Validator pipeline component can be used in both send and receive pipelines in any stage except for Disassemble or Assemble."
     
    So, when your not paying attention, and put the the component in the assemble stage of a send pipeline, you get the following error:
    There was a failure executing the send pipeline: "xxxxx.BizTalk.Pipelines.Send.Compress, xxxxx.BizTalk.Pipelines, Version=1.0.0.0, Culture=neutral, PublicKeyToken=1234a1aa1a123a1a" Source: "XML validator" Send Port: "xxxxx" URI: "FILE://D:\File.gz" Reason: AddDocument: The component "XML validator" must implement the IAssemblerComponent interface.
    I've learned my lesson.

    C# Enum.Parse

    Technorati Tags: ,,,
     
    Lately, I was working on a BizTalk Server pipeline component to unzip files. An enumeration was created to hold the supported archive types. When working with my enumeration I ended up with the following statement to convert the enum string value to an enum item value:
    ArchiveFormat myFormat = (ArchiveFormat) Enum.Parse(typeof(ArchiveFormat), formatName);
    Somehow, I knew there was a nicer way of coding this. While live searching I ran into a nice post from Christopher Bennage. He thought the code was ugly and contained too many casts. So he created a typesafe parse method using generics in a separate helper class called Enum<T>.
    Here's the code. It's pretty neat.
    public static class Enum<T>
    {
    public static T Parse(string value)
    {
      return (T) Enum.Parse(typeof (T), value);
    }
     
    public static IList<T> GetValues()
    {
      IList<T> list = new List<T>();
      foreach (object value in Enum.GetValues(typeof (T)))
      {
       list.Add((T) value);
      }
      return list;
    }
    }
    My code now looks like:
    ArchiveFormat myFormat = Enum<ArchiveFormat>.Parse(formatName);
    Nicer and better, it's type safe.

    Correlating BizTalk Instance with the PID of the BizTalk Service

    Just back from holidays, I needed to debug a c# component used in one of our orchestrations. Since we introduced some additional host instances, I needed to to determine to which host instance (service) to attach to. In the Attach to Process dialog it is not possible to see to which host instance the pid belongs, they, in this example, both show as  BTSNTSvc.exe.

    Attach to Process  

    However, by executing the tasklist command using the command prompt you are able to determine where to attach to.
    Execute the following command (on a 32 bit server):

    tasklist /svc /fi "imagename eq btsntsvc.exe"

    • tasklist
      Displays a list of applications and services with their Process ID (PID) for all tasks.
    • /svc
      Lists all the service information for each process without truncation.
    • /fi <filter name>
      Specifies the types of process(es) to include in or exclude from the query. The eq is equals.

    The result after executing the command will be something like:

    Taslist Command

    As the orchestrations are run within the BtsProcessingHost, the belonging PID can now easily be found and the component attached the corresponding BizTalk service.

    Promoted properties and datatypes

     
    When doing some modifications in a BizTalk solution I changed the datatype of an element in a Property Schema from string to long. After deployment it gave me the following error:
     
    There was a failure executing the receive pipeline: "Microsoft.BizTalk.DefaultPipelines.XMLReceive, Microsoft.BizTalk.DefaultPipelines, Version=3.0.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" Source: "XML disassembler" Receive Port: "Load ..." URI: "D:\In\XML\*.xml" Reason: Cannot convert "SomeID" to "long" because the type is not supported.
    I simply forgot BizTalk does not support promoted properties of type long. Changing the datatype back to string solved the problem.
     
     

    BizTalk schema editor, base data types and restrictions

    When you define an element with data type xs:decimal, there is no way that you can control the digits using the XSD schema editor in Visual Studio. However, you can still add the fractionDigit facet, by editing the BizTalk schema in a text/xml editor. Just add the following code under the xs:decimal data type element:

    <xs:simpleType>
                <xs:restriction base="xs:decimal">
                            <xs:fractionDigits value="3" />
                </xs:restriction>
    </xs:simpleType>

    If you than validate an instance the error nicely refers to the fractionDigits facet specified:

    The '….' element is invalid - The value '169.5652174' is invalid according to its datatype 'Decimal' - The FractionDigits constraint failed.

    Nice feature!

    While searching the internet I found this article by Stephen Kaufman describing the fractionDigit feature. It was written before BizTalk 2006 was even there. I'm wandering why this feature was not incorporated in BizTalk Server 2006 (R#).

    Flat-file Custom Date/Time Formats

    Technorati Tags: BizTalk Server 2006;Flat File;Custom Date/Time Format
     
    Lately I've been doing a lot of flat file validations and transformations. One of the conversions dealt with date/time conversions. In the schemas I wanted to use the xs:date datatype. However, the dates in the files supplied did not conform to the ISO 8601 format.
     
    When experimenting with the schemas, I ran into a property called Custom Date/Time Format. In that property you can define the alternative format of the actual supplied value and the flat file disassembler converts it to an xs:date format.
     
     BTS - Custom Format
     
    The use of Custom Date/Time Formats is explained in details at the Microsoft's BizTalk Server TechCenter.

    Team Foundation Server; 'Working folder is already in use'

    Technorati Tags: Team Foundation System;TFS
     
    Recently we migrated to TFS using virtual machines. However, when trying to get the sources creating work spaces and mapping working folder I ran into problems. The message I got was: 'The working folder is already in use by another workspace on this computer'.
     
    I followed some advice to remove the workspace using the command:
     tf workspace /delete /server:http://<server>:8080 <computer>;<domain>\<client>
     
    It did not solve my problem. The error indicates tha the server believes this folder is already in use in another workspace. So, I created a workspace using a different machine name and it worked. However, I did not want to use a different name other than my virtual machine name. It took me a moment to realise that there indeed was another workspace with the same name.  The person who cloned the virtual machines also had a workspace with the same machine name, but a different user name. Aparently, the workspace is bounded to a machine name and not to machine name and user as I would expect.
     
    Another lesson learned...

    'An error has occurred while establishing a connection to the server'

    When deploying a BizTalk project from Visual Studio, you sometimes run into this error:

    "An error has occurred while establishing a connection to the server.  When connecting to SQL Server 2005, this failure may be caused by the fact that under the default settings SQL Server does not allow remote connections. (provider: Named Pipes Provider, error: 40 - Could not open a connection to SQL Server)"

    This happened to me when migrating from Visual SourceSafe, VSS, to Team Foundation System, TFS, by copying the projects from a pc to a virtual machine. To solve this error, perform the following steps:

    1. Rightclick on the project and choose Properties
    2. Go to "Configuration Properties" => "Deployment"
    3. Change the "Server" property to be the servername of the SQL Server you are deploying to
    4. Save changes
    5. Deploy again

    The error happens since the servername is listed in the projectname.btproj.user file that is a part of the project.

    I often forget the change the servername, so this is to not forget it the next time.

    BizTalk Server 2006 R3

    Technorati Tags: , R3,VS2008,SQL Server 2008

    Today I read a blogpost on BizTalk Server Team Blog announcing the plans to deliver BizTalk server 2006 R3. This new release will support Windows Server 2008, .Net framework 3.5, Visual Studio 2008 and SQL Server 2008. According to Steve Martin's blogpost  a CTP of BizTalk Server R3 is expected later this year and the RTM is planned the first half of 2009.

    " at a high level we are planning some new investments in the release that includes:

    • New web service registry capabilities with support for UDDI (Universal Description Discovery and Integration) version 3.0 
    • Enhanced service enablement of applications (through new and enhanced adapters for LOB applications, databases, and legacy/host systems) 
    • Enhanced service enablement of “edge” devices through BizTalk RFID Mobile 
    • Enhanced interoperability and connectivity support for B2B protocols (like SWIFT, EDI, etc) 
    • SOA patterns and best practices guidance to assist our customer’s implementations"

    "Could not write to output file"

    Technorati Tags: ,,
     
    Occasionally, I run into the following error when building a solution containing multiple BizTalk projects:
    Could not write to output file '[path]\obj\Debug\[assembly].dll' -- 'The process cannot access the file because it is being used by another process.'
    I found this simple solution here. Just close and reopen Visual Studio 2005.
    Now you can rebuild your solution. Annoying, but it works.

    "An error has occurred while establishing a connection to the server"

    Recently I ran into this when I tried to deploy my BizTalk project from Visual Studio 2005:

    "An error has occurred while establishing a connection to the server.  When connecting to SQL Server 2005, this failure may be caused by the fact that under the default settings SQL Server does not allow remote connections. (provider: Named Pipes Provider, error: 40 - Could not open a connection to SQL Server)"

    I had run into this error before and after a few minutes I remembered what I did wrong: the server name. Since I moved the solution and projects from Visual Source Safe to Team Foundation System in a virtual machine environment, I needed to change the server name of the project. To change the property, complete the following steps:

    • Rightclick on the project and choose Properties
    • Go to "Configuration Properties" and select "Deployment"
    • Change the "Server" property to be the servername of the SQL Server you are deploying to
    • Save changes
    • Deploy again

    Now let's hope I won't forget it a next time.