Saturday, September 06, 2008

Multiple Flat File Schemas Disassembler

The problem with Flat File Disassembler is that doesn't allow multiple Document Schemas as XML Disassembler does.

In the BizTalk SDK, there is a sample pipeline component that allows this feature (see the project inside \Microsoft BizTalk Server 2006\SDK\Samples\Pipelines\SchemaResolverComponent\SchemaResolverFlatFileDasm), but this component only recognizes different documents if them have a Tag Identifier in the first two characters.

My problem was a bit different. The difference between documents is in a concrete position:

DOCUMENT DATA MESSAGE TYPE 65 DOCUMENT DETAIL

The info about wich is the flat file schema is inside the message (in previous sample, was 65 the identifier).

I have modified the SDK sample Pipeline Component to select the correct schema with the info inside the different messages.

First of all, I added two new properties: StartPosition and ReadLength. StartPosition indicates where the identifier characters starts. ReadLength is the identifier's length.
private int startPosition = 0;
private int readLength = 0;

public int StartPosition
{
get
{
return startPosition;
}
set
{
startPosition = value;
}
}

public int ReadLength
{
get
{
return readLength;
}
set
{
readLength = value;
}
}
Second step is to implement the IPersistPropertyBag, to save and load this properties:
public void Load(IPropertyBag propertyBag, int errorLog)
{
object property = null;

propertyBag.Read("StartPosition", out property, errorLog);
if (property != null)
StartPosition = (int)property;

propertyBag.Read("ReadLength", out property, errorLog);
if (property != null)
ReadLength = (int)property;
}

public void Save(IPropertyBag propertyBag, bool clearDirty, bool saveAllProperties)
{
object ptrVar = StartPosition;
propertyBag.Write("StartPosition", ref ptrVar);
ptrVar = ReadLength;
propertyBag.Write("ReadLength", ref ptrVar);
}
Third and last step is modify the Probe method, that reads the message stream, at the StartPosition position ReadLength characters:
public bool Probe(IPipelineContext pContext, IBaseMessage pInMsg)
{
if (null == pContext)
throw new ArgumentNullException("pContext");

if (null == pInMsg)
throw new ArgumentNullException("pInMsg");

if (null == pInMsg.BodyPart || null == pInMsg.BodyPart.GetOriginalDataStream())
return false;

ReadOnlySeekableStream stream = new ReadOnlySeekableStream(pInMsg.BodyPart.GetOriginalDataStream());
Stream sourceStream = pInMsg.BodyPart.GetOriginalDataStream();

if (!sourceStream.CanSeek)
{
ReadOnlySeekableStream seekableStream = new ReadOnlySeekableStream(sourceStream);

pInMsg.BodyPart.Data = seekableStream;

sourceStream = pInMsg.BodyPart.Data;
}

long position = sourceStream.Position;

char[] identifier = new char[ReadLength];
try
{
StreamReader reader = new StreamReader(sourceStream);
reader.BaseStream.Position = StartPosition;
if (reader.Read(identifier, 0, identifier.Length) < identifier.Length)
return false;

}
finally
{
sourceStream.Position = position;
}

string messageType = GetMessageType(new string(identifier));

if (null == messageType)
return false;

IDocumentSpec documentSpec = pContext.GetDocumentSpecByType(messageType);

pInMsg.Context.Write(DOCUMENT_SPEC_NAME_PROPERTY_NAME, XML_NORM_NAMESPACE_URI, documentSpec.DocSpecStrongName);

return disassembler.Probe(pContext, pInMsg);
}
At last, GetMessageType method in SDK sample, hard-coded the schemas DocumentSpec. We can modify this method to retrieve this information from a config file or SSO as config store.

Microsoft announced BizTalk Server 2009

Today Microsoft announced and updated Roadmap for BizTalk Server, including the BizTalk Server 2009 (BizTalk Server 2006 R3) release.

This is a summary of new features announced for this new realease:

* Service Oriented Architecture and Web Services:

- New Web Services Registry: BizTalk Server 2009 includes an UDDI 3.0 registry.
- New Adapters: Oracle E-Business Suites and SQL Server.
- Host Systems Integration: new WCF WebSphere MQ channel to integrate directly with WebSphere MQ via WCF.
- Enhanced Business Activity Monitoring
- Enhanced Enterprise Service Bus Guidance: new features and guidance for applying ESB usage patterns.

* Business to Business Integration:

- Updated SWIFT Support: including an extensibility to support SEPA Routing.
- Enhanced Support for EDI and AS2 Protocols

* Updated Platform Support:

- New Application Platform Support: BizTalk Server 2009 supports the latest Microsoft platform technologies (Windows Server 2008, Visual Studio 2008 SP1, SQL Server 2008 and .NET Framework 3.5 SP1).
- New Hyper-V Virtualization Support
- Improved Failover Clustering

* Device Connectivity:

- New Mobile RFID Platform and device management
- New RFID industry standards support

* Developer and Team Productivity:

- New Application Lifecycle Management (ALM) support: support for Team Foundation Server.
- Enhanced Developer Productivity: improvements in Visual Studio based BizTalk project for debugging maps, pipeline components and XLANG Orchestrations.

* Other Enhancements:

- Messaging: support for recoverable interchange processing for disassembly and validation stage. WCF adapter has been enhanced to provide support for configurable transactions.
- Administration: new query types for tracked message events and tracked service events.

Detailed information in Microsoft BizTalk Server Roadmap.

Thursday, August 28, 2008

Exchange 2007 Web Services (III): Update a calendar item (UpdateItem)

In my previous post, I explained how create a calendar item with an extended property and how find this calendar item by the extended property.

In this post, I will explain how to update this calendar item, modifying the appointment's End datetime.

This is the commented code:


public void UpdateAppointment(CalendarItemType calendarItem)
{
try
{
// Delegate to accept server certificate
ServicePointManager.ServerCertificateValidationCallback =
delegate(Object obj, X509Certificate certificate, X509Chain chain, SslPolicyErrors errors)
{
return true;
};

// Init Web Service Instance
ExchangeServiceBinding ewsService = new ExchangeServiceBinding();

// Set credentials and URL
ewsService.Credentials = new NetworkCredential("user", "qwerty", "DOMAIN");
ewsService.Url = @"https://server.domain.com/ews/exchange.asmx";

// If we need pass through a proxy
ewsService.Proxy = new WebProxy("proxy.domain.com", true);
ewsService.Proxy.Credentials = System.Net.CredentialCache.DefaultCredentials;

// Exchange properties
ewsService.RequestServerVersionValue = new RequestServerVersion();
ewsService.RequestServerVersionValue.Version = ExchangeVersionType.Exchange2007_SP1;

// Initialize the instance to pass to the web service method
UpdateItemType updateItem = new UpdateItemType();
updateItem.ItemChanges = new ItemChangeType[1];
updateItem.ItemChanges[0] = new ItemChangeType();

// Set the Calendar Item's ID (the item wich will be updated)
updateItem.ItemChanges[0].Item = calendarItem.ItemId;
updateItem.ItemChanges[0].Updates = new ItemChangeDescriptionType[1];

// The instance to modify the End property
SetItemFieldType setCalendarEnd = new SetItemFieldType();

// The path to the End property
PathToUnindexedFieldType calendarEndPath = new PathToUnindexedFieldType();
calendarEndPath.FieldURI = UnindexedFieldURIType.calendarEnd;

// The new End property's value
CalendarItemType calendarEndItem = new CalendarItemType();
calendarEndItem.End = new DateTime(2008, 08, 28, 17, 00, 00);
// If no -> ErrorIncorrectUpdatePropertyCount
calendarEndItem.EndSpecified = true;

setCalendarEnd.Item = calendarEndPath;
setCalendarEnd.Item1 = calendarEndItem;

updateItem.ItemChanges[0].Updates[0] = setCalendarEnd;

// This property is required in the UpdateItem method, when we update calendar items
updateItem.SendMeetingInvitationsOrCancellations = CalendarItemUpdateOperationType.SendToNone;
updateItem.SendMeetingInvitationsOrCancellationsSpecified = true;

// Invoke the web service method
UpdateItemResponseType response = ewsService.UpdateItem(updateItem);

// Get the response
UpdateItemResponseMessageType updateItemResponse =
(UpdateItemResponseMessageType)response.ResponseMessages.Items[0];

// Check the result
if (updateItemResponse.ResponseClass != ResponseClassType.Success)
{
// An error occurs
Console.Out.WriteLine("[UPDATE ITEM RESULTS]");
Console.Out.WriteLine(updateItemResponse.ResponseClass);
Console.Out.WriteLine(updateItemResponse.ResponseCode);
Console.Out.WriteLine(updateItemResponse.MessageText);
}
else
{
// No error
Console.Out.WriteLine("[UPDATE ITEM RESULTS]");
Console.Out.WriteLine(updateItemResponse.ResponseClass);
Console.Out.WriteLine(updateItemResponse.ResponseCode);
}
}
catch (Exception ex)
{
// An unexpected error
string message = ex.Message;
Console.Out.WriteLine(string.Format("Unexpected error...{0}", message));
}
}
Pay attention to this line:

