{tocify} $title={Table of Contents}
And in order to implement this interfaces , we need to use namespaces "Microsoft.BizTalk.Message.Interop","Microsoft.BizTalk.Component.Interop" which belong to "Microsoft.BizTalk.Pipeline.dll" assembly can be found at C:\Program Files\Microsoft BizTalk Server 2010\Microsoft.BizTalk.Pipeline.dll and also we need to use "Ionic.Zip" namespace which belongs to "Iconic.Zip" assembly can be downloaded from http://dotnetzip.codeplex.com/.There are many other Zip libraries available also.
After creating new C# project , we need to add reference to those assemblies and sign it with strong name .
Next is to add new class and implement the interfaces and along-with custom logic to unzip messages and promoting the extension of the unzipped files which can be used to route messages based on the extension.
To indicate that the component is custom pipeline component and can only be used in Disassemble stage, couple of attributes are added to the class.
GUID (global unique identifier) is to create a unique identity for an entity(component) have look at following post: Adding GUID generator to Visual Studio 2010 Tools.
To add a custom context property and promoting it in pipeline component , have look at following post: Promoting custom context property using Pipeline Component
Now build it and add it to gac.
Next is to copy the dll at location : C:\Program Files\Microsoft BizTalk Server 2010\Pipeline Components
Doing this makes this component available in the Pipeline Designer Tool Box.
Add new Receive pipeline and reset Toolbox - this will refresh Toolbox and custom component will be reflected. Drag and drop it in Disassemble stage. Build the project and deploy it.
ZipReceivePipeline is ready to use now.
See how to process Zip Files : BizTalk Server 2010: Processing Zip Message Having Multiple Type Files
Download Sample: BizTalk Server 2010: Processing Zip Message Having Multiple Type Files Sample
Will keep on posting as an when I find something to share!!!!!!!!!!!!
Introduction
Many times there are requirements where the default pipelines provided by BizTalk are not helpful , but we all know that BizTalk is capable of dealing with any type of message.
One such scenario is accepting the incoming message in zipped format which has XML files as well as image files, in this case we need to create a custom pipeline along with a custom disassembler which will unzip the incoming message and split the message into individual XML and Image files. Also a property should be promoted which is used for creating subscriptions and routing .
When we develop a custom pipeline component we actually need to implement the Interfaces IBaseComponent, IComponentUI and IPersistPropertyBag(optional) and IComponent. Depending on the requirement, custom logic is added to the required area.
Note: When creating Assemble or Disassemble component , IComponent interface is not implemented instead IAssemblerComponent interface and IDisassemblerComponent interface are implemented.
Wherein, this interfaces have properties and methods defined. Below are the interfaces showing the definitions it holds.
One such scenario is accepting the incoming message in zipped format which has XML files as well as image files, in this case we need to create a custom pipeline along with a custom disassembler which will unzip the incoming message and split the message into individual XML and Image files. Also a property should be promoted which is used for creating subscriptions and routing .
When we develop a custom pipeline component we actually need to implement the Interfaces IBaseComponent, IComponentUI and IPersistPropertyBag(optional) and IComponent. Depending on the requirement, custom logic is added to the required area.
Note: When creating Assemble or Disassemble component , IComponent interface is not implemented instead IAssemblerComponent interface and IDisassemblerComponent interface are implemented.
Wherein, this interfaces have properties and methods defined. Below are the interfaces showing the definitions it holds.
IComponent : It holds only one method i.e. Execute which returns message of type IBaseMessage which is expected by BizTalk Engine.
#region Assembly
Microsoft.BizTalk.Pipeline.dll, v2.0.50727
// C:\Program
Files\Microsoft BizTalk Server 2010\Microsoft.BizTalk.Pipeline.dll
#endregion
using
Microsoft.BizTalk.Message.Interop;
using System.Runtime.InteropServices;
namespace
Microsoft.BizTalk.Component.Interop
{
[Guid("05ac2001-2ed5-41f0-a961-2838a1836a22")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IComponent
{
IBaseMessage
Execute(IPipelineContext pContext, IBaseMessage pInMsg);
}
}
|
IComponentUI: It has definition of one property Icon which is used to represent Icon associated with the component and one method Validate which is used to validate the properties set in component.
#region Assembly
Microsoft.BizTalk.Pipeline.dll, v2.0.50727
// C:\Program
Files\Microsoft BizTalk Server 2010\Microsoft.BizTalk.Pipeline.dll
#endregion
using System;
using System.Collections;
using System.Runtime.InteropServices;
namespace
Microsoft.BizTalk.Component.Interop
{
[Guid("05ac2106-2ed5-41f0-a961-2838a1836a22")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IComponentUI
{
IntPtr
Icon { get; }
IEnumerator
Validate(object projectSystem);
}
}
|
IBaseComponent:It has three properties defined which defines the component properties i.e.Description,Name and Version which is visible in Properties tab of the component.
#region Assembly
Microsoft.BizTalk.Pipeline.dll, v2.0.50727
// C:\Program
Files\Microsoft BizTalk Server 2010\Microsoft.BizTalk.Pipeline.dll
#endregion
using System;
using System.Runtime.InteropServices;
namespace
Microsoft.BizTalk.Component.Interop
{
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
[Guid("05ac2000-2ed5-41f0-a961-2838a1836a22")]
public interface IBaseComponent
{
string
Description { get; }
string
Name { get; }
string
Version { get; }
}
}
|
IPersistPropertyBag: It has four methods defined which are used to set the properties of the component.
#region Assembly
Microsoft.BizTalk.Pipeline.dll, v2.0.50727
// C:\Program
Files\Microsoft BizTalk Server 2010\Microsoft.BizTalk.Pipeline.dll
#endregion
using System;
using System.Runtime.InteropServices;
namespace
Microsoft.BizTalk.Component.Interop
{
[Guid("37D84F60-42CB-11CE-8135-00AA004BB851")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IPersistPropertyBag
{
void
GetClassID(out Guid
classID);
void
InitNew();
void
Load(IPropertyBag propertyBag, int errorLog);
void
Save(IPropertyBag propertyBag, bool clearDirty, bool
saveAllProperties);
}
}
|
IAssemblerComponent: It has two methods defined AddDocument and Assemble.
#region Assembly
Microsoft.BizTalk.Pipeline.dll, v2.0.50727
// C:\Program
Files\Microsoft BizTalk Server 2010\Microsoft.BizTalk.Pipeline.dll
#endregion
using
Microsoft.BizTalk.Message.Interop;
using System;
using System.Runtime.InteropServices;
namespace
Microsoft.BizTalk.Component.Interop
{
[Guid("05ac2004-2ed5-41f0-a961-2838a1836a22")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IAssemblerComponent
{
void
AddDocument(IPipelineContext pContext, IBaseMessage pInMsg);
IBaseMessage
Assemble(IPipelineContext pContext);
}
}
|
IDisassemblerComponent: It has two methods defined , where Disassemble method is used to hold the custom logic and GetNext method is used to pass Message to BizTalk engine of IBaseMessageType.
#region Assembly
Microsoft.BizTalk.Pipeline.dll, v2.0.50727
// C:\Program
Files\Microsoft BizTalk Server 2010\Microsoft.BizTalk.Pipeline.dll
#endregion
using
Microsoft.BizTalk.Message.Interop;
using System;
using System.Runtime.InteropServices;
namespace
Microsoft.BizTalk.Component.Interop
{
[Guid("05ac2003-2ed5-41f0-a961-2838a1836a22")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IDisassemblerComponent
{
void
Disassemble(IPipelineContext pContext, IBaseMessage pInMsg);
IBaseMessage
GetNext(IPipelineContext pContext);
}
}
|
Developing custom Disassembler component:
In this case as we are developing disassembler component which will unzip the message and promote the property which will hold the extension of files which are unziped so following interfaces are to be implemented IBaseComponent, IComponentUI, IPersistPropertyBag and IDisassemblerComponent.
And in order to implement this interfaces , we need to use namespaces "Microsoft.BizTalk.Message.Interop","Microsoft.BizTalk.Component.Interop" which belong to "Microsoft.BizTalk.Pipeline.dll" assembly can be found at C:\Program Files\Microsoft BizTalk Server 2010\Microsoft.BizTalk.Pipeline.dll and also we need to use "Ionic.Zip" namespace which belongs to "Iconic.Zip" assembly can be downloaded from http://dotnetzip.codeplex.com/.There are many other Zip libraries available also.
After creating new C# project , we need to add reference to those assemblies and sign it with strong name .
Next is to add new class and implement the interfaces and along-with custom logic to unzip messages and promoting the extension of the unzipped files which can be used to route messages based on the extension.
To indicate that the component is custom pipeline component and can only be used in Disassemble stage, couple of attributes are added to the class.
GUID (global unique identifier) is to create a unique identity for an entity(component) have look at following post: Adding GUID generator to Visual Studio 2010 Tools.
To add a custom context property and promoting it in pipeline component , have look at following post: Promoting custom context property using Pipeline Component
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using
Microsoft.BizTalk.Message.Interop;
using
Microsoft.BizTalk.Component.Interop;
using Ionic.Zip;
namespace UnzipMessages
{
//Attributes of class
[ComponentCategory(CategoryTypes.CATID_PipelineComponent)]
[ComponentCategory(CategoryTypes.CATID_DisassemblingParser)]
//Generate unique identifier
[System.Runtime.InteropServices.Guid("9ABA4232-1F8E-4a45-B12D-9BE50160464B")]
public class UnzipMessageDisassembler:IBaseComponent,
IComponentUI,
IDisassemblerComponent,
IPersistPropertyBag,
{
//Implementing
Interfaces
#region IBaseComponent
private
const string
description = "UnzipMessages pipeline
component";
private
const string
name = "UnzipMessageDisaasembler";
private
const string
version = "1.0.0.0";
public
string Description
{
get
{
return
description;
}
}
public
string Name
{
get
{
return
name;
}
}
public
string Version
{
get
{
return
version;
}
}
#endregion
#region IComponentUI
private
IntPtr icon = new
IntPtr();
public
IntPtr Icon
{
get
{
return
icon;
}
}
public
System.Collections.IEnumerator Validate(object projectsystem)
{
return
null;
}
#endregion
#region IPersistPropertyBag
public
void GetClassID(out
Guid classid)
{
classid = new System.Guid("9ABA4232-1F8E-4a45-B12D-9BE50160464B");
}
public
void InitNew()
{
}
public
void Load(IPropertyBag
propertyBag, int errorlog)
{
}
public
void Save(IPropertyBag
propertyBag, bool clearDirty, bool saveAllProperties)
{
}
#endregion
#region IDisassemblerComponent
// This component will read the zipped input message as a stream and with the help //of Zip library the message will unzipped and stored in the Queue.
private
System.Collections.Queue OutFiles = new System.Collections.Queue();
public
void Disassemble(IPipelineContext
pContext, IBaseMessage pInMsg)
{
IBaseMessagePart
msgBodyPart = pInMsg.BodyPart;
if
(msgBodyPart != null)
{
Stream
msgBodyPartStream = msgBodyPart.GetOriginalDataStream();
if
(msgBodyPartStream != null)
{
using
(ZipInputStream zipInputStream = new ZipInputStream(msgBodyPartStream))
{
ZipEntry entry = zipInputStream.GetNextEntry();
while (entry != null)
{
MemoryStream memStream = new MemoryStream();
byte[] buffer = new
Byte[1024];
int bytesRead = 1024;
while (bytesRead != 0)
{
bytesRead =
zipInputStream.Read(buffer, 0, buffer.Length);
memStream.Write(buffer, 0, bytesRead);
}
//Creating outMessage
IBaseMessage outMessage;
outMessage =
pContext.GetMessageFactory().CreateMessage();
outMessage.AddPart("Body",
pContext.GetMessageFactory().CreateMessagePart(), true);
memStream.Position = 0;
outMessage.BodyPart.Data = memStream;
//Creating custom context property to hold extension of file
string extension = string.Empty;
extension =
entry.FileName.Substring(entry.FileName.IndexOf("."));
//Promoting the custom property
pInMsg.Context.Promote("Extension",
"https://DemoZip.ZipMessageProperties",
extension);
outMessage.Context
= PipelineUtil.CloneMessageContext(pInMsg.Context);
//Add outMessage to queue
OutFiles.Enqueue(outMessage);
entry =
zipInputStream.GetNextEntry();
}
}
}
}
}
public
IBaseMessage GetNext(IPipelineContext pContext)
{
if
(OutFiles.Count > 0)
return
(IBaseMessage)OutFiles.Dequeue();
else
return
null;
}
#endregion
}
}
|
Now build it and add it to gac.
Next is to copy the dll at location : C:\Program Files\Microsoft BizTalk Server 2010\Pipeline Components
Doing this makes this component available in the Pipeline Designer Tool Box.
Add new Receive pipeline and reset Toolbox - this will refresh Toolbox and custom component will be reflected. Drag and drop it in Disassemble stage. Build the project and deploy it.
ZipReceivePipeline is ready to use now.
See how to process Zip Files : BizTalk Server 2010: Processing Zip Message Having Multiple Type Files
Download Sample: BizTalk Server 2010: Processing Zip Message Having Multiple Type Files Sample
If you have questions or suggestions, feel free to do in comments section below !!!
Do share if you find this helpful .......
Knowledge Sharing is Caring !!!!!!
Related Post
- BizTalk Server: Multiple XML files to Single FlatFile Using File Adapter
- BizTalk 2013: Inserting RawXML (Whole Incoming XML Message) in SQL database
- BizTalk 2013: Inserting RawXML (Whole Incoming XML Message) in SQL database - Part 2
- Is it possible to have Map Chaining on the Port Level
- Promoting custom context property using Pipeline Component
- Custom ZipReceivePipeline to Unzip Multi-Type Messages
- Grouping and debatching Inbound Messages from WCF SQL Adapter - BizTalk 2010
- Polling data from SQL using WCF-SQL Adapter in BizTalk 2010 - TypedPolling(From Multiple table)
- Grouping XML Messages using custom XSLT- BizTalk 2010
- Insert Records in SQL Server using WCF-SQL Adapter in BizTalk 2010 - Composite operation(Multiple Records insertion)
- Insert Records in SQL Server using WCF-SQL Adapter in BizTalk 2010- Composite Operation (Message Transformation Pattern)
- Debatching(Splitting) XML Message - BizTalk 2010
- Debatching(Splitting) XML Message in Orchestration using DefaultPipeline - BizTalk 2010
- BizTalk Server: Multiple XML files to Single FlatFile Using File Adapter
- BizTalk 2013: Inserting RawXML (Whole Incoming XML Message) in SQL database
- BizTalk 2013: Inserting RawXML (Whole Incoming XML Message) in SQL database - Part 2
- Is it possible to have Map Chaining on the Port Level
- Promoting custom context property using Pipeline Component
- Custom ZipReceivePipeline to Unzip Multi-Type Messages
- Grouping and debatching Inbound Messages from WCF SQL Adapter - BizTalk 2010
- Polling data from SQL using WCF-SQL Adapter in BizTalk 2010 - TypedPolling(From Multiple table)
- Grouping XML Messages using custom XSLT- BizTalk 2010
- Insert Records in SQL Server using WCF-SQL Adapter in BizTalk 2010 - Composite operation(Multiple Records insertion)
- Insert Records in SQL Server using WCF-SQL Adapter in BizTalk 2010- Composite Operation (Message Transformation Pattern)
- Debatching(Splitting) XML Message - BizTalk 2010
- Debatching(Splitting) XML Message in Orchestration using DefaultPipeline - BizTalk 2010
Tags:
BizTalk