在BizTalk Server中,经常需要创建接收位置来处理外部的Web服务请求。本文将介绍如何在不使用Orchestration的情况下,通过创建一个WCF-Custom服务行为来实现对请求的同步响应。
在某些情况下,可能需要在BizTalkServer中创建一个WCFWebservice类型的接收位置,并在接收到请求后立即同步返回一个XML类型的响应。这个响应需要根据输入消息中的字段来填充响应XML中的某些字段。
假设需要创建一个BizTalk的WCFWebservice接收位置,一旦在这个端口上接收到请求,就需要立即同步返回一个响应,并且这个响应是一个XML类型,但是需要从输入消息的字段中填充响应XML的一些字段。
可以通过创建一个WCF-Custom服务行为来解决上述问题,而不需要使用Orchestration。以下是实现步骤:
首先,需要在BizTalkServer中创建一个WCF-CustomIsolated类型的接收位置。如果需要,也可以使用WCF-Custom,并将其托管在进程内主机上。
接下来,需要添加一个类库项目,并在其中添加以下三个类:
这个类是自定义行为扩展元素,它允许在配置文件中定义成功和错误响应的XML。
public class CustomTechKundanBTSResponseProviderBehaviorExtensionElement : BehaviorExtensionElement
{
public CustomTechKundanBTSResponseProviderBehaviorExtensionElement()
{
}
public override Type BehaviorType
{
get { return typeof(CustomTechKundanBTSResponseProviderServiceBehavior); }
}
protected override object CreateBehavior()
{
return new CustomTechKundanBTSResponseProviderServiceBehavior(SuccessResponse, ErrorResponse, MaxLengthFaultMessage);
}
[ConfigurationProperty("SuccessResponse", DefaultValue = "", IsRequired = false)]
public string SuccessResponse
{
get { return (string)base["SuccessResponse"]; }
set { base["SuccessResponse"] = value; }
}
[ConfigurationProperty("ErrorResponse", DefaultValue = "", IsRequired = false)]
public string ErrorResponse
{
get { return (string)base["ErrorResponse"]; }
set { base["ErrorResponse"] = value; }
}
[ConfigurationProperty("MaxLengthFaultMessage", DefaultValue = "", IsRequired = false)]
public int? MaxLengthFaultMessage
{
get { return (int?)base["MaxLengthFaultMessage"]; }
set { base["MaxLengthFaultMessage"] = value; }
}
}
这个类实现了IDispatchMessageInspector接口,用于在收到请求后创建响应消息。
public class CustomTechKundanBTSResponseProviderMessageInspector : IDispatchMessageInspector
{
private string _successResponse = null;
private string _errorResponse = null;
private int? _maxLengthFaultString;
private bool _emptyMessage;
public CustomTechKundanBTSResponseProviderMessageInspector(string successResponse, string errorResponse, int? maxLengthFaultString)
{
_successResponse = successResponse;
_errorResponse = errorResponse;
_maxLengthFaultString = maxLengthFaultString;
}
object IDispatchMessageInspector.AfterReceiveRequest(ref Message request, IClientChannel channel, InstanceContext instanceContext)
{
_emptyMessage = request.IsEmpty;
XmlDocument xmldoc = new XmlDocument();
xmldoc.Load(request.GetReaderAtBodyContents());
// Log the request message
EventLog.WriteEntry("KundanBTS WCF compo", xmldoc.InnerXml);
Message message = Message.CreateMessage(request.Version, null, new XmlNodeReader(xmldoc));
// Copy back the original headers and properties to the new message
message.Headers.CopyHeadersFrom(request.Headers);
message.Properties.CopyProperties(request.Properties);
// Assign the new message to the referenced request message
request = message;
return null;
}
void IDispatchMessageInspector.BeforeSendReply(ref Message reply, object correlationState)
{
if (!_emptyMessage)
{
if (reply.IsFault)
{
// Create the error message if the property is set
if (_errorResponse != null && _errorResponse.Length > 0)
{
string strProvider = null;
string strRequester = null;
XPathNavigator navigator = xmldoc.CreateNavigator();
XPathNodeIterator Providernode = navigator.Select("//*[local-name()='providerID']");
XPathNodeIterator Requesternode = navigator.Select("//*[local-name()='RequesterD']");
while (Providernode.MoveNext())
{
strProvider = Providernode.Current.Value;
}
while (Requesternode.MoveNext())
{
strRequester = "KundanBTS_" + Requesternode.Current.Value;
}
string sErrorResponse = _errorResponse;
sErrorResponse = sErrorResponse.Replace("%providerID%", strProvider);
sErrorResponse = sErrorResponse.Replace("%RequesterID%", strRequester);
StringReader stringreader = new System.IO.StringReader(sErrorResponse);
XmlTextReader xmlreader = new XmlTextReader(stringreader);
Message newMsg = Message.CreateMessage(reply.Version, null, xmlreader);
reply.Close();
reply = newMsg;
}
}
else
{
// Create the success message if the property is set
string strProvider = null;
string strRequester = null;
XPathNavigator navigator = xmldoc.CreateNavigator();
XPathNodeIterator Providernode = navigator.Select("//*[local-name()='providerID']");
XPathNodeIterator Requesternode = navigator.Select("//*[local-name()='RequesterID']");
while (Providernode.MoveNext())
{
strProvider = Providernode.Current.Value;
}
while (Requesternode.MoveNext())
{
strRequester = Requesternode.Current.Value;
}
string sSuccessResponse = _successResponse;
sSuccessResponse = sSuccessResponse.Replace("%providerID%", strProvider);
sSuccessResponse = sSuccessResponse.Replace("%RequesterID%", strRequester);
StringReader stringreader = new System.IO.StringReader(sSuccessResponse);
XmlTextReader xmlreader = new XmlTextReader(stringreader);
Message newMsg = Message.CreateMessage(reply.Version, null, xmlreader);
reply.Close();
reply = newMsg;
}
}
}
}
这个类实现了IServiceBehavior接口,用于在服务行为中添加消息检查器。
public class CustomTechKundanBTSResponseProviderServiceBehavior : IServiceBehavior
{
private string _successResponse = null;
private string _errorResponse = null;
private int? _maxLengthFaultString;
public CustomTechKundanBTSResponseProviderServiceBehavior(string successResponse, string errorResponse, int? maxLengthFaultString)
{
_successResponse = successResponse;
_errorResponse = errorResponse;
_maxLengthFaultString = maxLengthFaultString;
}
public void AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, System.Collections.ObjectModel.Collection endpoints, BindingParameterCollection bindingParameters)
{
}
public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
{
CustomTechKundanBTSResponseProviderMessageInspector inspector = null;
foreach (ChannelDispatcher chDisp in serviceHostBase.ChannelDispatchers)
{
foreach (EndpointDispatcher epDisp in chDisp.Endpoints)
{
inspector = new CustomTechKundanBTSResponseProviderMessageInspector(_successResponse, _errorResponse, _maxLengthFaultString);
epDisp.DispatchRuntime.MessageInspectors.Add(inspector);
}
}
}
public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
{
}
}
编译上述类库项目,并将其添加到全局程序集缓存(GAC)中。
在32位和64位的machine.config文件中添加以下配置:
<add name="CustomTechKundanBTSResponse" type="Kundan.Integrations.WCF.CustomTechKundanBTSResponseProviderBehaviorExtensionElement, Kundan.Integrations.WCF.CustomTechKundanBTSResponse, Version=1.0.0.0, Culture=neutral, PublicKeyToken=c1a801be9a87ef72" />
更新配置后,需要重启IIS和BizTalk Host实例。
在WCF-Custom(或WCF-CustomIsolated)接收位置的行为选项卡上,右键单击并添加扩展。可以看到CustomTechKundanBTSResponse在列表中,添加它,并提供成功和错误响应XML。