Simple RegEx replace in C#

As I don’t use regular expressions that often I always forget the syntax. So I thought I just put a basic replace pattern up here.
This method takes a schema, finds all places where is says schemaLocation=”whatever” in a text and changes this to schemaLocation=”whatever.xsd“ and then returns the schema.

private XmlSchema FixSchemaLocation(XmlSchema schema)
{
System.Text.RegularExpressions.Regex locationReplacePattern […]

Mercator or WTX (WebSphere Transformation Extender)

Mercator or WTX (WebSphere Transformation Extender)

I am sure some of you who happen onto this blog have worked with the old Mercator or WebSphere TX product.

I just spent the last few days working on upgrading a 6.7 solution to 8.1. I was amazed how I was still able to remember all of the command line switches/card overrides after a few years of not dealing with it.

I just want to tip my hat to all you who are still working with that product. I kinda wish that the mapping capabilies that are in the mapper would be present in the BizTalk mapper.

Anyway, just wanted to put a note out there that I was suprised that either the product must be near perfection because there were not many new features from two versions ago, except a debugging utility in the mapper, and it deals with XML a little differently.

Difference between (PassThruReceive, PassThruSend) and (XmlReceive, XmlSend) Biztalk Pipelines (For Beginners)

Difference between (PassThruReceive, PassThruSend) and (XmlReceive, XmlSend) Biztalk Pipelines (For Beginners)

I’ve recently seen a query in the “Biztalk New Users” newsgroup someone asking the above question. I quickly did a search to find out if there is (are) a decent article out there explaining the difference and didn’t find any. I feel its quite important and basic thing every biztalk developer should understand, ofcourse we all learned this by experience, but for new comers it will be a big confusing point. So, let me put a short article here to explain the difference.

 

The above figure show the architecture for Biztalk 2004/2006 (I’m sure you would have come across this picture million times by now, I took it from MSDN). It shows clearly the only way messages can come in and go out of the message system via some kind of pipeline. So, whether you are doing any processing in the pipeline or not you need some default pipeline for the message to come in and go out of Biztalk.

 

Out of the box biztalk provides 2 Receive pipelines (PassThruReceive, XmlReceive) and 2 Send Pipelines (PassThruSend, XmlSend), ofcourse you can go and build more custom pipelines if required. For a detail understanding of pipelines read my white paper published by Microsoft.

 

Now, what’s the difference?

The default PassThruReceive and PassThruSend pipelines doesn’t do any processing at all with the message. You can treat them as if like no pipelines are present (virtually) inbetween the adapter and the message box. Wheareas the XmlReceive pipeline will have a XmlDisassembler pipeline component on the disassembling stage and the XmlSend pipeline will have a XmlAssembler on the Assemble stage as shown in the above figure.

 

Why do we need a XmlReceive pipeline:
As discussed earlier the only additional component in the XmlReceive pipeline when compared to PassThruReceive pipeline is the addition of XmlDisassembler pipeline component on the disassembling stage. Whenever an Xml message is received via the XmlReceive pipeline the XmlDisassembler will do the following tasks:

1.Promote the “MessageType” context property by taking the combination of TargetNamespace and Rootelement in the format, Targetnamespace#RootElement.
2. Remove Envelopes and disassemble the interchanges
3. Promote the content properties from interchange and individual document into message context based on the confirured distingushed fields and promoted properties.

See the link for detailed explanation of XmlDisassembler (http://msdn2.microsoft.com/en-us/library/ms964545.aspx).

There are 3 important things you need to keep in mind.

1. Maps on the receive side will be applied after the receive pipeline. In order to pick the correct schemas for processing, Maps need the “MessageType” property, which is promoted by the XmlDisassembler. So, if you are using PassThruReceive “MessageType” property won’t be present, which in turn will result in Map not being applied.

2. Binding of logical port (Activation port) in the orchestration to a message (inside the orchestration designer), and deploying/enlisting the orchestration will create the subscription for the particular message type. So, if you are using PassThruReceive “MessageType” property won’t be present, which in turn will result in not starting the particular Orchestration instance.

3. If you have configured content based routing based on the properties in the message (Filters in SendPorts, Example: BTS.MessageType = http://tempuri#Person), routing won’t happen until the correct properties are present in the message context.

Note: There are numerous ways in which you can make all the above 3 points work without XmlReceive pipeline, but they all requires some custom coding.

Is there any rule on the combination of Pipelines you can use on the Receieve and Send side?

Of course, NOT. There is no restriction on the type of pipeline combination you need to use on the Receive and Send side. For example: You can receive a message via XmlReceive pipeline and Send it thru PassThruSend pipeline, this applies to custom pipelines as well. In fact Biztalks pub/sub architecture doesn’t put direct connection (or in better terms won’t know) between the receive and send side.

Why do we need a XmlSend pipeline?

XmlSend pipeline does the reverse of what a XmlReceive pipeline did. It got a XmlAssembler component in the Assemble stage in addition to the PassThruSend pipeline, which does the following tasks:

1. XML Assembler Builds envelopes as needed and appends XML messages within the envelope.

2. Populates content properties on the message instance and envelopes.

See the link for detailed explanation of XmlAssembler http://msdn2.microsoft.com/en-us/library/ms964547.aspx

For beginners, you can skip all the points related to Envelopes and Interchanges mentioned above.

Defining design-time properties using basic .NET data types

Defining design-time properties using basic .NET data types

<!–
/* Style Definitions */
p.msonormal, li.msonormal, div.msonormal
{margin:0cm;
margin-bottom:.0001pt;
font-size:12.0pt;
font-family:”Times New Roman”;}
h2
{margin-top:12.0pt;
margin-right:0cm;
margin-bottom:3.0pt;
margin-left:0cm;
page-break-after:avoid;
font-size:14.0pt;
font-family:arial;
font-style:italic;}
p.codesk, li.codesk, div.codesk
{margin:0cm;
margin-bottom:.0001pt;
line-height:11.0pt;
font-size:8.0pt;
font-family:”Courier New”;
color:black;}
@page section1
{size:595.3pt 841.9pt;
margin:72.0pt 90.0pt 72.0pt 90.0pt;}
div.section1
{page:section1;}
–>

Recently I was building a pipeline component which requires a simple design time property. Even though I’ve written a white paper about it Understanding Design-Time Properties for Custom Pipeline Components in BizTalk Server I couldn’t remeber all the syntax on top of my head. So, I opened the document for a quick view. I just copied a section from the article which explains the basic steps and published it here. View the full article for detailed explanation of some of the advanced concepts.

Let’s start with an example where you need three properties-ConnectionString (string), SaveContext (bool), and LogLevel (enum). To define these properties, you need to perform the following steps within your pipeline component:

 

Step 1: Define the enumeration type required.

public enum LogLevelType

{

 Warning,

 Error,

 Information

}

 

Step 2: Define private field variables.

 

private string _connectionString = string.Empty;

private bool _saveContext = false;

private LogLevelType _logLevel = LogLevelType.Information;

 

Step 3: Define public design-time properties.

public string ConnectionString

{

get{return _connectionString;}

set{_connectionString = value;}

}

public bool SaveContext

{

get{return _saveContext;}

set{_saveContext = value;}

}

public LogLevelType LogLevel

{

get{return _ logLevel;}

set{ _logLevel = value;}

}

 

Step 4: Implement the Load method of the IPersistPropertyBag interface.

public virtual void Load(Microsoft.BizTalk.Component.Interop.IPropertyBag pb, int errlog)

       {

            object val = ReadPropertyBag(pb,”ConnectionString“);

            if (val != null) _connectionString = (string)val;

 

            val = ReadPropertyBag(pb, “SaveContext“);

            if (val != null) _saveContext = (bool)val;

 

            val = ReadPropertyBag(pb, “LogLevel“);

            if (val != null) _logLevel = (LogLevelType)val;

        }

 

The helper function ReadPropertyBag is used to read the design-time properties from the property bag.  Error-handling code inside this function is required when the component is loaded inside the pipeline designer for the first time. At that point there are no values associated with the properties, which results in an exception. This helper function catches and suppresses the exception.

 

Private object ReadPropertyBag(Microsoft.BizTalk.Component.Interop.IPropertyBag pb, string propName)

        {

            object val = null;

            try

            {

                pb.Read(propName, out val, 0);

            }

            catch (System.ArgumentException )

            {

                return val;

            }

            catch (System.Exception e)

            {

                throw new System.ApplicationException(e.Message);

            }

            return val;

        }

Step 5: Implement the Save method of the IPersistPropertyBag interface.

public virtual void Save(Microsoft.BizTalk.Component.Interop.IPropertyBag pb, bool fClearDirty, bool fSaveAllProperties)

       {

            object val = _connectionString;

            pb.Write(“ConnectionString“, ref val);

 

            val = _saveContext;

            pb.Write(“SaveContext“, ref val);

 

            val = (LogLevelType)_logLevel;

            pb.Write(“LogLevel“, ref val);

        }

Step 6: Implement the GetClassID and InitNew methods of the IPersistPropertyBag interface.

 

   Public void GetClassID(out System.Guid classid)

        {

            classid = new System.Guid(“AC21E483-C9BF-41F1-9AF0-2031528535C6”);

        }

The GetClassID method needs to return a unique identifier that represents the component within unmanaged code, which will allow interoperability with unmanaged code.

 

Note: The BizTalk 2004/2006 messaging engine is built using unmanaged code.

 

public void InitNew(){}

 

For basic data types you can leave the InitNew implementation blank, since we don’t have any structure, data, cache, or object to initialize for our sample.  

 

After you compile the component and insert it into a BizTalk pipeline (see “Using the custom pipeline component within a BizTalk pipeline” later in this article), the properties will be displayed in the property grid as shown in the following figure.

 

 

Another BizTalk Financial Services Case Study by Decillion! Well done!

Another BizTalk Financial Services Case Study by Decillion! Well done!

Back in March 2006 I had the pleasure of blogging about the great job that Decillion (a local Australian Partner) did on their BizTalk / SWIFT Accelerator implementation at BNP Paribas here in Australia. Well it appears they have done it again – this time with Cuscal! Congratulations guys! Check out the details below.

 

Decillion SWIFT Payments Solution Goes Live

Cuscal, the leading wholesale financial services provider in Australia and Decillion Solutions Australia, have today announced the successful implementation of a SWIFT RTGS payments system developed by Decillion based on Microsoft BizTalk Server 2004. Cuscal processes in excess of $13 billion worth of RTGS payments per annum representing more than 90,000 transactions.

31st January 2007 – Decillion Solutions Australia and Cuscal have today jointly announced the successful implementation of a new SWIFT RTGS payments system. The system, developed by Decillion using Microsoft BizTalk 2004 Server and the Microsoft BizTalk Accelerator for SWIFT 2.1, has been in live operation since early November. It enables Cuscal’s clients to create and manage SWIFT RTGS payments via a highly secure internet based portal. With annual transaction volumes in excess of $13 billion the system is critical to the Cuscal’s service offering.

When the need to replace Cuscal’s previous SWIFT RTGS payment solution was identified, a rigorous vendor selection process was undertaken. “Being a mission critical system, mitigation of risk was an important factor in vendor selection” says Oliver Hudson, Cuscal’s Head of Financial Markets and Treasury. “There were two key elements in this area that marked Decillion out. One was the domain knowledge and previous experience of Decillion both in SWIFT and Microsoft BizTalk. We were confident that Decillion could leverage their partnerships with both SWIFT and Microsoft to overcome any issues faced during the development. Secondly, the Microsoft BizTalk Accelerator for SWIFT has been gold certified by SWIFT assuring us of compliance with the complex SWIFT standards both now and in the future.”

The use of Microsoft BizTalk was another important factor in the decision. “Cuscal is a very customer focused organization with a reputation of innovation in financial products and services” says John Carroll, Head of Operations. “Having made a significant investment in technology, we wanted to ensure that we were empowering ourselves to bring new products to market quickly. The flexibility and scalability of BizTalk, coupled with the fact that the Microsoft BizTalk Accelerator for SWIFT supports all SWIFT FIN messages, will provide the basis for the ongoing evolution and enhancement of our service offering.”

Decillion employs a client driven design process, with a focus on platforms not products, to enable the development of highly customized solutions tailored to the specific business process of their clients. In the case of Cuscal, it was critical that the project went live before the annual change in SWIFT message standards which the old system was unable to process. With less than 6 months from project initiation to go-live, project management was critical to the success of the initiative. Anthony Saber, Cuscal Project Manger, in reviewing the project commented that “the commitment shown by Decillion staff to delivery of the project was outstanding. Moreover, in large complex projects such as
this, the integration of teams is a critical component to the success of the project. I was particularly impressed with the ability of the Decillion staff to integrate into our working environment and work together with us as one team.”

 

About Decillion Solutions
Decillion Solutions Australia – based in Sydney, is part of the Decillion Solutions Group, headquartered in Singapore with offices in Kuala Lumpur, Bangkok, Jakarta and Shanghai. Specialising in a range of services for the finance industry, Decillion offers a product portfolio providing solutions for SWIFT, financial messaging, integration and automation, and Anti Money Laundering. Decillion Solutions Australia will customise solutions to assist you to achieve your organisations
business and technical goals. In conjunction with our product offerings, Decillion also provide implementation, support and training, through our trained and experienced staff. Decillion Solutions is a Business Partner and Service Partner for SWIFT. For more information, visit www.decillion.com.au or contact James Bibby, Regional Sales Director, Decillion Solutions Australia +61 2 9929 0655

About Cuscal
Cuscal is Australia’s leading wholesale provider of transactional banking, liquidity and capital management products and services to over 150 specialist financial service retailers including the majority of Australia’s credit unions. Cuscal’s clients manage more than $30 billion worth of assets. A key strength of Cuscal’s operating model is aggregation through its collective buying power on behalf of clients. In addition, Cuscal’s partnerships with other suppliers enables it to offer clients access to the Australian capital markets, payment systems, card schemes and inter-institutional
settlement arrangements. Clients are also able to leverage from Cuscal’s credentials as an approved deposit taking institution, AA- S&P credit ratings, principal membership of both Visa and MasterCard card schemes, and
membership of the Australian Payments Clearing Association (APCA). For more information, visit www.cuscal.com.au or contact Simon Covill, Corporate Communications Manager, Cuscal, +61 2 8299 9114.

Configuration management tool using C# 2.0 System.Configuration

Configuration management tool using C# 2.0 System.Configuration

So, I have been trying to write a tool to manage addition/updates to configuration
file like SomeApp.exe.config. This involves reading and writing to configuration files.
Using XML DOM is too low level when 2.0 provides System.Configuration namespace.
Here is the outcome of that effort. Thought I will share in view of the lack of documentation
from MS. Read/Write AppSettings wasnt hard. What I had problems with
was read/write custom ConfigurationSection

Here are a bunch of gotchas from this effort

  • If you are writing a configuration management app that wants to access random config
    files, you need to use ExeConfigurationFileMap and ConfigurationManager.OpenMappedExeConfiguration

  • When you read a configuration section from a source file and move
    it into some target file, you get an error “Cannot add a ConfigurationSection
    that already belongs to the Configuration
    “. I used reflection to get around
    this. I will show you how in a moment.

  • You can get raw xml configuration from ConfigurationSection using section.SectionInformation.GetRawXml().
    Likewise use SetRawXml to set this

  • When you load a config file using OpenMappedExeConfiguration,
    you get an in memory configuration which is “merged” and has sections from machine.config.
    You can check if a section came from the file you provided using section.ElementInformation.Source.Equals(source.FilePath)

So having got through that, here is how I did what I did

First off, load the source and target configs
>

//Load
Source


ExeConfigurationFileMap map = new ExeConfigurationFileMap();
map.ExeConfigFilename = “source.config”;
Configuration source = ConfigurationManager.OpenMappedExeConfiguration(map,ConfigurationUserLevel.None);

//Load
Target


map.ExeConfigFilename = “target.config”;
Configuration target = ConfigurationManager.OpenMappedExeConfiguration(map,
ConfigurationUserLevel.None);

Now
that we have the source and the target files we can start doing the real work

foreach (ConfigurationSection
section in source.Sections)
{
   //We
want to ensure that this guy came from the file we provided.. and not from say machine
config


   if (section.ElementInformation.Source
!=null &&
section.ElementInformation.Source.Equals(source.FilePath))
   {
      //Enumerator
is on AppSettings. So we update the appSettings


      if (section is AppSettingsSection)
      {
         foreach (KeyValueConfigurationElement
element in source.AppSettings.Settings)
         {
            target.AppSettings.Settings.Remove(element.Key);
            target.Save(ConfigurationSaveMode.Full, false);
            target.AppSettings.Settings.Add(element);
         }
       }
      //Enumerator
is on a custom section


      else

      {
         //Remove
from target and add from source. 


         target.Sections.Remove(section.SectionInformation.SectionName);
         //Just
paranoid.


         target.Save(ConfigurationSaveMode.Full, false);
         //Using
reflection to instantiate since no public ctor and the instance we hold is tied to
“Source”


         ConfigurationSection reflectedSection = Activator.CreateInstance(section.GetType()) as ConfigurationSection;
         reflectedSection.SectionInformation.SetRawXml(section.SectionInformation.GetRawXml());
         //Bug/Feature
in framework prevents target.Sections.Add(section.SectionInformation.Name, Section);


         target.Sections.Add(section.SectionInformation.Name,
reflectedSection);
      }
         ConfigurationManager.RefreshSection(section.SectionInformation.SectionName);
   }


 

>

 

Here is what the source looks like. It has one custom section and one appsettings
key value pair

<?xml
version=”1.0″ ?>
<configuration>
<configSections>
<section name=”MyCustomConfiguration” type=”Covarius.Configuration.MyCustomConfigurationSection,
Covarius.Configuration, Version=1.0.0.0, Culture=neutral, PublicKeyToken=147be6ea50c5d416″
/>

</configSections>
<MyCustomConfiguration ConfigValue=”C:\Test2.ini” MyURL=”http://webservices.covarius.dev/testservice.asmx”/>

<appSettings>
    <add key=”CustomConfig”
value=”c:\blahCon.config”/>
</appSettings>
</configuration>

That was easy wasnt it. I have attached a utility AppConfigUpdater.exe. So you can
use it as a deployment tool to update config in say QA or PROD. Syntax is AppConfigUpdater
<sourcefile> <targetfile>

Comments welcome.

Linus Joseph

 >
Download
AppConfiUpdater.exe (16 KB)