Saturday, November 19, 2011

Exposed Orchestration as Web service returning void?

I was working on an Integration Scenario where we needed to call the BizTalk Orchestration from MS Access.
SO first thing started looking at how could we could send request from MS Access to Biztalk. We wanted a Synchronous Scenario where MS Access sends Request and waits for a Response.
The best option we had was to Expose the Orchestration as Webservice.
We did that and after googling we understood

  •  MS Access cannot consume a WCF Service.
  • To Comsume a BizTalk WCF Service we need to create a Proxy Class.
So finally we thought to settle down for normal SOAP Web-services and exposed our Orchestration as Soap Web-service.
It looked good but we planned to make it more easy to be called from MS Access we thought to have the Web-service Input/Output parameter as string.
So MS Access will send XML in string and get response XML i nstring object.

So we made the changes in Orchestration and republished the Orchestration as Webservice and tried to consume it from a WebService testing tool caleld WCF Strom.
The input was passed on and the Webservice returned void though in BizTalk I noticed that I am returning the right XML.

After googling I found this link where it says we need to fine tune the Webservice to work it out.

I made the changes in my Webservice created by the Webservice Publishing Wizard.

And finally got the Response as string.

Hope it helps you in working with Exposing Orchestration as Webservices.

Friday, September 16, 2011

Message as Mail Attachment?

How to send any message as a mail attachment?
  1. No need to create Multipart messages.
  2. No need to set any parameters.
Just set the Dynamic SendPort SMTP properties like.
UserName,Password,Hostname,To email address.
You can find more settings here

Important thing is using the Mime Encoder in the Send Pipeline if you want to send attachments.
It seems like I tried setting the property in Orchestration as
msgXmlDocumentOut(SMTP.MessagePartsAttachments) = 1;
It dint work.Finally I added the PipelineComponent and it worked fine. You can also set the FileName Overriding the Mime.FileName property as shown below.
public static void SetMimeFileName(Microsoft.XLANGs.BaseTypes.XLANGPart msgpart, string MimeFileName)
                msgpart.SetPartProperty(typeof(MIME.FileName), MimeFileName);

Saturday, September 3, 2011

Global Context Field which is independent of a Message

I was thinking of writing about a Context field which is independent of message. Imagine a Scenario where you would like to promote a field only for routing no matter what the incoming file content is, you know one thing for sure that there is a field in the content of the file(FF,XML,EDI) which has the data for routing to destination system. In this case it never makes sense to create a Schema and promote the field as Distinguished or Property field and only for routing you don’t even need to create an Orchestration.Message In….. MessageOut ….simple J
So I thought to show you how simple is it to do with BizTalk.
  1. Create a new BizTalk project and add a new Property Schema which will have our Global PropertySchema field.
  2. Let’s add a field called Property1 to this Property Schema. Set the PropertySchemaBase as MessageContextPropertybase. So by this we say that the field Property1 will not be dependent upon the message content or it won’t be linked to any field in the message. 
  3. This namespace below is important. This is the namespace in which this property field (Property1) will be promoted globally.
  4. Deploy the solution to BizTalk so our global property Schema is in BizTalk.
  5. You can promote this field from any pipeline or Orchestration as shown below. pInMsg.Context.Promote(“Property1”,"https://BizTalk_Server_Project3.PropertySchema1", "Test");
  6. If you want to access it from Orchestration then it’s important to know the .Net Namespace the property belongs to as shown below in the properties.
The Property field (Property1) can easily be accessed from the Orchestration with the .Net namespace. strProp=Msg_XmlDocumentIn(BizTalk_Server_Project3.Property1);
Simple enough…promotions are important as they can save lot of your design time to plan complex Integration's. Promotions can help you route any message from a ReceivePort to SendPort but I limit the use of such uncontrolled scenarios and use Orchestration as it gives me full control over the message for complex scenarios… ;) .

Wednesday, May 11, 2011

SQL Receive Adapter: Multiple tables in different Database

Last week I had a simple scenario where BizTalk Server will use a SQL Receive Adapter and poll a SQL Stored Procedure(SP) which will return the rows from multiple tables spread across 2 different database.
Initially I thought the only catch out here will be to grant rights across all tables for the same User Account with which Biztalk polls the SP. Following were the last 2 lines of my proc.
Select @ReturnXML
The SP worked perfect from SQL Query window but I started getting the following error when called by BizTalk SQL Receive Adapter.
Event ID: 5740
Description:The adapter "SQL" raised an error message. Details "HRESULT="0x      7a" Description="Description not provided"

I thought I am missing some access rights on the 'XYZ' table, I granted all possible rights for the user on the table but still the same issue. After struggling for 2 days I thought to concentrate only on what the SP returned in the last 2 lines shown above.I felt that BizTalk is having an issue with the data returned from SP as it wont care what you do in the SP.BizTalk is only interested in the results(rows) returned,So I removed the variable(@ReturnXML) and it worked. So SP now returns the SQL Query directly.

Hope it helps you.

Tuesday, May 3, 2011

BAM Portal Activity Search: "This action cannot be performed because one or more database(s) appears corrupted"

I noticed this error when I tried to search on an Activity in the BAM Portal.

I googled and noticed a good description about this issue by Gilles but it did not help me resolve the problem.

