Introduction
WCF with BizTalk comes with great features. There are a lot of things we can do this, we just need to discover them. As it is not too old,
a lot of things can't be found on the web. But believe me it is much more than what we think.
I am just sharing one of the features with you.
Background
Problem statement: Suppose you want to create a BizTalk receive location (of WCF Webservice),
and once you receive a request on this port,
you need to send a Response back (with-in same time synchronously) with some kind of XML type but populating some of the response XML fields
from Input message fields.
Note: Solve the above problem without using an Orchestration.
Solution
We can solve the above problem without using an Orchestration, by creating a WCF-Custom Service Behaviour.
Steps
- Create a BizTalk Server Receive location of WCF-CusomIsolated (or we can use WCF-Custom, host it on In-Process host in this case).
- Add a Class Library project and add three classes.
- CustomTechKundanBTSResponseProviderBehaviorExtensionElement.cs
using System;
using System.Collections.Generic;using System.Text;
using System.ServiceModel.Configuration;
using System.Configuration;
using System.Xml.Schema;
using System.Xml;
namespace Kundan.Integrations.WCF{
public class CustomTechKundanBTSResponseProviderBehaviorExtensionElement :
BehaviorExtensionElement{public CustomTechKundanBTSResponseProviderBehaviorExtensionElement(){
}
public override Type BehaviorType{
get{return typeof(CustomTechKundanBTSResponseProviderServiceBehavior);}
}
protected override object CreateBehavior(){
return new CustomTechKundanBTSResponseProviderServiceBehavior(SuccesResponse,
ErrorResponse, MaxLengthFaultMessage);}
[ConfigurationProperty("SuccesResponse", DefaultValue = "", IsRequired = false)]
public string SuccesResponse{
get { return (string)base["SuccesResponse"]; }
set { base["SuccesResponse"] = 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; }}
}
}
- CustomTechKundanBTSResponseProviderMessageInspector.cs
using System;
using System.Collections.Generic;
using System.Text;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Dispatcher;
using System.Xml;
using System.Xml.XPath;
namespace Kundan.Integrations.WCF{
public class CustomTechKundanBTSResponseProviderMessageInspector :
IDispatchMessageInspector{String _succesResponse = null;
String _errorResponse = null;
int? _maxLengthFaultString;
bool _emptyMessage;
XPathDocument Requestdocument = null;
XmlDocument xmldoc = null;
public CustomTechKundanBTSResponseProviderMessageInspector(
String succesResponse, String errorResponse, int? maxLengthFaultString){
_succesResponse = succesResponse;
_errorResponse = errorResponse;
_maxLengthFaultString = maxLengthFaultString;
}
#region IDispatchMessageInspector Members
object IDispatchMessageInspector.AfterReceiveRequest(ref Message request,
IClientChannel channel, InstanceContext instanceContext){
_emptyMessage = request.IsEmpty;
xmldoc =
new XmlDocument();xmldoc.Load(request.GetReaderAtBodyContents());
System.Diagnostics.
EventLog.WriteEntry("KundanBTS WCF compo", xmldoc.InnerXml);
Message message = Message.CreateMessage(request.Version, null, new XmlNodeReader(xmldoc));
message.Properties.CopyProperties(request.Properties);
void IDispatchMessageInspector.BeforeSendReply(ref Message reply, object correlationState){
System.IO.
StringReader stringreader = null;System.Diagnostics.
EventLog.WriteEntry("KundanBTS WCF compo", "Inside Reply");
String sErrorResponse = "";
String sSuccesResponse = "";
if (!_emptyMessage){
if (reply.IsFault){
System.Diagnostics.
EventLog.WriteEntry("KundanBTS WCF compo", "Inside Error");
if (_errorResponse.Contains("%providerID%")){
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;}
sErrorResponse = _errorResponse;
sErrorResponse = sErrorResponse.Replace(
"%providerID%", strProvider);sErrorResponse = sErrorResponse.Replace(
"%RequesterID%", strRequester);
stringreader =
new System.IO.StringReader(sErrorResponse);
}
else{return;}
}
}
else{
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;
}
sSuccesResponse = _succesResponse;
sSuccesResponse = sSuccesResponse.Replace(
"%providerID%", strProvider);sSuccesResponse = sSuccesResponse.Replace(
"%RequesterID%", strRequester);stringreader =
new System.IO.StringReader(sSuccesResponse);
}
XmlTextReader xmlreader = new XmlTextReader(stringreader);
reply = newMsg;
}
}#endregion}
}
- CustomTechKundanBTSResponseProviderServiceBehavior.cs
using System;
using System.Collections.Generic;
using System.Text;
using System.ServiceModel.Description;
using System.Xml.Schema;
using System.ServiceModel;
using System.ServiceModel.Dispatcher;
using System.ServiceModel.Channels;
namespace Kundan.Integrations.WCF{
public class CustomTechKundanBTSResponseProviderServiceBehavior :
IServiceBehavior{String _succesResponse = null;
String _errorResponse = null;
int? _maxLengthFaultString;
public CustomTechKundanBTSResponseProviderServiceBehavior(String succesResponse,
String errorResponse, int? maxLengthFaultString){
_succesResponse = succesResponse;
_errorResponse = errorResponse;
_maxLengthFaultString = maxLengthFaultString;
}
public void AddBindingParameters(ServiceDescription serviceDescription,
ServiceHostBase serviceHostBase,
System.Collections.ObjectModel.Collection<ServiceEndpoint> 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(_succesResponse,
_errorResponse, _maxLengthFaultString);epDisp.DispatchRuntime.MessageInspectors.Add(inspector);
}
}
}
public void Validate(ServiceDescription serviseDescription, ServiceHostBase serviceHostBase){
}
}
}
- Compile and GAC the DLL.
- Add below line to 2.0 and 4.0 machine.config both at 32 bit and 64 bit machine.config files.
<add name="CustomTechKundanBTSResponse"
type="Kundan.Integrations.WCF.CustomTechKundanBTSResponseProviderBehaviorExtensionElement,
Kundan.Integrations.WCF.CustomTechKundanBTSResponse,
Version=1.0.0.0, Culture=neutral, PublicKeyToken=c1a801be9a87ef72" />
Re-start IIS and BizTalk Host instances.
- Go to WCF-Custom (or WCF-CustomIsolated) receive location and on Behaviour tab, right click and Add-Extension.
You can see CustomTechKundanBTSResponse in the list,
add it, and provide Success and Fault Response XMLs.
Now test it with your application or using SOAPUI.