All posts by tiagooliveira

BTDF – Generate specific environment binding

BizTalk Deployment Framework (BTDF) is known as the best way to perform BizTalk artifacts installation.
It’s also the only way (I know) to create an automatic BizTalk deployment.

If you don’t know what is BTDF, go to  https://biztalkdeployment.codeplex.com.

This Framework allow us to create an MSI deployment package directly  from Visual Studio or Command Line.
It also has a great feature that allow us to maintain only one binding file concerning all environments.
That binding template files are replaced for the correct environment data in the MSI generation.
The specific environment data is configured in a XML file that can be opened in Excel.

Sometimes there are releases that only have binding changes, and you want to use the best practice of always use BTDF generated data in your deployments.
So… how can you deal with this in BTDF.!! The VS menu does not have an option to generate environment bindings.

The BTDF installation give us a tool called xmlpreprocess, which is used in the MSI generation by the BTDF engine.
Xmlpreprocess tool allow us to merge a specific environment configuration with the binding template (normally named master binding), resulting in the transformed deployment binding.

It’s very easy to use.

  1. Open a Command Line Prompt
  2. Navigate to the  BTDF install folder “..\Framework\DeployTools” (normally  C:\Program Files (x86)\Deployment Framework for BizTalk 5.6\Framework\DeployTools)
  3. Execute xmlpreprocess.exe /v /c /noDirectives /i:”PORT_BINDINGS_MASTER_XML_PATH” /o:” OUTPUT_BINDING_FILE_PATH” /d:CurDir=”MAIN_SOLUTION_FOLDER” /s:”ENVIRONMENT_TO_GENERATE_BINDING_CONFIG_XML”

For example

xmlpreprocess.exe /v /c /noDirectives /i:”C:\Projects\MyProject\Deployment\PortBindingsMaster.xml” /o:”C:\Projects\MyProject\GeneratedBindings\OutputBinding.xml” /d:CurDir=”C:\Projects\MyProject” /s:”C:\Projects\MyProject\Deployment\EnvironmentSettings\Exported_ProdSettings.xml”

The generated environment (Local, QA, PRD, …) is defined in xml file path after the “/s” parameter.

Hope this helps.

 

BizTalk Server Single Sign On – Save config data in SSO

This is my last post about using SSO on Biztalk Server. In this post I will show how to set and retrieve configuration data from SSO.