So I thought of fixing it in the BAM (BAMPrimaryImport)database as it clearly said about duplicate entry. I searched on the ActivityID and found only 1 record in "bam_ActivityName_active" table and I also found 1 record in the "bam_ActivityName_completed" Activity table.
SELECT * FROM [BAMPrimaryImport].dbo.bam_ActivityName_active where ActivityID='{42B99A00-4A43-40D4-8F6F-183851984197}'
So I thought that its not a duplicate issue as the Error says as I saw only 1 entry in each tables.
But I was wrong.

The issue is that there should not be any pending records in the Active tables if  the Activity is completed ie. if there exist a record in _Completed table for the same ActivityID.
In my case I intiated an Activity(BeginActivity) and Biztalk failed while updating the Actvity(UpdateActivity)and after that I completed the Activity(EndActivity). So there was an Orphan record in the _active table.
So I deleted all the records from _active table and it worked fine.
DELETE FROM [BAMPrimaryImport].dbo.bam_ActivityName_active

So this is what BizTalk means by Duplicate records.
"There should not be a record in the _active table if the activity has a record in the _completed table for the same ActivityID.If it exist then its a duplicate Error."

Error in Eventlog was as follows:
Event Type: Error
Event Source: BAM Portal
(BAMPortal.PortalApplication) Void LogAllErrors(System.Exception[]): System.Web.HttpUnhandledException: Exception of type 'System.Web.HttpUnhandledException' was thrown. ---> System.Web.Services.Protocols.SoapException: System.Web.Services.Protocols.SoapException: There are instances with duplicate ID '{42B99A00-4A43-40D4-8F6F-183851984197}' in activity 'xxx'. The duplicates must be removed from the database to fix this problem.
   at Microsoft.BizTalk.Bam.WebServices.Query.BamQueryService.GetInstanceData(String viewName, String activityName, InstanceQuery query, Int32 timeout)
   at System.Web.Services.Protocols.SoapHttpClientProtocol.ReadResponse(SoapClientMessage message, WebResponse response, Stream responseStream, Boolean asyncCall)
   at System.Web.Services.Protocols.SoapHttpClientProtocol.Invoke(String methodName, Object[] parameters)
   at Microsoft.BizTalk.Bam.WebServices.QueryService.BamQueryService.GetInstanceData(String viewName, String activityName, InstanceQuery query, Int32 timeout)
   at Microsoft.BizTalk.Bam.Portal.DataAccess.QueryResultsObjectDataSource.ExecuteQuery(SQLQuery query)
   at Microsoft.BizTalk.Bam.Portal.DataAccess.QueryResultsObjectDataSource.EnsureData(SQLQuery query)
   at Microsoft.BizTalk.Bam.Portal.DataAccess.QueryResultsObjectDataSource.QueryResults(SQLQuery query)
   at BAMPortal.Search_aspx.ExecuteQuery()
   at BAMPortal.Search_aspx.executeQueryButton_Click(Object sender, CommandEventArgs e)
   at System.Web.UI.WebControls.Button.OnCommand(CommandEventArgs e)
   at System.Web.UI.WebControls.Button.RaisePostBackEvent(String eventArgument)
   at System.Web.UI.WebControls.Button.System.Web.UI.IPostBackEventHandler.RaisePostBackEvent(String eventArgument)
   at System.Web.UI.Page.RaisePostBackEvent(IPostBackEventHandler sourceControl, String eventArgument)
   at System.Web.UI.Page.RaisePostBackEvent(NameValueCollection postData)
   at System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)
   --- End of inner exception stack trace ---
   at System.Web.UI.Page.HandleError(Exception e)
   at System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)
   at System.Web.UI.Page.ProcessRequest(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)
   at System.Web.UI.Page.ProcessRequest()
   at System.Web.UI.Page.ProcessRequestWithNoAssert(HttpContext context)
   at System.Web.UI.Page.ProcessRequest(HttpContext context)
   at ASP.pages_search_aspx.ProcessRequest(HttpContext context)
   at System.Web.HttpApplication.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()
   at System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously)

Happy Talking Biz. ;)

Thursday, April 21, 2011

MIME.FileName= "Blank" ??

While working on an Integration to receive a file via email as attachment we normally use POP3 Adapter and MIME Decoder enabled So that the MIME Context fields are filled in properly. I googled on how does the POP3 Adapter populates it. This link helped me understand it better.
BizTalk uses the following logic to get the file name:
1. Take it from the Content-Description header. Some vendors don't populate the Content-Description header in the message sent to Exchange.
2. If not found, then the part name is based on the Content-ID header.
3. If still not found, then generate a GUID for the part name.

In our Scenario MIME.FileName was blank and the reason was the Mail Header was missing "content-disposition" field for Attachments.
Actual Header:
content-type: application/octet-stream;
content-transfer-encoding: base64
Expected Header:
content-type: application/octet-stream;
content-transfer-encoding: base64
content-disposition: attachment;

Scott did shed some light on this issue out here
We had a discussion with the Vendor to populate content-disposition field for attachments in header but they were clear that their Mail Server guys will not accept this Change Request as the FileName is already available in ContentType field in the Mail header.Well actually the BizTalk MIME Decoder does populates it in "PartContentTypeSecondaryHeaderValue" .

So we handled it this way
filename = MIME.PartContentTypeSecondaryHeaderValue
I could not find much about this field.
Hope it helps you while working with FileNames in Mail Attachments.

Happy Integrating,