|
Hi Tom,
I have a solution for that now. Basically I wrote a msbuild task to add the configuration information to the adapter using WMI. There are a couple of things to do
1. Define your port settings as per normal in the port bindings file and create the port without any custom behaviour.
2. I use a custom xml file to define the behaviour configuration as below.
<AdapterConfig>
<Handler>
<AdapterName>WCF-Custom</AdapterName>
<HostName>BiztalkServerApplication</HostName>
<ConfigSection>
<CustomProps>
<WcfExtensions vt="8"><behaviorExtensions><add name=\"CustomAuthBehaviorElement\" type=\"Integration.Common.WCFBehaviours.WCFSecurityBehaviours.BiztalkServiceAuthorisationBehaviourElement, Integration.Common.WCFBehaviours, Version=#VersionNumber#, Culture=neutral, PublicKeyToken=your key here\"/></behaviorExtensions></WcfExtensions>
</CustomProps>
</ConfigSection>
<IsReceiveHandler>true</IsReceiveHandler>
</Handler>
</AdapterConfig>
3. Update the btdf project file to include the custom Task and define a target as below.
add reference assemblies
<UsingTask
AssemblyFile="BiztalkDeployment.Tasks.dll"
TaskName="BiztalkManagement.ReceiveHandler.UpdateAdapterCustomTransportProperties"
/>
add the Target needed. GetPipelineVersionNumber is a custom task that reads the version that is being deployed from somewhere
<Target Name="UpdateCustomBehaviors" DependsOnTargets="GetPipelineVersionNumber">
<!-- find the VersionNumber and replace with correct one -->
<File.Replace Path="$(PortBindingsPath)\AdapterConfig.xml" OldValue="#VersionNumber#" NewValue="$(VersionNumber)"/>
<!-- add the config file. $(portBindingsPath) is set somewhere else and will depened on how the deployment project is set up. -->
<BiztalkManagement.ReceiveHandler.UpdateAdapterCustomTransportProperties ConfigFilePath="$(PortBindingsPath)\AdapterConfig.xml"/>
</Target>
when installing MSBUILD is run with a /t:"UpdateCustomBehaviours" switch.
Below is the implementation for the custome Task.
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Management;
using System.Xml.Linq;
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;
namespace BiztalkDeployment.Tasks.BiztalkManagement.ReceiveHandler
{
public class UpdateAdapterCustomTransportProperties : Task
{
[Required]
public string ConfigFilePath { get; set; }
public override bool Execute()
{
try
{
var result = false;
if (File.Exists(ConfigFilePath))
{
//get configuration items.
var configItemList = ReadConfigItems();
var receiveHandlers = configItemList.Where(itm => itm.isReceive);
//update receive handlers.
if (receiveHandlers.Any())
result = ProcessHandler(receiveHandlers, "MSBTS_ReceiveHandler");
//update send handlers.
var sendHandlers = configItemList.Where(itm => !itm.isReceive);
if (sendHandlers.Any())
result = ProcessHandler(sendHandlers, "MSBTS_SendHandler");
Log.LogMessage("Configuration added successfully.");
return result;
}
Log.LogError("Configuration file {0} does not exist.", ConfigFilePath);
return false;
}
catch (Exception ex)
{
Log.LogErrorFromException(ex, true);
return false;
}
}
private bool ProcessHandler(IEnumerable<ConfigItems> configList, string mgmtObject)
{
var configUpdated = false;
var options = new PutOptions { Type = PutType.UpdateOrCreate };
foreach (var itm in configList)
{
if (!ValidateConfigItem(itm)) continue;
var strWQL = string.Format("SELECT * FROM {0} WHERE AdapterName=\"{1}\" AND HostName=\"{2}\"",
mgmtObject, itm.AdapterName, itm.HostName);
var searchReceiveHandler = new ManagementObjectSearcher(
new ManagementScope("root\\MicrosoftBiztalkServer"), new WqlObjectQuery(strWQL), null);
var handlers = searchReceiveHandler.Get();
if (handlers.Count > 0)
{
foreach (ManagementObject handle in handlers)
{
handle["CustomCfg"] = itm.ConfigurationXml;
handle.Put(options);
handle.Dispose();
}
configUpdated = true;
}
searchReceiveHandler.Dispose();
}
return configUpdated;
}
private IEnumerable<ConfigItems> ReadConfigItems()
{
var doc = XDocument.Load(ConfigFilePath);
var root = doc.Element("AdapterConfig");
var handlers = from itm in root.Elements("Handler")
select new ConfigItems
{
AdapterName = itm.Element("AdapterName") == null ? string.Empty : itm.Element("AdapterName").Value,
HostName = itm.Element("HostName") == null ? string.Empty : itm.Element("HostName").Value,
ConfigurationXml = ConfigXml(itm),
isReceive = itm.Element("IsReceiveHandler") == null ? false :
itm.Element("IsReceiveHandler").Value.Equals("true", StringComparison.OrdinalIgnoreCase)
};
return handlers;
}
private string ConfigXml(XElement configElement)
{
var elem = configElement.Element("ConfigSection");
string str = string.Empty;
if (elem != null)
{
var reader = (configElement.Element("ConfigSection").CreateReader());
reader.MoveToContent();
str = reader.ReadInnerXml();
}
return str;
}
private bool ValidateConfigItem(ConfigItems item)
{
return (!string.IsNullOrEmpty(item.AdapterName)
&& !string.IsNullOrEmpty(item.HostName)
&& !string.IsNullOrEmpty(ConfigFilePath));
}
internal class ConfigItems
{
public string AdapterName { get; set; }
public string HostName { get; set; }
public string ConfigurationXml { get; set; }
public bool isReceive { get; set; }
}
}
}
I would also love to know if anyone else has run into this and has an alternate approach.
Cheers,
Min
|