calendarEndItem.End = new DateTime(2008, 08, 28, 17, 00, 00);
calendarEndItem.EndSpecified = true;

If we don't set EndSpecified property, we will receive a confusing error code: ErrorIncorrectUpdatePropertyCount.

Exchange 2007 Web Services (II): Find a calendar item by an Extended Property (FindItem)

In my previous post, I explained how to create a calendar item in Exchange 2007 through Exchange Web Services (EWS) with an extended property (NetShowUrl).

In this post, I will show you, how to find this calendar item by this property.

Here is the commented code:


public CalendarItemType FindAppointment(String filterValue)
{
try
{
// Delegate to accept server certificate
ServicePointManager.ServerCertificateValidationCallback =
delegate(Object obj, X509Certificate certificate, X509Chain chain, SslPolicyErrors errors)
{
return true;
};

// Init Web Service Instance
ExchangeServiceBinding ewsService = new ExchangeServiceBinding();

// Set credentials and URL
ewsService.Credentials = new NetworkCredential("user", "qwerty", "DOMAIN");
ewsService.Url = @"https://server.domain.com/ews/exchange.asmx";

// If we need pass through a proxy
ewsService.Proxy = new WebProxy("proxy.domain.com", true);
ewsService.Proxy.Credentials = System.Net.CredentialCache.DefaultCredentials;

// Set Exchange properties
ewsService.RequestServerVersionValue = new RequestServerVersion();
ewsService.RequestServerVersionValue.Version = ExchangeVersionType.Exchange2007_SP1;

// Initialize the instance to pass to the web service method
FindItemType item = new FindItemType();

// Set the Calendary folder to save the item
DistinguishedFolderIdType[] folders = new DistinguishedFolderIdType[1];
folders[0] = new DistinguishedFolderIdType();
folders[0].Id = DistinguishedFolderIdNameType.calendar;
// If we need to find the another's user item
//folders[0].Mailbox = new EmailAddressType();
//folders[0].Mailbox.EmailAddress = "user1@example.com";
item.ParentFolderIds = folders;

// Extended Property by we do the search
PathToExtendedFieldType netShowUrlPath = new PathToExtendedFieldType();
Guid mapiGuid = new Guid("{00062002-0000-0000-C000-000000000046}");
netShowUrlPath.PropertySetId = mapiGuid.ToString ("D");
netShowUrlPath.PropertyId = 0x8248; // NetShowUrl
netShowUrlPath.PropertyIdSpecified = true;
netShowUrlPath.PropertyType = MapiPropertyTypeType.String;

// To get this extra property to in our search
PathToUnindexedFieldType datetimestampPath = new PathToUnindexedFieldType();
datetimestampPath.FieldURI = UnindexedFieldURIType.calendarDateTimeStamp;

// We set wich properties we want
item.ItemShape = new ItemResponseShapeType();
item.ItemShape.BaseShape = DefaultShapeNamesType.AllProperties;
item.ItemShape.AdditionalProperties = new BasePathToElementType[2];
item.ItemShape.AdditionalProperties[0] = netShowUrlPath;
item.ItemShape.AdditionalProperties[1] = datetimestampPath;

// The Filter
item.Restriction = new RestrictionType();
IsEqualToType filterNetShowUrl = new IsEqualToType();
filterNetShowUrl.FieldURIOrConstant = new FieldURIOrConstantType();
FieldURIOrConstantType netShowUrlConstanType = new FieldURIOrConstantType();
ConstantValueType netShowUrlConstantValueType = new ConstantValueType();
netShowUrlConstantValueType.Value = filterValue;
netShowUrlConstanType.Item = netShowUrlConstantValueType;
filterNetShowUrl.Item = netShowUrlPath;
filterNetShowUrl.FieldURIOrConstant = netShowUrlConstanType;
item.Restriction.Item = filterNetShowUrl;

// Invoke the web service method
FindItemResponseType response = ewsService.FindItem (item);

// Get the response
FindItemResponseMessageType findItemResponse =
(FindItemResponseMessageType)response.ResponseMessages.Items[0];

// Check the result
if (findItemResponse.ResponseClass != ResponseClassType.Success)
{
// An error occurs
Console.Out.WriteLine("[FIND ITEM RESULTS]");
Console.Out.WriteLine(findItemResponse.ResponseClass);
Console.Out.WriteLine(findItemResponse.ResponseCode);
Console.Out.WriteLine(findItemResponse.MessageText);

return null;
}
else
{
// Get the first item
ArrayOfRealItemsType arrayItems = (ArrayOfRealItemsType)findItemResponse.RootFolder.Item;
CalendarItemType appointmentItem = (CalendarItemType)arrayItems.Items[0];

// Print the item's info
Console.Out.WriteLine("[FIND ITEM RESULTS]");
Console.Out.WriteLine(appointmentItem.Start);
Console.Out.WriteLine(appointmentItem.End);
Console.Out.WriteLine(appointmentItem.Subject);
Console.Out.WriteLine(appointmentItem.Location);
Console.Out.WriteLine(appointmentItem.DateTimeStamp.ToUniversalTime().ToString());

// Return the Item
return appointmentItem;
}
}
catch (Exception ex)
{
// An unexpected error
string message = ex.Message;
Console.Out.WriteLine(string.Format("Unexpected error...{0}", message));
return null;
}
}

Exchange 2007 Web Services (I): Create a calendar item with an Extended Property (CreateItem)

Here is my code sample to create an appointment item in Exchange 2007 throug Exchange Web Services (EWS), using the CreateItem method. It's commented, I hope that is sufficient to explain how to use this Exchange 2007 feature.

