Sunday, 8 March 2009

MSBTS_SendAdapter doesn't work!

Just a quick post as a reminder to me (and a pointer for anyone else who happens upon this blog) to save lots of time scratching my head, looking at code that should work but doesn't.

I wrote some code as part of a BizTalk deployment framework which was intended to create an adapter handler if one does not already exist for the specified adapter/host. The Receive handler version worked fine but the Send version gave some strange results.

First I queried the existence of the send handler via WMI using MSBTS_SendHandler. This always returned an empty set indicating that it doesn't (even when the handler does in fact exist). When trying to create a send handler I got an error message (will update with exact text when I get a chance to look).

Anyway, to cut a long story short it turns out that MSBTS_SendHandler2 works fine so the guidance is to use this instead. My question is though - why does MSBTS_SendHandler still exist at all? It can't be for backwards compatibility because IT DOESN'T WORK! Why not just fix MSBTS_SendHandler instead of adding MSBTS_SendHandler2? Answers on a postcard to...

Wednesday, 24 December 2008

Identifying a BizTalk process

When using multiple BizTalk Hosts the process relating to each host can be identified using the following command line instruction:

tasklist /SVC /FI "IMAGENAME eq btsntsvc.exe"

This will display a list of BizTalk processes with the name of the Host and the PID. Note the PID for the host you are interested in. Match the correct PID with the process listed in Task Manager or the Visual Studio  Attach To Process dialog.

Tuesday, 23 December 2008

Resolving Schema Type Name Clashes

A common schema related error that may occur when building BizTalk projects that include schemas is:

BEC2017: Node "<Schema>" - This schema file has a TypeName that collides with the RootNode TypeName of one of its root nodes. Make sure that they are different.

The reason for this is quite simple - when the project is compiled, a .NET class will be generated for each top level element in your schema. If you have two schemas which share the same top level element name a clash will occur.

This is quite a common scenario and it is not always practical (or even possible) to change the element names. The solution is to change the generated type name for the schema. To do so, select the schema in the Solution Explorer and press F4 to display the Properties window. Then change the Type Name property so that it is not the same as any of the top level elements.

Monday, 22 December 2008

Default content in Maps

On a couple of occasions recently I have hit upon the need to use default content in some elements of a message generated via a map. More specifically I had an orchestration which did the following:

  • Defined an input and output schema that contained a standard header section
  • Makes calls to external .NET components, other orchestrations and send ports
  • If all works OK, a suitable response message is returned
  • In the event of a failure, an exception handler is invoked which constructs a new message to send to a common error logging orchestration before creating and returning a response message to the caller

The area of interest is the message sent to the error logging orchestration. This schema contains the standard header along with error information to be logged (for which each element defined as a distinguished field) i.e.

<xsd:element name="exception_details">
  <xsd:complexType>
    <xsd:sequence>
      <xsd:element name="type" type="xsd:string" />
      <xsd:element name="description" type="xsd:string" />
      <xsd:element name="error_source" type="xsd:string" />
      <xsd:element name="details" type="xsd:string" />
    </xsd:sequence>
  </xsd:complexType>
</xsd:element>

To create an instance of this message I transform the original request (to create the standard header) and insert the error details via code in a message assignment shape.

image

msgException.exception_details.description = ex.Message;
msgException.exception_details.details = ex.ToString();
msgException.exception_details.error_source = "orch name";
msgException.exception_details.type = "details here";

However, in order to programmatically insert the content into these elements, the elements had to exist in the new message! If it does not I get an XPath error when trying to set the distinguished property values.

To ensure that the elements exist I used the useful but often overlooked property of the element - Value. To find this open the Map Designer, select the target element and go to the Properties window. There you will see a Value property which can be used to set a default value for the element or <empty>. In this case <empty> was most appropriate giving message content of:

<message>
    <header>
        ...header content omitted
    </header>
    <payload>
        <exception_details>
            <description/>
            <details/>
            <error_source/>
            <type/>
        </exception_details>
    </payload>
</message>

This allowed me to set the error detail programmatically as required. Voila!

How can I use Fiddler to debug BizTalk messages?

When using HTTP, SOAP or WCF send ports it can be incredibly useful to view the content of messages that are sent on the wire. This allows you to inspect the headers (SOAP or HTTP). Fiddler is a simple but fantastic tool to allow you to do this.

By default, Fiddler will not trace any messages sent to endpoints by BizTalk as it does not use WinInet. However, BizTalk send ports can be configured to use a proxy allowing Fiddler to intercept them. On the Send Port tick the Use Proxy checkbox and set the Server to 127.0.0.1 and the port to 8888. For dynamic ports, set the following properties (as applicable to the adapter being used)

// Debug via fiddler
msgSendRequest(SOAP.UseProxy) = true;
msgSendRequest(SOAP.ProxyAddress) = "127.0.0.1";
msgSendRequest(SOAP.ProxyPort) = 8888;

Note that this needs to be removed when Fiddler is not running since traffic directed to the proxy will not be received by anything.

Friday, 9 May 2008

Fix Missing Vista Segoe UI font

