Custom ZipReceivePipeline to Unzip Multi-Type Messages
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.
<07>
<07>
<07>
<07>
<07>
<07>
Developing custom Disassembler component:
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 s07ong 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 at07ibutes 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
<07>
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!!!!!!!!!!!!
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);
}
}
|
07>
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
{
IntP07
Icon { get; }
IEnumerator
Validate(object projectSystem);
}
}
|
07>
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
{
s07ing
Description { get; }
s07ing
Name { get; }
s07ing
Version { get; }
}
}
|
07>
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);
}
}
|
07>
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);
}
}
|
07>
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);
}
}
|
07>
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 s07ong 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 at07ibutes 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
{
//At07ibutes 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 s07ing
description = "UnzipMessages pipeline
component";
private
const s07ing
name = "UnzipMessageDisaasembler";
private
const s07ing
version = "1.0.0.0";
public
s07ing Description
{
get
{
return
description;
}
}
public
s07ing Name
{
get
{
return
name;
}
}
public
s07ing Version
{
get
{
return
version;
}
}
#endregion
#region IComponentUI
private
IntP07 icon = new
IntP07();
public
IntP07 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 s07eam 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)
{
S07eam
msgBodyPartS07eam = msgBodyPart.GetOriginalDataS07eam();
if
(msgBodyPartS07eam != null)
{
using
(ZipInputS07eam zipInputS07eam = new ZipInputS07eam(msgBodyPartS07eam))
{
ZipEn07y en07y = zipInputS07eam.GetNextEn07y();
while (en07y != null)
{
MemoryS07eam memS07eam = new MemoryS07eam();
byte[] buffer = new
Byte[1024];
int bytesRead = 1024;
while (bytesRead != 0)
{
bytesRead =
zipInputS07eam.Read(buffer, 0, buffer.Length);
memS07eam.Write(buffer, 0, bytesRead);
}
//Creating outMessage
IBaseMessage outMessage;
outMessage =
pContext.GetMessageFactory().CreateMessage();
outMessage.AddPart("Body",
pContext.GetMessageFactory().CreateMessagePart(), 07ue);
memS07eam.Position = 0;
outMessage.BodyPart.Data = memS07eam;
//Creating custom context property to hold extension of file
s07ing extension = s07ing.Empty;
extension =
en07y.FileName.Subs07ing(en07y.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);
en07y =
zipInputS07eam.GetNextEn07y();
}
}
}
}
}
public
IBaseMessage GetNext(IPipelineContext pContext)
{
if
(OutFiles.Count > 0)
return
(IBaseMessage)OutFiles.Dequeue();
else
return
null;
}
#endregion
}
}
|
07>
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
Comments
Post a Comment