Also, in this sample, I explain how to add an Extended Property to our calendar item (in next post, I'll show you how to find this calendar item through this Extended Property):


public void CreateAppointment(DateTime fecha)
{
try
{
// Delegate to accept server certificate ServicePointManager.ServerCertificateValidationCallback =
delegate(Object obj, X509Certificate certificate, X509Chain chain, SslPolicyErrors errors)
{
return true;
};

// Init Web Service Instance
ExchangeServiceBinding ewsService = new ExchangeServiceBinding();

// Set credentials and URL
ewsService.Credentials = new NetworkCredential("User", "qwerty", "DOMAIN");
ewsService.Url = @"https://server.domain.com/ews/exchange.asmx";
// If we need pass through a proxy
ewsService.Proxy = new WebProxy("proxy.domain.com", true);
ewsService.Proxy.Credentials = System.Net.CredentialCache.DefaultCredentials;

// Create the appointment instance
CalendarItemType appointmentItem = new CalendarItemType();

// Set Start and End Properties
appointmentItem.Start = DateTime.Now.AddHours(-1);
appointmentItem.End = DateTime.Now.AddHours(1);

// Set Location
appointmentItem.Location = "Meeting point";

// Set the Subject
appointmentItem.Subject = "Talk about Exchange 2007";

// Set the Appointment's Body
appointmentItem.Body = new BodyType();
appointmentItem.Body.BodyType1 = BodyTypeType.Text;
appointmentItem.Body.Value = "Esto es una cita de prueba.";

// According to previous Exchange's versions
appointmentItem.ItemClass = "IPM.Appointment";

// We set an extra property
appointmentItem.DateTimeStamp = fecha;

// We set an Extended Property (NetShowUrl)
appointmentItem.ExtendedProperty = new ExtendedPropertyType[1];
appointmentItem.ExtendedProperty[0] = new ExtendedPropertyType();
PathToExtendedFieldType pathNetShowUrl = new PathToExtendedFieldType();
Guid mapiGuid = new Guid("{00062002-0000-0000-C000-000000000046}");
pathNetShowUrl.PropertySetId = mapiGuid.ToString ("D");
pathNetShowUrl.PropertyId = 0x8248;
pathNetShowUrl.PropertyIdSpecified = true;
pathNetShowUrl.PropertyType = MapiPropertyTypeType.String;
appointmentItem.ExtendedProperty[0].ExtendedFieldURI = pathNetShowUrl;
appointmentItem.ExtendedProperty[0].Item = "My NetShowUrl Property value";

// Initialize the instance to pass to the web service method
CreateItemType item = new CreateItemType();

// We add our appointment item to the parameters
item.Items = new NonEmptyArrayOfAllItemsType();
item.Items.Items = new ItemType[1];
item.Items.Items[0] = appointmentItem;

// Set the Calendary folder to save the item
DistinguishedFolderIdType calendarFolder = new DistinguishedFolderIdType();
calendarFolder.Id = DistinguishedFolderIdNameType.calendar;
calendarFolder.Mailbox = new EmailAddressType();
item.SavedItemFolderId = new TargetFolderIdType();
item.SavedItemFolderId.Item = calendarFolder;

// Set if we need to send to appointment's people and invitation
// (Required Property in CalendarItem)
item.SendMeetingInvitations = CalendarItemCreateOrDeleteOperationType.SendToNone;
item.SendMeetingInvitationsSpecified = true;

// Invoke the web service method
CreateItemResponseType response = ewsService.CreateItem(item);

// Get the response
ItemInfoResponseMessageType itemInfoResponse =
(ItemInfoResponseMessageType)response.ResponseMessages.Items[0];

// Check the result
if (itemInfoResponse.ResponseClass != ResponseClassType.Success)
{
// An error occurs
Console.Out.WriteLine("[CREATE ITEM RESULTS]");
Console.Out.WriteLine(itemInfoResponse.ResponseClass);
Console.Out.WriteLine(itemInfoResponse.ResponseCode);
Console.Out.WriteLine(itemInfoResponse.MessageText);
}
else
{
// No error
Console.Out.WriteLine("[CREATE ITEM RESULTS]");
Console.Out.WriteLine(itemInfoResponse.ResponseClass);
Console.Out.WriteLin(itemInfoResponse.ResponseCode);
}
}
catch (Exception ex)
{
// An unexpected error
string message = ex.Message;
Console.Out.WriteLine (string.Format("Unexpected error...{0}", message));
}
}

Thursday, August 21, 2008

New version of NDoc (NDoc3)

After NDoc, a new version of this code documentation generation tool is developed to support C# 2.0 and 3.0, is NDoc3.

At this moment, is a Beta version, but it works with a few bugs.

The project page is http://sourceforge.net/projects/ndoc3/.

Tuesday, August 19, 2008

Map Error - The map contains a reference to a schema node that is not valid

Yesterday, developing a map, I received this error:


Exception Caught: The map contains a reference to a schema node that is not valid.
Perhaps the schema has changed.
Try reloading the map in the BizTalk Mapper.
The XSD XPath of the node is:


The problem is including or importing Schemas in other Schema. I don't know the reason, I'm studiyng this error, when I have an explanation, I will write a new post with the fix.

Thursday, August 07, 2008

Publishing Orchestrations/Schemas as Web Services: "[System.Xml.Schema.XmlSchemaException] The content type of the base type must not be a simple..."

If we publish an Orchestration/Schema as Web Service and receive:

Unable to load assembly. ''[System.Xml.Schema.XmlSchemaException] The content type of the base type must not be a simple type definition.


If we are publishing schemas, we will have to validate the schema.

If we are publishing orchestrations, we will have to validate the schemas of the messages that we receive or send by the orchestration ports and validate that the xsd are correct.

We can check our XSDs at W3C.

BizTalk Mapper - Specific Namespace Prefix

By default, BizTalk Maps generates the output xml files with ns0, ns1, ns2, ... namespace prefix. If we need to set this prefixes to a specific value, we will have to use the map's "Custom XSL Path" property by following these steps:

1) We validate our current Map (the original map, that generates ns0, ... prefixes) -> Right Click on Map File and select "Validate Map".

2) We get the generated XSL file. The path is in the Results Panel:
The output XSLT is stored in the following file: <file:///C:\Documents and Settings\F1504\Configuración local\Temp\_MapData\CsvEntrada2XmlCache.xsl>

3) We change the namespace values in the generated XSL file, finding and replacing "ns0:" to whatever we want.

4) We add a new map to our Project, with source and destination schemas the same as out original map.

5) We set "Custom XSL Path" property in our new map, selecting the XSLT file that previously we have modified.

Tuesday, July 08, 2008

New features in VSTS "Rosario": Architecture Explorer And Class Dependencies

Architecture Explorer is a WPF interface that allows us to explore our solution. To open Architecture Explorer, we only have to select Architecture Explorer on View menu.

In my previous post, I use Architecture Explorer to generate a Sequence Diagram. Now I go to explain how to see all class dependencies inside our solution.

I added to my sample project, a new class FormatMessage, that modify the returned message from HelloWorld class.

The code in my form (Form1) when I click the submit button is:

Private Sub btnSubmit_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnSubmit.Click
Dim helloClass As New HelloWorld(txtName.Text)
Dim formatMessage As New FormatMessage(helloClass.SayHello())
lblHelloName.Text = formatMessage.CustomMessage()
End Sub

My class Form1 has dependencies with HelloWorld class and with FormatMessage class. We can see this dependencies from the Architecture Explorer:

Click on View -> Architecture Explorer menu and choose:

Column 1) "TestingSequenceDiagrams" Solution
Column 2) Contains
Column 3) "TestingSequenceDiagrams" Project
Column 4) Contains
Column 5) "Form1", "HelloWorld" and "FormatMessage"

And the result is...

From this diagram, I can navigate through the code, clicking the class shapes.

Saturday, July 05, 2008

New features in VSTS "Rosario": UML Sequence Diagram

I have download the April 2008 CTP Visual Studio Team System Code Name "Rosario" VPC Image to test the new features.
In this article I will talk about the Sequence Diagram feature. In VSTS "Rosario" we can either create a sequence diagram from scratch and generate the associated code or we can write our code and using reverse-engineer to generate our sequence diagram.