A bit off topic here but useful nonetheless. Recently my Vista box mislaid the default system font Segoe UI and consequently fell back to the italic version of the same font. Whilst this is not a huge issue, it just looks ugly!

Anyway after a lot of searching, the font can be replaced for free by installing Windows Live. Worked for me!

Tuesday, 4 March 2008

Using the SSO database for storing configuration data

Single Sign-on is something that is often overlooked as being related only to Parties and for management of credentials. However, in its raw form, SSO provides a secure data store that can be used to store any information your application needs. In fact it can be used by non-BizTalk applications and doesn't have to only be for sensitive data, though this is the most typical usage.

In order to use SSO programmatically, an API is provided for accessing data. An MMC snap-in is also supplied for administrative purposes and third-party tools also exist for this purpose. Command line based tools also exist enabling scripting support.

Adding new configuration items to SSO

Using the tools supplied out-of-the-box with BizTalk 2006 R2, it is pretty easy to create an SSO schema and populate it with some data.

Create a schema for the configuration data. This is an XML file that look like the following:

<sso>
    <application name="Application Name here">
        <description>Description here</description>
        <contact>email address here</contact>
        <appuserAccount>domain\AppUserAccount</appuserAccount>
        <appAdminAccount>domain\AppAdminAccount</appAdminAccount>
        <field ordinal="0" label="reserved" masked="no" />
        <field ordinal="1" label="field name here" masked="no" />
        <field ordinal="2" label="field name here" masked="yes" />
        <flags groupApp="no" configStoreApp="no" allowTickets="no"
           validateTickets="yes" allowLocalAccounts="no" timeoutTickets="yes"
           adminAccountSame="no" enableApp="no" />
    </application>
</sso>

You can create as many fields as needed and multiple applications too. Note that the first field should not be used for a custom setting and is reserved for internal use.

Use the ssomanage.exe command line tool (in the C:\Program Files\Common Files\Enterprise Single Sign-On\ folder) to create the SSO application based upon the schema. To do so use the -createapps option specifying the filename of the schema XML created above. The application has access control for user and administrators based upon groups. By default these are the “BizTalk Application Users” and “BizTalk Server Administrators” groups respectively.

ssomanage -createapps "MySchema.xml"

To populate the schema with some data, use the BTSScnSSOApplicationConfig.exe command line tool (supplied with source code) in the C:\Program Files\Microsoft BizTalk Server 2006\SDK\Common\SsoApplicationConfig folder. Run Setup.bat to compile the tool and the executable should be generated in the bin folder.

BTSScnSSOApplicationConfig.exe -set AppName "ConfigProperties" "paramname" "paramvalue"

To retrieve a data item

BTSScnSSOApplicationConfig.exe -get AppName "ConfigProperties" "paramname"

Retrieving SSO configuration values in code

Once the data is stored, it can be accessed using the API. BizTalk 2006 comes with a client DLL which can be used to create a configuration reader class. In most instances it is recommended to create a type safe version to convert data items from their name/value pairs into the correct data type.

  • Add a reference to assembly Microsoft.BizTalk.InterOp.SSOClient.dll
  • Create a Property Bag that implements from IPropertyBag

public class ConfigurationPropertyBag : IPropertyBag
{
    private HybridDictionary properties;

    internal ConfigurationPropertyBag()
    {
        properties = new HybridDictionary();
    }

    public void Read(string propName, out object ptrVar, int errLog)
    {
        ptrVar = properties[propName];
    }

    public void Write(string propName, ref object ptrVar)
    {
        properties.Add(propName, ptrVar);
    }

    public bool Contains(string key)
    {
        return properties.Contains(key);
    }

    public void Remove(string key)
    {
        properties.Remove(key);
    }

}

  • Use the SSOConfigStore class to access the data using the property bag

public static class SSOConfigHelper
{

    private static string idenifierGUID = "ConfigProperties";

    /// <summary>
    /// Read method helps get configuration data
    /// </summary>
    /// <param name="appName">The name of the affiliate application
    /// to represent the configuration container to access</param>
    /// <param name="propName">The property name to read</param>
    /// <returns>
    ///  The value of the property stored in the given affiliate
    /// application of this component.
    /// </returns>
    public static string Read(string appName, string propName)
    {
        try
        {
            SSOConfigStore ssoStore = new SSOConfigStore();
            ConfigurationPropertyBag appMgmtBag = new ConfigurationPropertyBag();
            ((ISSOConfigStore) ssoStore).GetConfigInfo(appName, idenifierGUID, SSOFlag.SSO_FLAG_RUNTIME, (IPropertyBag) appMgmtBag);
            object propertyValue = null;
            appMgmtBag.Read(propName, out propertyValue, 0);
            return (string)propertyValue;
        }
        catch (Exception e)
        {
            System.Diagnostics.Trace.WriteLine(e.Message);
            throw;
        }
    }
}

Whilst the use of these command line tools is potentially advantageous from a scripting perspective, their use on an ad-hoc basis is not ideal. An MMC snap-in now exists for managing an SSO database. Richard Seroter has written a really cool configuration tool for managing configuration data which has a handy export feature that will export the application schema as an XML file. Source code is also available.