Tuesday, December 24, 2013

Converting Image File to Binary

There was required in one of project couple of months ago, wherein the image files have to be stored/inserted into the database using BizTalk.

Although we know that keeping files on folder location is much better than storing it in Database, we had to implement.

Note: BLOBs(Image files, Video files etc) smaller than 256KB are more efficiently handled by a database,while a filesystem is more efficient for those greater than 1MB. Of course, this will vary between different databases and filesystems.


It seemed to be challenging at the beginning, but was an interesting experience for me and my colleague  Dhiraj Bhavsar.

To achieve this, we came up with a solution of creating a Helper class which will convert the file into binary and later can be used .

Below is a screenshot  of Helper Class, which accepts a file path as input and returns data in bytes and deletes the file.





Note: This can used for other types of files also. 

Download Helper Class CodeFileReader - Helper Class to convert file into Bytes

Have composed an article as to how to insert images in SQL, have a look : BizTalk Server 2010: How to Insert Image In SQL Through Orchestration

Download BizTalk Server 2010: How to Insert Image In SQL Through Orchestration Sample 

Friday, December 20, 2013

Beginner To Expert: BizTalk Available Resources

Yesterday received a mail from a beginner in BizTalk asking about how to learn BizTalk . What are the resources which are available and can help the learning process.

There is a huge amount of resources available in the form of  Books, Videos, Tutorials , Blogs , Articles , Samples etc.  You can begin learning and if you are stuck somewhere or do not understand some concept, there are dedicated BizTalk forums wherein you can ask questions and I can guarantee that your question will be answered.

So if you are truly passionate about learning BizTalk then do utilize the available resources, and in case you are comfortable learning from some tutor then I guess there are online training providers which you can look at.
I personally feel that at last it will be your curiosity of knowing more and more about BizTalk which will help you. (It applies to learning other technologies as well)


Below are a few links which I would like to suggest to look at (Beginners should):

Microsoft BizTalk Server

BizTalk Server Tutorials

BizTalk Server 2010 Developer Training Kit

Microsoft BizTalk Server 2010 Help

How about seeing the samples and understanding how the implementations are done: BizTalk Server Code Gallery Samples

The most important resource which I feel personally is  BizTalk Server Resources on the TechNet Wiki (This is certainly a gateway to BizTalk World), it holds excellent articles written by MVP's, MCC's and BizTalk Community member from all over the world. It does contains lot of other links and resources which will help you in learning as well when you are working on some project.

Likewise there are many Community members who share their experiences via their blog, you can look out for those too.

Experts are the people who know how to implement the concept they know, so keep implementing. It will take time as BizTalk deals with many technologies and is very rich from that perspective.

So Keep BizTalking !!!!!!!!


Update: BizTalk Featured Downloads from Microsoft




Monday, December 16, 2013

Token StartElement in state Epilog would result in an invalid XML document.

In a project there was requirement to aggregate the responses, and for that I used SendPipeline in Orchestration.

Created a Envelope schema, imported the document schema and set the Body Xpath.

All was smooth, even the messages were consumed until the last one and following error appeared in the EventLog.


What was this about, tried many things but still haven't found the reason why this happened.

Finally thought of having look at the Aggregator Sample, all was almost same except one thing.

In the sample the Envelope schema has used <Any> element, so I did the same ( though I was not in harmony to use it) but it worked.

<Any> means to allow the elements which are not specified in schema, then why not elements specified in schema.

So now the question is , is this exceptional case or is there something else which should be considered?


Will try to dig more into it .... and will update with the finding!!!!!!!!!!

Saturday, November 16, 2013

Bronze Medal: TechNet Guru Awards - October 2013

Monday, November 11, 2013

Failed to add resource(s)

After completing my demo application , I build the project and then  deployed the project . But to my surprise the application wasn't listed , it was not showing up in the Applications (In BizTalk Admin Console).

Then what , I tried again deploying it (assuming that I didn't do it first time ;) ) and got a lovely error which did puzzled me for a minute i.e. Failed to add resource(s)...........





Cool, so what does this error says : Resource(....) is already in store and is either associated with another application or with another type.

So this means the application was deployed first time but why it didn't appeared under Applications.

The reason was , I had not specified the Application Name in Deployment Tab of Project properties.

Note: If no Application Name is specified then all the resources are deployed under the default Application of that Group(BizTalk Application1).

To fix this :
1. I removed the demo application resources from BizTalk Application 1
2. Provided name against the Application Name in Deployment Tab of Project properties
3. Deployed it
4. Now the Demo application is listed under Applications




Will keep on posting as an when I find something to share!!!!!!!!!!!!

Friday, October 25, 2013

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.

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

Will keep on posting as an when I find something to share!!!!!!!!!!!!

Promoting custom context property using Pipeline Component

While working on an application , there was requirement to route file based on the extension. But no context property holds that information .

To overcome this obstacle, I created a custom property and added it to Property schema and promoted it in custom pipeline component.After deploying the solution , this custom property was available in the filter options of Send Port.

How to do:

1.Open the project , add a property schema to it
2.Add the custom property and name it as per the purpose(I have used Extension as I need it to store extension of file).

3.Set  the Property Schema Base to MessageContextPropertyBase (this tells that the property is part of Message context)
4.Now in the custom pipeline component promote the field (this can be done in the disassembler component)


5. Now this property will be available in the filter as DemoZip.Extension

Will keep on posting as an when I find something to share!!!!!!!!!!!!

Friday, October 18, 2013

Adding GUID generator to Visual Studio 2010 Tools

While working on custom pipeline component , I had to create GUID for that particular component.

It's very easy ,

1. Go to Tools from Visual Studio Menu Bar
2. Select Create GUID 
3. Window will appear which gives options for creating New GUID , Copy and Exit
4. It allows to select the format out of four options



But, when I selected Tools - there was no Create GUID available. Well don't know why(if found reason - will update here)

Solution to this is to add the GUID generator to Tools.
1. Go to Tools from Visual Studio Menu Bar 
2. Select External Tools
3.Click on Add button



4.Give name to tool against the Title label(I have used GUID generator)
5.Next is provide Command, it is here where the path of guidgen.exe is provided.
6. Click on the ellipsis and browse to location"C:\Program Files\Microsoft SDKs\Windows\v7.0A\bin\guidgen.exe"
7.Click ok
8.Go to Tools from Visual Studio Menu Bar
9.Now you can see GUID Generator

Will keep on posting as an when I find something to share!!!!!!!!!!!!