For example, I write a sample solution "TestingSequenceDiagrams" with a project "TestingSequenceDiagrams" with a typical "Hello World" windows form application with a form (Form1), a button (btnSubmit), a textbox (txtName), a label (lblHelloName) and a HelloWorld class with a SayHello function. The btnSubmit click event code is:

Private Sub btnSubmit_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnSubmit.Click
Dim helloClass As New HelloWorld(txtName.Text)
lblHelloName.Text = helloClass.SayHello()
End Sub

Next, I add a new blank sequence diagram: Right button at the project element -> Add -> New Item... -> Common Items -> General -> Sequence Diagram.

Next step is going to View -> Architecture Explorer menu and choose:

Column 1) "TestingSequenceDiagrams" Solution
Column 2) Contains
Column 3) "TestingSequenceDiagrams" Project
Column 4) Contains
Column 5) "Form1"
Column 6) Contains
Column 7) "btnSubmit_Click"
Column 8) Insert into Active Diagram

And the result is the btnSubmit_Click method sequence diagram...


Thursday, June 26, 2008

Publishing Schemas as Web Services: "This invalid type may be from a property schema"

Few days ago, I was trying to publish a schema as a Web Service through BizTalk Web Services Publishing Wizard. When I tried to test this Web Service through a Xml Validation pipeline, I received the error "This invalid type may be from a property schema":

This error is due the fact that the BizTalk Web Services Publishing Wizard sets the DocumentSpecName when invokes the web method. My problem was, that my schema had two root nodes and BizTalk Web Services Publishing Wizard don't set in DocumentSpecName the root node:

string bodyTypeAssemblyQualifiedName = "Company.ESB.PC02._02.SOAPService_company_es_ConectorWS_servi" + "ces_SN627003, Company.ESB.PC02.02, Version=1.0.0.0, Culture=neutral, Public" + "KeyToken=9431070526ed7a05";

There are two approaches to resolve this problem:

1) Set the root node in the Web Service:

string bodyTypeAssemblyQualifiedName = "Company.ESB.PC02._02.SOAPService_company_es_ConectorWS_servi" + "ces_SN627003+Root1, Company.ESB.PC02.02, Version=1.0.0.0, Culture=neutral, Public" + "KeyToken=9431070526ed7a05";

2) Set to null this param in the Web Service:

object[] invokeResults = this.Invoke("WebMethod1", invokeParams, inParamInfos, outParamInfos, 0, null, inHeaders, inoutHeaders, out inoutHeaderResponses, out outHeaderResponses, null, null, null, out unknownHeaderResponses, false, false);

Thursday, June 05, 2008

BizTalk Expert Series

QuickLearn offers new BizTalk specialized courses in advanced topics:

- BizTalk Expert Series: Business Activity Monitoring (BAM)
- BizTalk Expert Series: Business Rule Engine (BRE)
- BizTalk Expert Series: RFID Solutions
- BizTalk Expert Series: ESB Solutions
- BizTalk Expert Series: EDI Integration
- BizTalk Expert Series: Testing Strategies

More information in QuickLearn site.

Sunday, June 01, 2008

ESB Guidance: Get Map from UDDI

Inside ESB Guidance, we can use UDDI to get TransportType, TransportLocation, ... and also we can get from UDDI the Map to apply.

First of all, we have to insert an UDDI service, with TransformType property and the value of the map that we will want to apply (map name and assembly), for example:



In previous example, I have setted the value "TransformType://GlobalBank.ESB.DynamicResolution.Transforms.SubmitOrderRequestNA_To_SubmitPurchaseOrderRequestCN,GlobalBank.ESB.DynamicResolution.Transforms, Version=1.0.0.0, Culture=neutral, PublicKeyToken=c2c8b2b87f54180a".

Next, we add a Receive Location and use a Receive Pipeline with a ESB Dispatcher Disassembler Component, for example. We set the component's MapName property, to our UDDI service connection string, for example:

UDDI:\\serverUrl=http://localhost/uddi;serviceName=MyService;serviceProvider=MyProvider

Finally, we have to do a little change inside the ESB's resolver UDDI class (Microsoft.Practices.ESB.Resolver.UDDI.ResolveProvider). Inside the CopyResolution method, add inside the try block this line:

if (!string.IsNullOrEmpty(source.TransformType)) destination.TransformType = source.TransformType;

Now, we can use UDDI to get the transformation to apply.

Monday, May 19, 2008

SOA and ESB Architecture with BizTalk

Searching info about ESB Guidance, I found a recent little book (25 pages) by Robert V. Hogg & Ewan Fairweather, that seems to be very interesting.

This is the link http://www.wrox.com/WileyCDA/WroxTitle/productCd-047027011X.html.

BizTalk Accelerator for SWIFT 2008 Message Pack

BizTalk Server Team have launched Evaluation Program of BizTalk Accelerator for SWIFT 2008 Message Pack to test the next release of this product. BizTalk Accelerator for SWIFT 2008 Message Pack will provide compliance with SWIFT 2008 Standards Release Guide (SRG) specification.

The planned release schedule is:

- June 23, 2008 -> CTP
- July 21, 2008 -> Beta
- September 5, 2008 -> RTW

The 2008 Message Pack will include:

- Complete re-packaging of all SWIFT FIN Flat File message types and business rules.
- Updates to all message schemas and business rules for compliance with SWIFT 2008 Certification requirements.
- Roll-up of all schemas and business rule Hot fixes not superseded by 2008 requirements.
- Validation of SWIFT Reference data as a business rule rather than a schema

Friday, May 09, 2008

Endless XmlDisassembler

This is a curious behaviour of XmlDisassembler component. My problem was that I have developed a custom XmlDisassembler, that inside uses BizTalk XmlDisassembler component (Microsoft.BizTalk.Component.XmlDasmComp).

My component disassembles the message with the BizTalk component and discard some of the returned messages, based on some conditions. The problem is when I call XmlDasmComp's GetNext method, never ends.

Why? The problem is that in my conditions to discard the returned messages, I don't need to read the returned message. Inside the XmlDasmComp, in GetNext2 private method, it test a property 'IsNewDoc' to retrieve a new message or not. This property is updated only when we read the returned message.

Why this property is updated only when we read the returned message? Obvious, in BizTalk standard behaviour, it always read the returned message before to call GetNext method other time.

Standard behaviour in a BizTalk disassemble is:

1) XmlDasmComp.Disassemble
2) XmlDasmComp.GetNext (First Message)
3) Validate and ResolvePartyComponents (this components can read the message)
4) Receive Pipeline ends, then BizTalk READ THE MESSAGE
5) XmlDasmComp.GetNext (Second Message)
...
Until GetNext method returns a null message.

In my component, I was calling GetNext method continuosly without reading the message, so 'IsNewDoc' never was updated and GetNext method never ends.