To configure and set configuration data, Microsoft has an MMC Snap-In called “SSO Configuration Application”, that allow us to create and manipulate applications and their properties (http://www.microsoft.com/en-us/download/details.aspx?id=14524).

From the community there are several tools to set SSO configuration. The most well know was created by Richard Seroter in 2007 that allow us to manipulate previously created properties in an easy way (http://seroter.wordpress.com/2007/09/21/biztalk-sso-configuration-data-storage-tool/).  There are also some Richard Seroter tool improvements, like a version from Mark Burch in http://biztorque.net/archive/2010/06/07/74.aspx, that allow us to create new SSO properties.

BizTalk Deployment Framework also include an SSO module, that use a different approach of using the Excel to set SSO config data in each environment (http://biztalkdeployment.codeplex.com/).

To get configuration from SSO by code, you can use “SSOConfigHelper.cs” included in Microsoft BizTalk Server 2006 SDK, but still working with the latest Biztalk server versions (http://www.getcodesamples.com/src/2B2085E1/C4A921B1).
Just get the code and include “Microsoft.BizTalk.Interop.SSOClient.dll” in SSO install folder (for example C:\Program Files\Common Files\Enterprise Single Sign-On\Interop1.1\Microsoft.BizTalk.Interop.SSOClient.dll) and call the read method, setting the previous create application and property name.

Hope that 4 posts about SSO will help you to use SSO more frequently in BizTalk programming.

BizTalk Server Single Sign On – Using SSO with adapters

In BizTalk Server there are several adapters that automatically support SSO without any code.
Many BizTalk Adapters already support this feature, like SQL, most of WCF, Oracle, FTP, HTTP, etc.

The SSO configuration to support this feature is very easy.
First enter SSO Administration tool, and create a new affiliate application with the above settings (you can put any name in the application name):

image

image

image

image

In BizTalk Server Administration, when setting the receive location configuration, set the use SSO option, and use an isolated host with a running account that belongs to the SSO application administrators group (images above).

image

image

In the send port adapter configuration set the affiliate application created earlier.
image

image

To finalize the configuration, you must set SSO to allow ticket usage (by default is not allowed).
Execute the following instruction in the command prompt “ssomanage -tickets yes” (http://msdn.microsoft.com/en-us/library/aa559512.aspx)

The credential mapping is working without any “hand made” code creation.

BizTalk Server Single Sign On – Get mapped credential by code

This is my second post about using single sign on in Biztalk Server.
In this post i will show how to access mapped credentials by code.

First create a new affiliate application and a credential mapping as i show in the last post.

    1. Create a new class library project called “Test.SSO”
    2. Add a reference to the assembly “Microsoft.BizTalk.Interop.SSOClient.dll”, located in “C:\Program Files\Common Files\Enterprise Single Sign-On”
    3. Add the following code in a new class called SSOManager
      using System;
      using System.Collections;
      using System.Collections.Specialized;
      using Microsoft.BizTalk.SSOClient.Interop;
      namespace Test.SSO
      {
           public static class SSOManager
           {
                /// <summary>
                /// Get external application credentials.
                /// </summary>
                /// <param name="ticket">Credential ticket generated by biztalk receive port.</param>
                /// <param name="appName">Application name to get external credentials.</param>
                /// <param name="userAccount">User account to get external credentials.</param>
                /// <returns>ArrayList with mapped credentials.</returns>
                public static ArrayList GetExternalApplicationCredentials(string ticket, string appName, string userAccount)
                {
                     ISSOTicket ssoTicket = new ISSOTicket();
                     string externalUsername;
                     string[] credentials = ssoTicket.RedeemTicket(appName, userAccount, ticket, SSOFlag.SSO_WINDOWS_TO_EXTERNAL, out externalUsername);
      
                     if (credentials == null || credentials.Length == 0 || String.IsNullOrWhiteSpace(externalUsername))
                     {
                          return null;
                     }
      
                     ArrayList credentialsList = new ArrayList();
                     credentialsList.Add(externalUsername);
                     credentialsList.AddRange(credentials);
                     return credentialsList;
                }
           }
      }
      
    4. Create a new Orchestration called SSOOrch
    5. Include a reference to the previous created class library
    6. Publish a new wcf service  using “WCF Service Publishing Wizard” and publish it at basic auth (http://msdn.microsoft.com/en-us/library/bb226564.aspx)
    7. Set the Orchestration receive location to receive messages from the service created
    8. Configure the receive location security área like the following image, but checking “Use Single-On” option.
      image_thumb.png
    9. Create na Orchestration variable called ssoMapping as ArrayList
    10. Add a new expression shape in the orchestration
    11. Add the following code in the previous expression Shape (TestApp is the name of the affiliate application previously created)
      ssoMapping = Test.SSO.SSOManager.GetExternalApplicationMapping(SSOOrch(BTS.SSOTicket), “TestApp”, SSOOrch(BTS.WindowsUser));
    12. Complete the orchestration by setting a send shape to file system.
    13. Deploy the orchestration and set the regular configurations, but very important – set an host instance with an account that belongs to a SSO application administration group
      image
    14. Invoke the previously created wcf service with an account that you have set in the SSO mapping.
    15. If you debug the orchestration, you will get in the ssoMapping ArrayList 4 parameters with the data you have set in “User Id”, “MappedUser”, “”MappedPassword” and “MappedDomain” as you see in the next image.
      image

Hope this example will help you to easily use SSO in BizTalk Server.
Happy coding.

BizTalk Server Single Sign On Configuration

This is my first post (in a total of four) about using SSO on BizTalk Server.
In this post i will show how to config an 1 on 1 credential mapping in SSO, in the next 3 posts i will show how to access mapped credentials by code, use SSO directly in BizTalk adapters, and the most commonly used to store key pair values.

It’s very easy to configure SSO to store credential mapping data.
First access mmc console and choose Enterprise Single-Sign-On application.

SSO1_1

Then choose Affiliate Applications and select “Create Application”.

SSO1_2

The application creation wizard starts. Choose “next”.

SSO1_3

For 1 on 1 credential mapping, select “Individual” application Type. To read about all mapping types, check http://msdn.microsoft.com/en-us/library/aa578204.aspx.
Select the application name, description and leave the other options unchecked (if you are using dev or single server, check the option “Allow local accounts for access accounts”).

SSO1_4

Set the Windows group that will manage this Affiliate Application in the “Application Administrators” picker.
Set the windows group for which mappings can be created in “Application Users” picker.
You can check more about this configurations in http://msdn.microsoft.com/en-us/library/aa561561.aspx.

SSO1_5

In the Options menu check the following options:

    • Enabled.
    • Allow Windows initiated SSO.
    • Tickets Allowed (with all ticket options selected).
    • Application Users cannot create mappings (only a security measure).

A ticket is a kind of SSO encrypted context, that contains the request user domain and username and the ticket expiration time.
You can check more info about SSO tickets in  http://msdn.microsoft.com/en-us/library/aa578039.aspx.

SSO1_6

In the fields menu, you must choose the destiny application attributes to map in this SSO affiliate application.
I have created 3 attributes (Mapped User, Password and Domain).
The User ID mapping is created by default and is a mapped credential unique key.
The masked attribute is used for the password fields, and the synchronized attribute determines that the field is used for password synchronization.

SSO1_7

The affiliate application is created successfully.

SSO1_8

After creating the affiliate application it’s very easy to create a mapped credential.
Just go to the Affiliate Applications menu, select the previously created “TestApp” application and “New Mapping” option.

SSO1_9

In the “Create New Mapping” menu select the windows account to map and the unique destiny account name to map.
Check the “Set credentails for this mapping” option.

SSO1_10

In the Set Credentials menu, set the mapped data.
The user id can be used to store the mapped user data, but beware because user id must be unique. So I have created the MappedUser field, because I can have multiple source accounts to map to the same destiny account data.

SSO1_11

The new mapped credential appears in the “TestApp” affiliate application mapped credentials.

SSO1_12

In the next post I will show how to get the mapped credentials data by code, to use for example in a BizTalk Orchestration or Pipeline.

Biztalk xml header processing

When we use infopath or similar technologies with biztalk, the messages have always a xml processing header. Biztalk does not copy xml processing header to the output messages by default, so we have to set it manually.

There are several options in biztalk to manipulate xml header processing in output messages:

  • Set the header in orchestration using the message context properties

Example
message(XMLNORM.ProcessingInstructionOption) = 0 (append) or 1 (create new);
message(XMLNORM.ProcessingInstruction) = “xml processing header to add or append”;

Important: For the demoting process to occur, you must use the Xml assembler component or xml transmit pipeline in the output send port.

  • Use xml transmit pipeline or a custom pipeline with the xml assembler component in the output send port

When you use the xml transmit pipeline, you must set the following properties:

ProcessingInstructionsOptions – 0 (append) or 1 (create new)
XmlAsmProcessingInstructions – “xml processing header to add or append”

  • Use a custom pipeline component

When  you use a custom pipeline with xml assembler component, set the following properties:

Add Processing Instructions – Append or Create new
Add processing instructions text – “xml processing header to add or append”

This option is the most difficult to implement, you have to create a custom assembler component, get and change the output message.

Do not forget to set the the biztalk maps property “copy processing instructions (pis)” to “yes” when you want to copy the processing instructions from the input to output messages.

Using xpath function in orchestrations

Xpath is a function that can be used in any orchestration to set and retrieve data from/to messages.

The syntax is very simple:

  1. Set a value in message
    xpath(message, "xpathQuery") = value;
  2. Get a value from message
    variable = xpath(message, "xpathQuery");

The first problem that all users complains it's how to get the xpath of a specific message element. This can be achieved by going to the properties of the chosen element and copy the "Instance XPath" property value.

 

Another problem is using Xpath function to get message elements data. When you want to get a string value to a string variable, for example, you must use the xpath string function.

stringVariable = xpath(message, "string(xpathQuery)");

For a number value

intVariable = xpath(message, "number(xpathQuery)");

If you want to use the Xpath function to get xml data to a XmlDocument variable you must not use any xpath function.

xmlDocumentVariable = xpath(message, "xpathQuery");

Some examples:

booleanVar = xpath(message, "boolean(/*[local-name()='Root' and namespace-uri()='http://TestNamespace/200902']/*[local-name()='IntField' and namespace-uri()=''])");

xmlVariable = xpath(message, "/*[local-name()='Root' and namespace-uri()='http://TestNamespace/200902']/*[local-name()='anyField' and namespace-uri()='']");

xpath(message, "/*[local-name()='Root' and namespace-uri()='http://TestNamespace/200902']/*[local-name()='anyField' and namespace-uri()='']") = xmlVariable.InnerXml;

xpath(message, "/*[local-name()='Root' and namespace-uri()='http://TestNamespace/200902']/*[local-name()='BooleanField' and namespace-uri()='']") = booleanVar;

xpath(message, "/*[local-name()='Root' and namespace-uri()='http://TestNamespace/200902']/*[local-name()='IntField' and namespace-uri()='']") = 3;

Replace namespace prefix pipeline component

In some biztalk integrations with legacy systems, there are message specifications that requires a specific namespace prefix, but all biztalk messages use ns0, ns1, ns… definition to define prefix information.

To solve this problem there are two solutions :

  1. You can replace the prefix data in all maps output xslt, then replace the map with the changed xslt, solution explained in Jeff Lynch blog.
  2. Use a custom pipeline with a component that makes the necessary replacements.

If you have few maps that do not change frequently, you can implement the first solution, otherwise the second solution is better.

I have created a custom component, based on the ESB Guidance namespace component, that perform the prefix replacements. It only requires the old and the new prefix name and uses streams in the replacement for better performance.

Before use, check the regular expression replacement agains your message schemas, and see if doesn't make any unnecessary replacement.

How to – Validate Windows Workflow custom activity input

Windows Workflow allow us to perform custom validator input that is executed at design and compile time. The error output is similar as Biztalk Orchestration shape errors.

Adding a validator to a custom activity involves two steps:

  1. Create a class that derives from ActivityValidator class and override Validate method;
  2. Add a ActivityValidator attribute with the validator type to the custom activity;

As an example, i'm going to show a validator creation that verifies if a specific property is set.

I have already created a custom activity that is called Hello and have a property that receives the user name. To validate if the activity proprety is set, i'm going to create a validator. 

ActivityValidator class creation:

As said early, to create a validator i have to create a class that derives from ActivityValidator. To perform the validation i have to override the validate method and set the validation code.

using System;

using
System.Text.RegularExpressions;

using
System.Workflow.ComponentModel.Compiler;

internal sealed class ExampleValidator : ActivityValidator {

    public override ValidationErrorCollection Validate (ValidationManager manager, object obj)
    {

        if (manager == null throw new ArgumentNullException("Invalid manager.");)

        if (obj == null throw new ArgumentNullException("Invalid activity.");)

        HelloActivity activity = obj as HelloActivity

        if (activity == null) throw new InvalidOperationException("Activity should be a HelloActivity.");

        ValidationErrorCollection errors = base.Validate(manager, obj);

        // Validate UserName property setting validationErrorCollection with information
        // about the property that causes the error.

        if (string.IsNullOrEmpty(activity.UserName)) {
           
errors.Add(ValidationError.GetNotSetValidationError("Username"));
        } 

        return errors;
    }
}

 

Custom activity and validator association

To associate the validator with the custom activity it's used the activityvalidator attribute.

[ActivityValidator(typeof(ExampleValidator))]

public sealed class HelloActivity : System.Workflow.ComponentModel.Activity {..

 

In the end the custom activity validator error will be show like this:

WFValidator 

Using WF CallExternalMethod activity in Windows Workflow

The CallExternalMethod Activity allows us to make synchronous communication between Workflow and the Host through the Local Service using Local Service Communication.

Local Service Communication allows workflows to communicate with an external service that resides within the Host.

Using this activity involves 4 phases:

1.    Contract interface creation;

2.    Workflow CallExternalMethod activity configuration with the contract interface, the parameter(s) and return properties (if applies);

3.    Contract implementation creation;

4.    Using ExternalDataExchangeService class at the Host, to register the Contract implementation

We can optionally set the input properties and read the return data.

Example:

In this example I'm going to show the execution of a simple method that returns the 2 input parameters concatenation.

1.    Contract interface creation

    In the contract interface you have only to create the interface contract definition used by the Workflow.

    You're going to create an Interface named "IContract", which defines the Concatenate method.

    All interfaces must have the ExternalDataExchange attribute defined that marks the interface as a local service interface.

       [ExternalDataExchange]
    public interface IContract 
    {

        string Concatenate(string parameter1, string parameter2);
       }

2.    Workflow CallExternalMethodActivity configuration

    Add the CallExternalMethodActivity to the Workflow.

    The Workflow will appear like this:

    Then you will create three properties that correspond to the two input parameters to concatenate and the return concatenation.

    public string Parameter1ToConcat { get; set; }

    public string Parameter2ToConcat { get; set; }

    public string ConcatenateReturn { get; set; }

    

    Configure the CallExternalMethodActivity properties like this:

InterfaceType

IContract interface

MethodName

Concatenate

Parameter1 & parameter2

Parameter1ToConcat & Parameter2ToConcat properties

(ReturnValue)

ConcatenateReturn property

 

3.    Contract implementation creation

    At the contract implementation creation, you have to create a class that implements IContract defined at the first step.

  public class ContractImplementation : IContract
  { 

      public string Concatenate(string parameter1, string parameter2)                      
      { 

          return parameter1 + parameter2; 
           }            
   }

4.    Host configuration

    At the Host, the contract implementation is registered by using the ExternalDataExchangeService class.

    The input properties can be set by using the second parameter from the CreateWorkflow method.

    The return parameter can be retrieved using the OutputParameters property from the WorkflowCompletedEventArgs class, at the WorkflowCompleted event.

using (WorkflowRuntime workflowRuntime = new WorkflowRuntime())

  …  
  workflowRuntime.WorkflowCompleted += delegate(
          object sender, WorkflowCompletedEventArgs e) 
    {
      // this is where we can get the return value 
      Console.Write((string)e.OutputParameters["ConcatenateReturn"]); 
      waitHandle.Set();
    } 
  … 
  ExternalDataExchangeService externalDataExchangeService = new ExternalDataExchangeService();  

  // add the external data exchange service to the runtime 
  workflowRuntime.AddService(externalDataExchangeService); 

  // add the external method implementation to the local services 
  // this is where we add the object(that implements IContract)
  // that is going to be invoked by the CallExternalMethodActivity 
  externalDataExchangeService.AddService(new ContractProject.ContractImplementation()); 

  Dictionary<string, object> parameters = new Dictionary<string, object>(); 

  // add both paramenters  
  parameters.Add("Parameter1ToConcat", "1"); 
  parameters.Add("Parameter1ToConcat", "2"); 

  WorkflowInstance instance = workflowRuntime.CreateWorkflow(
              typeof(WorkflowConsoleApplication1.Workflow1), parameters); 
  instance.Start(); 
  waitHandle.WaitOne();