Monday, September 17, 2012

BizTalk WCF Custom Service Behaviour

WCF with BizTalk comes with a great features. There are lot of thing we can do this, we just need to discover them. As it is not too old , so lots of things we can't find on web. But belive me it is much more than what do we think.

I am just sahring its one of the feature with you.

Creating WCF-Custom Service Behaviour


 Problem statement: Suppose you want to create a BizTalk receive location (of WCF Webservice), And once you receive a requent on this port , immediately you need to send a Response back (with-in same time syncronously) with some kind of XML type but populating some of the response xml fields from Input message fields.

Note: Solve above problem without using Orchestration.

Solution:

We can able to solve above problem without using an Orchestration , but creating a WCF-Custom Service Behaviour.

Setps.
1. Create a BizTalk Server Recevie location of WCF-CusomIsolated (Or can be WCF-Custom , host it on In-Process host in this case).
2.Add Class library Project and Add three classess.

a. CustomTechKundanBTSResponseProviderBehaviorExtensionElement.cs
//Start 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; }}
}
}
//End: CustomTechKundanBTSResponseProviderBehaviorExtensionElement.cs
b.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));
//copy back the original headers and properties to the new messagemessage.Headers.CopyHeadersFrom(request.Headers);
message.Properties.CopyProperties(request.Properties);
//assign the new message to the referenced request messagerequest = message;return null;}


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");
//create the error message if the property is setif (_errorResponse != null && _errorResponse.Length > 0){

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{//create the succes message if the property is setSystem.Diagnostics.EventLog.WriteEntry("KundanBTS WCF compo", "Inside Success");
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);

// Create new message Message newMsg = Message.CreateMessage(reply.Version, null, xmlreader);
// Close the original message and return new messagereply.Close();
reply = newMsg;
}
}
#endregion}
}

c.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){
}
}
}


3. Compile and GAC the dll .
4. Add below line to 2.0 and 4.0 machine.config both at 32bit and 64bit 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.
5. Go to WCF-Custom (or WCF-CustomIsolated) receive location and on Behaviour tab ,
right click and Add-Extension
the you can able to see CustomTechKundanBTSResponse in the list, Add it and provide Success and Fault Response XMLs.




Now Test it eith by your application or by SOAPUI.





No comments:

Post a Comment