Solution is, after calling GetNext method, I read the message and then I seek to the begin the message (If no, the internal Stream is in the last position and next components couldn't read it)

Thursday, May 08, 2008

Deploy Orchestrations: "Failed to update binding information"

Yesterday, I was redeploying an orchestration through BizTalk MMC -> MyApplication -> Add -> BizTalk Assemblies... with "Overwrite all" checked, when I received this error:



The detail error said that "Receive Location 'Receive Location MQ por FILE' has no Transport type specified.". I was confused, because Receive Location 'Receive Location MQ por FILE' didn't exists, it was a Receive Location that I have deleted weeks ago.

Searching for BindingInfo inside my computer, I discovered that BizTalk stores info about the last deployments in C:\Documents and Settings\[user name]\Application Data\Microsoft\BizTalk Server\Deployment\BindingFiles (over Vista in C:\Users\[user name]\AppData\Roaming\Microsoft\BizTalk Server\Deployment\BindingFiles).

When you do a redeployment, BizTalk uses this information. If this information is erroneous, we get this error "Failed to update binding information".

Solution is easy, remove the info binding file and we can redeploy our orchestration.

Sunday, April 27, 2008

Set Filename for the Attachment

If we want to send message through a SMTP Port with attachments and we want to set the attachment's filename, we have to set MIME.FileName property.

When we are designing the orchestration, Intellisense don't show us this property:



We have to write "Message_1(MIME." and Intellisense will show us this property:



This is because MIME.FileName is a PartContextPropertyBase and Intellisense by default only show us the MessageContextPropertyBase properties.

SMTP Adapter - "Unknown Error Description"

If inside an orchestration, we set SMTP.EmailBodyText property in a message and we don't set SMTP.EmailBodyTextCharset, we receive "Unknown Error Description" when we send this message through a Dynamic Port.

To avoid this error, we have to set SMTP.EmailBodyTextCharset property.

More information in http://msdn2.microsoft.com/en-us/library/aa578225.aspx.

Thursday, April 24, 2008

BizTalk Server 2006 R3

Yesterday, in BizTalk Server Team Blog and in Steven Martin's blog, announced their plans to deliver BizTalk Server 2006 R3.

At high level, new features will be:

- New web service registry capabilities with support for UDDI (Universal Description Discovery and Integration) version 3.0
- Enhanced service enablement of applications (through new and enhanced adapters for LOB applications, databases, and legacy/host systems)
- Enhanced service enablement of “edge” devices through BizTalk RFID Mobile
- Enhanced interoperability and connectivity support for B2B protocols (like SWIFT, EDI, etc)
- SOA patterns and best practices guidance to assist customer’s implementations

They expect to deliver a CTP of BizTalk Server 2006 R3, later this year and an RTM in H1 CY09.

They have also launched the BizTalk Server 2006 R3 TAP program.

Wednesday, April 02, 2008

XmlAsmException (HRESULT = 0xc0c01829) And XmlDasmException (HRESULT = 0xc0c01470)

XmlAsmException (HRESULT = 0xc0c01829) And XmlDasmException (HRESULT = 0xc0c01470) are exceptions without an error message.

Using Tomas Restrepo's error lookup utility (see my previous post), we can get a more detailed message:

0xc0c01829 = "BtsErrorAssemblerDoctypeDoesntMatchSchemas"
0xc0c01470 = "BtsErrorDisassemblerDoctypeDoesntMatchSchemas"

This error message means, that the provided schemas don't match with:
<message root element name> or <message namespace>#<message root element name>

This is the obvious error, but also we can get both error messages if our message has the DocumentSpecName context property setted.

The problem is that the standard biztalk's assemblers and disassemblers, override the DocumentSpecNames property of the XML Assembler/Disassembler pipeline components and the Document Schema property of the Flat File Assembler/Disassembler pipeline component if we set the message's DocumentSpecName context property.

Monday, March 31, 2008

Pipeline Components Error Lookup

Here is a Tomas Restrepo very useful utility class to translate HRESULT error codes from pipeline components (XML Disassembler, ...) to a understandable error code:

http://www.winterdom.com/dev/bts/BtsErrorLookup.cs.txt

For example, in my last application I get from Flat File Assembler an empty error message with HRESULT = 0xc0c01829. The Tomas Restrepo utility class, translate it to "BtsErrorAssemblerDoctypeDoesntMatchSchemas", that helps me to solve the error.

More information in:

http://technet.microsoft.com/en-us/library/microsoft.biztalk.component.aspx

For example:

http://technet.microsoft.com/en-us/library/microsoft.biztalk.component.xmlasmexception.btserrorassemblerdoctypedoesntmatchschemas.aspx

Friday, February 29, 2008

Bug: You may receive a WSE590 exception in Web Services Enhancements 3.0 for Microsoft .NET when you try to implement OASIS Web Services Security 1.0

I have encountered with this error with WSE 3.0: You may receive a WSE590 exception in Web Services Enhancements 3.0 for Microsoft .NET when you try to implement OASIS Web Services Security 1.0.

The proposal solution is set KeyIdentifier myKeyIdentifier = new KeyIdentifier("MIGfMa0GCSq");

I was using MutualCertificate11Assertion and for that, I take advantage that this assertion uses an X509Certificate.

I propose a better and cleaner solution:

1) In our Assertion class, we inherit directly from MutualCertificate11Assertion.
2) In our Filter class:
2.1) A private X509Certificate2 attribute (_certificate).
2.2) In constructor declaration, add a X509Certificate2 parameter (certificate).
2.3) Inside constructor, set _certificate = certificate.
2.4) Instead of KeyIdentifier myKeyIdentifier = ... line, set KeyIdentifier myKeyIdentifier = new KeyIdentifier(System.Convert.ToBase64String(_certificate.GetCertHash()));
3) From our Assertion class, pass this.ServiceX509TokenProvider.GetToken ().Certificate to the Filter class constructor.

Thursday, February 21, 2008

Changing SSO Master Secret Server from one Server to another

If we want to change Master Secret Server from their current server to another, we have to execute on current Master Secret Server (Server1):

"C:\Program Files\Common Files\Enterprise Single Sign-On\ssoconfig.exe" -backupsecret ssosecret.bkp

Create on the new Master Secret Server (Server2) an XML file (ssoserver.xml) with this content:

<sso><globalInfo><secretServer>SERVER2</secretServer></globalInfo></sso>

And execute:

"C:\Program Files\Common Files\Enterprise Single Sign-On\ssomanage.exe" -updatedb ssoserver.xml

Then execute:

"C:\Program Files\Common Files\Enterprise Single Sign-On\ssoconfig.exe" -restoreSecret ssosecret.bkp

And finally, you can test that is correct executing a backupsecret on each server.

Here is a complete sequence:

Server 1
C:\>"c:\Program Files\Common Files\Enterprise Single
Sign-On\ssoconfig" -backupsecret ssobackupsecret.bkp
Password : ***********
Confirm Password : ***********
Password reminder : Reminder
The operation completed successfully.

Server 2

D:\>"c:\Program Files\Common Files\Enterprise Single Sign-On\ssomanage.
exe" -updatedb ssoserver.xml
Using SSO server on this computer

Updated SSO global information with the following values -

SSO secret server name : SERVER2
SSO Admin account name : NOT CHANGED
SSO Affiliate Admin account name : NOT CHANGED


D:\>"c:\Program Files\Common Files\Enterprise Single Sign-On\ssoconfig.
exe" -restoreSecret ssobackupsecret.bkp
Password reminder : Reminder
Password : ***********
The operation completed successfully.

Server 1

C:\>"c:\Program Files\Common Files\Enterprise Single
Sign-On\ssoconfig" -backupsecret ssobackupsecret2.bkp
ERROR: Secrets can only be backed up on the master secret server.
ERROR: 0xC0002A0E : This function can only be performed on the master secret ser
ver.

Wednesday, January 02, 2008

Orchestration Expressions: exists and succeeded operators

exists Operator

This operator inside an Orchestration allow us to determine if a message context property exists in a message.

Syntax:
<Message Property Name Message Part Property Name> exists <Message Variable Name Message Part Name>

Example:
BTS.AckType exists msgIn

This is util to avoid 'There is no value associated with the
property <property> in the message.' error message when we get the value of a property, for example:

if (BTS.AckType exists msgIn)
{
myAckType = msgIn(BTS.AckType);
}


succeeded Operator

This operator is very usefull when we want to use a message (that is constructed inside a transaction) in a handling exception block inside an Orchestration.

For example, if we construct msgOut inside transaction Transaction_1 and in the handling exception block, we write in a expression shape:

System.Diagnostics.Debug.WriteLine ("Received Port was: " + msgOut(BTS.ReceivePortName));

We will receive this error: use of unconstructed message 'msgOut'

But if we write this code, we get the desired behaviour and no compilation error:

if (succeeded(Transaction_1))
{
System.Diagnostics.Debug.WriteLine ("Received Port was: " + msgOut(BTS.ReceivePortName));
}

Wednesday, December 19, 2007

Call SubmitDirect Adapter from Orchestration

If we want call SubmitDirect directly from Orchestration, we will get this error:

"The Messaging Engine failed to register the adapter for "Submit" for the
receive location "submit://submitrequest". Please verify that the receive
location is valid, and that the isolated adapter runs under an account that
has access to the BizTalk databases."


This error is because SubmitDirect adapter needs to run in an Isolated process, because is an Isolated adapter.

My solution is convert this adapter in an In-Process adapter. This is simple, we need to do 2 changes in the SubmitDirect solution:

1) Implement IBTTTransportControl at BizTalkMessaging class (in MessagingAPIs.cs at TransportProxyUtils project), for example:

public void Initialize(IBTTransportProxy transportProxy)
{
_tp = transportProxy;
}

public void Terminate()
{
}

2) Change RegisterAdapter.cs in TransportProxyUtilsReg project:

Change this line "rkBizTalk.SetValue("Constraints", 0x00000081);" with "rkBizTalk.SetValue("Constraints", 0x00000089);"

First change is to implement all interfaces that need an In-Process adapter (see BizTalk documentation "Interfaces for an In-Process Receive Adapter").

Second change is to indicate that our adapter is hosted in-process (see BizTalk documentation "Registering an Adapter -> Constraints -> eProtocolReceiveIsCreatable flag).

With this changes, we build the solution and then, we register our custom SubmitDirect adapter and voilà, we can call SubmitDirect adapter from a Orchestration without errors, because our adapter will run within BizTalk process.

Monday, December 17, 2007

XPath inside BizTalk

XPath is a powerfull feature in BizTalk solutions, but is little complicated when we have a lot of namespaces and elements.

If we develope a solution wich uses this feature, it can be very frustrating, because it's a thorny issue.

There is a good tool that help us to test our xpath expressions, XPathmania.

This tool is a plug-in for Visual Studio 2005 and allows us to do queries against a XML document. After install it, we open this tool in View -> Other Windows -> Xpathmania menu:


If we open a XML document, we can test our xpath queries:


If xpath query is correct, Xpathmania will set the backcolor of selected nodes to green. If it is any sintax error in our query, Xpathmania will tell us the error:

Sunday, December 09, 2007

"No XOP Parts"

Due to a bug in Axis2 1.3, when we call a web service from a .NET application using WSE 3.0 and MTOM, we receive this error: "WSE1608: No XOP parts were located in the stream for the specified content-id: ...".

The problem is that in Axis2 response we receive something like this:

HTTP/1.0 200 OK
Date: Sun, 09 Dec 2007 10:41:00 GMT
X-Powered-By: Servlet 2.4; Tomcat-5.0.28/JBoss-3.2.7 (build: CVSTag=JBoss_3_2_7 date=200501280217)
Content-Type: multipart/related; boundary=MIMEBoundaryurn_uuid_E3F73E4E791CD88AAB1197196860587; type="application/xop+xml"; start="0.urn:uuid:E3F73E4E791CD88AAB1197196860588@apache.org"; start-info="text/xml"
Set-Cookie: BIGipServerhttp_87_integracion= 50571456.22272.0000; path=/
Connection: close

--MIMEBoundaryurn_uuid_E3F73E4E791CD88AAB1197196860587
Content-Type: application/xop+xml; charset=utf-8; type="text/xml"
Content-Transfer-Encoding: binary
Content-ID: <0.urn:uuid:E3F73E4E791CD88AAB1197196860588@apache.org>


The problem is with start attribute, that doesn't match with the content-id of the object root, because it hasn't < and >. According to RFC 2387: "The 'start' parameter, if given, points, via a content-ID, to the
body part that contains the object root."
.
A example from this RFC:

Content-Type: Multipart/Related; boundary=example-1
start="<950120.aaCC@XIson.com>";
type="Application/X-FixedRecord"
start-info="-o ps"

Content-Type: Application/X-FixedRecord
Content-ID: <950120.aaCC@XIson.com>


Here is a link to this issue from Axis2:
https://issues.apache.org/jira/browse/AXIS2-3196.
Here is a link to the culprit version change: http://svn.apache.org/viewvc?view=rev&revision=555276.
Here is a link to the correct version change: http://svn.apache.org/viewvc?view=rev&revision=573037.

Here is the .NET call, that is correct according to RFC:

POST /services/SOAPService HTTP/1.1
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; MS Web Services Client Protocol 2.0.50727.1433)
VsDebuggerCausalityData: uIDPo/roRa0+I2ZGg8sva4yaNrAAAAAA0oIuYeGHw0WWedV3KmBPQfNgOTYMehBNh8VxIFQqoJ8ACAAA
SOAPAction: "process"
Host: test.host.com
Content-Type: multipart/related; type="application/xop+xml"; boundary=--MIMEBoundary633327972312845535; start="<0.633327972312845535@example.org>"; start-info="text/xml; charset=utf-8"
Content-Length: 1358
Expect: 100-continue
Proxy-Connection: Keep-Alive

----MIMEBoundary633327972312845535
content-id: <0.633327972312845535@example.org>
content-type: application/xop+xml; charset=utf-8; type="text/xml; charset=utf-8"
content-transfer-encoding: binary

Monday, November 26, 2007

Custom Pipeline FTP Component Error: "Ran out of memory"

We have developed a custom pipeline component that writes in context FTP properties, such as BeforePut, UserName, ...

When we are testing this component we received an unusual error: "Ran out of memory".

After discard memory problems, we realize that our problem was that...Password was not properly setted!!

We set Password FTP Context property ("http://schemas.microsoft.com/BizTalk/2003/ftp-properties") and our "Ran out of memory" error disappears.

Saturday, November 24, 2007

SOA Conference 2007 at Madrid

Next December 4 at Madrid, Microsoft announces SOA Conference 2007 in Spain. My friend Tomás Hernández will talk about "BizTalk Adapters for WCF".

Here is a complete agenda:
http://www.microsoft.com/spain/sunegocioconectado/agenda.aspx

Friday, November 23, 2007

MQSC Adapter error

We have installed MQSC adapter for BizTalk, with WebSphere MQ Client 6, with fixpack 6.0.2.2.

Our MQ Servers are MQ WebSphere 6, one in Z/OS Server and other in a Windows 2003 Server.

When we defined a Receive Location and try to get a message, we received this two errors:

"The adapter "MQSC" raised an error message. Details "Failure encountered while attempting to get message from queue. queue = <QueueName>, queueManager = <QueueManagerName>, reasonCode = 2354"."

"The MQCD structure was not valid. The value of 'Version' field has the value '0'. This value is invalid for the operation requested."

We was investigating in this issue, when we find this post:
http://biztalk.softwareheadlines.com/mqsc-adapter-mqseries-client-adapter-extended-transaction-t3299.html

We try this solution and it works!!

Our channel name (for example CHANN.NAMES.SVRCONN) had sufficient length to produces the error. We change the channel name with a shorter name (CHANN.NAMES) and works ok.

Solution is give a channel name one char less that maximum length.

Wednesday, November 21, 2007

Download the Visual Studio 2008 Express Edition All-in-One DVD

Since few days ago is possible to download Visual Studio 2008 in an ISO image. Here is the link:
http://go.microsoft.com/fwlink/?LinkId=104679

Also for instructions on burning the Visual Studio Express Editions DVD there is this link:
http://www.microsoft.com/express/download/offline.aspx

Thursday, November 15, 2007

Web Parts Personalization Providers

As I say in my previous post, today I found a lot of problems when I deploy my application in an integration environment.

Web Parts Personalization was a problem, because I can't use the default database to store the personalization values.

We found two posible solutions in this links:
http://msdn2.microsoft.com/en-us/library/aa479037.aspx
http://www.kowitz.net/files/source/XmlFilePersonalizationProvider.cs.txt

First of two, allow to store values in a txt file and second allow to store values in an XML files.

Both examples, build a class that derives from ProviderBase class. I use txt file provider, I customize the class, because I need more functionality. For example, I implemented this method that recognize when a user has personalization data:

public override int GetCountOfState(PersonalizationScope scope,
PersonalizationStateQuery query)
{
if (File.Exists(GetPath(query.UsernameToMatch, query.PathToMatch)))
return 1;
else
return 0;
}


It works ok and now, I don't need the default personalization database.

SSO Error - The trust relationship between the primary domain and the trusted domain failed.

Today, when I was deploying my application in an integration environment, I found a lot of problems. First of all was this error message when I deploy my config files into SSO:

SSO AUDIT
Function: CreateApplication
Tracking ID: caa4f99b-8053-4a8a-bfd0-67fcce18e978
Client Computer: server.domain.com (ssomanage.exe:4520)
Client User: DOMAIN\User
Application Name: MyApplication
Error Code: 0x800706FC, The trust relationship between the primary domain and the trusted domain failed.

This error message confuse me, but finally I found the solution and was very simple. My error was that in my application configuration XML file for SSO, I set in appAdminAccount tag, my local account, instead of domain account.

Monday, November 12, 2007

AddressAccessDeniedException - Windows Vista

Due to new security settings in Windows Vista, we get this error "HTTP could not register URL http://+:8081/Greeting. Your process does not have access rights to this namespace (see http://go.microsoft.com/fwlink/?LinkId=70353 for details)" when we try to run a ServiceHost in an HTTP address.

To resolve this, we have to give permissions to our user:

1º) Run Visual Studio 2005 Command Prompt as Administrator.
2º) Execute netsh http add urlacl url=http://+:8081/Greeting user=DOMAIN\user
3º) If we want remove permissions: netsh http delete urlacl url=http://+:8081/Greeting

Monday, October 29, 2007

ESB in a .NET environment

Regarding for information about ESB over .NET environment, I found this two alternatives (see Jesus Rodriguez's WebLog at http://weblogs.asp.net/gsusx/archive/2007/10/09/some-thoughts-on-esb-vs-rest-dynamic-languages.aspx):

Neuron ESB:
http://www.neudesic.com/Main.aspx?SS=7&PE=75

ESB Guidance Toolkit:
http://www.codeplex.com/esb

Now I am studying both alternatives...soon I will tell you my opinion.

Friday, October 26, 2007

Unit Testing Class for Maps

Here is my class for unit testing BizTalk maps:

using Microsoft.XLANGs.BaseTypes;

using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Xml.XPath;
using System.Xml.Xsl;

namespace MyNamespace.Test
{
  public class MapsUtil
  {
    public static void CompareMaps(TransformBase map, Stream originStream, Stream expectedStream)
    {
      XslTransform transformation = map.Transform;
      XsltArgumentList transformationArgs = map.TransformArgs;

      MemoryStream outputStream = new MemoryStream();

      XPathDocument xpathDoc = new XPathDocument(originStream);

      transformation.Transform(xpathDoc, transformationArgs, outputStream);

      outputStream.Position = 0;

      StreamUtil.CompareStreams(expectedStream, outputStream);

      expectedStream.Flush();
      expectedStream.Close();
      outputStream.Flush();
      outputStream.Close();
    }
  }
}

And here is an example that uses it:

[Test()]
public void MapTest()
{
  MyMap map = new MyMap();
  TransformBase mapping = (TransformBase)map;

  Stream originStream = DocLoader.LoadStream(MESSAGES_NAMESPACE, "NOOP1.Reply.input.xml");
  Stream expectedStream = DocLoader.LoadStream(MESSAGES_NAMESPACE, "NOOP1.Reply_output.xml");

  MapsUtil.CompareMaps(mapping, originStream, expectedStream);
}

Where CompareStreams is a class for compare two different streams and DocLoader is a class for load resources as streams.

Tuesday, September 25, 2007

Mapping to a XML element with fixed attribute

Few days ago, I had this problem: I want to map a source schema to a destination schema, wich one of his elements has a fixed attribute (an attribute with a value in Fixed property). This element hadn't any input value and had minOccurs=0, but the mapper generates it. Here is an example:

- Source Schema



- Destination Schema



- Map



- XML Result

<ns0:Root xmlns:ns0="http://MappingError.DestinationSchema" />
  <element1>
    <field11>element1_0</field11>
    <field12>element2_0</field12>
  </element1>
  <element2 fixedattribute="FixedValue"/>
  <element3>
    <field31>element3_0</field31>
  </element3>
</ns0:root>

One solution is set for this element, an constant input value false, but my problem was that I had a lot elements with fixed attributes that mustn't be generated.

A solution for this is edit the map with notepad (because we can't edit in Visual Studio Properties Window) and set GenerateDefaultFixedNodes property to "No" (default is "Yes").

If we set this property to "No" the result XML is the correct:

<ns0:Root xmlns:ns0="http://MappingError.DestinationSchema" />
  <element1>
    <field11>element1_0</field11>
    <field12>element2_0</field12>
  </element1>
  <element3>
    <field31>element3_0</field31>
  </element3>
</ns0:root>

BizTalk Server 2006 R2 trial software is available for download

Here is the link from Microsoft TechNet for download a trial version:

http://technet.microsoft.com/en-us/bb738059.aspx

Saturday, September 08, 2007

Developing Pipelines Components Common Errors - UNC Path

When we add a pipeline component to our toolbox and we receive this error message: "You have selected an invalid pipeline component assembly. Please check security settings for the assembly if you are loading it from an UNC path.", probably our pipeline component don't find a referenced dll.


If you get this error, you must ensure that all referenced assemblies by this pipeline component are located under the same directory of our pipeline component dll or in the GAC.

Thursday, September 06, 2007

BizTalk Accelerator for SWIFT 2007 Message Pack

Today, BizTalk Server Team Blog have announced the release to the web of BizTalk Accelerator for SWIFT 2007 Message Pack.

For download:
http://support.microsoft.com/kb/925731/en-us

The Future of BizTalk

Great article from Tomas Restrepo about how BizTalk could evolve, expected improvements in new BizTalk version, the impacts of the possible changes in future migrations to new version, ...

Here is the link:
http://www.winterdom.com/weblog/2007/09/03/TheFutureOfBizTalkWCFWF.aspx

Wednesday, August 29, 2007

Enterprise Single Sign-on Service (SSO) as a configuration store (III)

In this article I will explain how to do a .NET class to get config properties from an SSO Affiliate Application.

First of all, we have to add a reference in our project to this DLL:
Common Files\Enterprise Single Sign-On\SDK\Bin\Microsoft.BizTalk.Interop.SSOClient.dll

Then we have to implement a class that implements IPropertyBag, something like this:

using Microsoft.BizTalk.SSOClient.Interop;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;

namespace SSOConfig{
   public class PropertyBag : IPropertyBag
   {
      private Hashtable _hashTable;
      public PropertyBag()
      {
         _hashTable= new Hashtable();
      }
      public void Read(string propName, out object ptrVar, int errorLog)
      {
         ptrVar = _hashTable[propName];
      }
      public void Write(string propName, ref object ptrVar)
      {
         if (_hashTable.ContainsKey(propName))
            _hashTable[propName] = ptrVar;
         else
            _hashTable.Add(propName, ptrVar);
      }
   }
}

Now, we can implement our class that gets properties from our affiliate application:

using Microsoft.BizTalk.SSOClient.Interop;
using System;
using System.Collections.Generic;
using System.Text;

namespace SSOConfig{
   public class SSOSettingsGetter    {

      private const string SSO_APPLICATION_NAME = "My Application";
      private const string SSO_IDENTIFIER_NAME = "ConfigProperties";

      public object GetProperty(string propertyName)
      {
         ISSOConfigStore appStore = new ISSOConfigStore();
         PropertyBag pb = new PropertyBag ();
         appStore.GetConfigInfo(SSO_APPLICATION_NAME, SSO_IDENTIFIER_NAME, SSOFlag.SSO_FLAG_RUNTIME, pb);
         object propertyValue = null;
         pb.Read(propertyName, out propertyValue, 0);
         return propertyValue;
      }
   }
}

Enterprise Single Sign-on Service (SSO) as a configuration store (II)

In previous article, I explained how to create an affiliate application in SSO. The most important thing was this lines:

...
<appAdminAccount>BizTalk Server Administrators</appAdminAccount>
<appUserAccount>BizTalk Application Users</appUserAccount>
...
<flags configStoreApp="yes" allowLocalAccounts="yes" enableApp="yes" />

First lines are important because our user should be under one of previous groups. Last line is important because determine that our application is for configuration.

Now I will explain how to set/get the properties' values from command line. We have to use BTSScnSSOApplicationConfig.exe tool.
The sintaxis for this tool to set a value is:
BTSScnSSOApplicationConfig.exe -set <appName> <id> <propertyName> <propertyValue>
The sintaxis for this tool to get a value is:
BTSScnSSOApplicationConfig.exe -get <appName> <id> <propertyName>

For example, to modify my "db.passwd" value:
BTSScnSSOApplicationConfig.exe -set "My Application" ConfigProperties db.passwd mynewpasswd

To obtain this value:
BTSScnSSOApplicationConfig.exe -get "My Application" ConfigProperties db.passwd

Monday, August 27, 2007

Differences/Similarities between WCF behaviors and BizTalk pipelines

Great Jesus Rodriguez's about wich WCF features are similar to BizTalk pipelines and wich are different, how this features can complement existing BizTalk pipelines features and which overlaps existing pipeline features:
http://weblogs.asp.net/gsusx/archive/2007/08/23/wcf-behavior-vs-pipelines-on-biztalk-server-r2.aspx

Here another article by Tomas Restrepo from a different point of view:
http://www.winterdom.com/weblog/2007/08/25/WCFAndBizTalkMessaging.aspx

Saturday, August 18, 2007

Enterprise Single Sign-on Service (SSO) as a configuration store (I)

If we want store our BizTalk application configuration in SSO, first we have to create our affilitiate application with an XML similar to this:

<sso>
<application name="My Application">
<description>My application description</description>
<contact>felixmondelo@gmail.com</contact>
<appAdminAccount>BizTalk Server Administrators</appAdminAccount>
<appUserAccount>BizTalk Application Users</appUserAccount>
<field ordinal="0" label="reserved" masked="no"/>
<field ordinal="1" label="db.passwd" masked="yes" value="passwd" />
<field ordinal="2" label="db.conn.string" masked="yes" value="Data Source=localhost;Initial Catalog=MyDb;Integrated Security=True" />
<flags configStoreApp="yes" allowLocalAccounts="yes" enableApp="yes" />
</application>
</sso>

For more information about each field in this xml go to http://msdn2.microsoft.com/en-us/library/ms961685.aspx.

Then we have to insert this application into SSO with this executable "%root%\Program Files\Common Files\Enterprise Single Sign-On\ssomanage.exe". Sintaxis to create an application is:
ssomanage.exe -createapps <previous xml document path>, for example:
ssomanage.exe -createapps myssoappconfiguration.xml.

Tuesday, August 14, 2007

Stored Procedure to return a Policy to its editable state

When we publish or deploy a Policy during development, if we want to modificate the Policy we need to create a new version. With this stored procedure, we can unpublish/undeploy our Policy and modificate it:

CREATE PROCEDURE [dbo].[re_setpolicyeditable] (@policyName nvarchar(256),@nMajor bigint, @nMinor bigint)

AS

DECLARE @nRuleSetID AS BIGINT

SET @nRuleSetID = (SELECT nRuleSetID FROM dbo.re_ruleset WHERE strName = @policyName AND nMajor = @nMajor AND nMinor = @nMinor)

IF @nRuleSetID IS NULL BEGIN PRINT 'The Policy [' + @policyName + ' ' + CAST(@nMajor AS nvarchar(10)) + '.' + CAST(@nMinor AS nvarchar(10)) + '] not exists.' RETURN

END

UPDATE dbo.re_ruleset SET nStatus = 0 WHERE nRuleSetID = @nRuleSetID

DELETE FROM dbo.re_deployment_config WHERE nRuleSetID = @nRuleSetID

DELETE FROM dbo.re_tracking_id WHERE nRuleSetID = @nRuleSetID

INSERT INTO dbo.re_deployment_history VALUES (@policyName , 1, 0, 0, getdate())

GO

Friday, August 10, 2007

Microsoft.BizTalk.Component.Utilities.dll (or how to add reference to a dll wich is only in the GAC)

There are some DLLs wich are located only in the GAC, there is no physical file in our computer. Visual Studio does not allow you to add references to components in the GAC.

We have two alternatives:

1) Copy the file from the GAC to a physical file:
copy C:\WINDOWS\assembly\GAC_MSIL\
Microsoft.BizTalk.Component.Utilities\
3.0.1.0__31bf3856ad364e3\
Microsoft.BizTalk.Component.Utilities.dll

2) Unload the project, edit it and add manually the reference:

<itemgroup>
<reference include="Microsoft.BizTalk.Component.Utilities, Version=3.0.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<reference include="Microsoft.BizTalk.Pipeline, Version=3.0.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<specificversion>False></specificversion>
<hintpath>..\..\lib\Microsoft.BizTalk.Pipeline.dll></hintpath>
</reference>

Wednesday, August 08, 2007

InterchangeId vs MessageId

Here is an excerpt from "Professional Biztalk Server 2006" book explaining wich is the most appropiate identifier for a message in BizTalk:
"The most appropriate identifier to use is the BTS.InterchangeID message context property. The interchange ID is a GUID that is created by the engine. It is flowed automatically by the Messaging Engine as the message passes through the pipeline. You should note that the Message ID is typically not appropriate, since the message may be cloned multiple times during its processing, as described in Chapter 4, and each clone will have a unique Message ID. The Orchestration Engine will also flow the BTS.InterchangeID message context property where it can, although you must flow the property yourself in scenarios in which you create new messages"

NAnt - Error Handling

When an error occurs in a NAnt process, we can execute an error handling task. We only need to set "nant.onfailure" property to point to valid target element in the build file.

Example:

<property name="nant.onfailure" value="myproject.error" />

<target name="myproject.error">
  <call failonerror="false" target="myproject.error.deletetempfiles" />
  <call failonerror="false" target="myproject.error.deletetestcertificates" />
  <call failonerror="false" target="myproject.error.deletesettings" />
</target>