Sunday, April 7, 2013

BizTalk Server ESB Toolkit Service ESB.ItineraryServices.Generic.Response.WCF Fails to browse

If you browse this service after installing and configuring ESB toolkit then you receive one of the error depending on if you are using BizTalk 2010 or BizTalk 2013:

BizTalk 2010

Error 855000: Could not find schema file for SOAP header 'ItineraryDescription' at path C:\Program Files (x86)\Microsoft BizTalk ESB Toolkit 2.1\Web\ESB.ItineraryServices.Generic.Response.WCF\App_Data\ItineraryDescription.xsd

BizTalk 2013

An ExceptionDetail, likely created by IncludeExceptionDetailInFaults=true, whose value is:
System.ArgumentException: The value could not be added to the collection, as the collection already contains an item of the same type: 'Microsoft.Practices.ESB.ServiceModel.Helpers.SoapHeaderMetadataBehavior'. This collection only supports one instance of each type.

Cause

By definition, Generic On-Ramp services are meant for not passing the itinerary details with the message and so they don't need to have ItineraryDescription. This is how One Way On-Ramp service also works. However this ESB.ItineraryServices.Generic.Response.WCF On-Ramp service expects to have soap header with Itinerary description as per its configuration but from a deployment perspective there is no ItineraryDescription.xsd in the folder and as a result this error is returned.

Solution

The solution to this problem is to disable soapHeaderMetadata in Web.Config file so that WCF does not try to load the SoapHeader information. So within the serviceBehaviors node change soapHeaderMetadata node attribute enabled=false as follows and recycle the IIS application pool:

soapHeaderMetadata enabled="false"




Friday, April 5, 2013

BizTalk ESB Toolkit Sample Service ESB NorthAmericanServices Fails to execute

If you try to call ESB.NorthAmericanServices/CustomerOrder.asmx web service which is part of Dynamic Resolution Sample provided as part of ESB ToolKit 2.1, then most likely you will get the following error:

There was a failure executing the receive pipeline: "GlobalBank.ESB.DynamicResolution.Pipelines.ESBReceiveXML, GlobalBank.ESB.DynamicResolution.Pipelines, Version=2.1.0.0, Culture=neutral, PublicKeyToken=e457dd48ca33cd6f" Source: "ESB Dispatcher Disassemble" Receive Port: "DynamicResolutionReqResp" URI: "/ESB.NorthAmericanServices/CustomerOrder.asmx" Reason: The document specification from assembly failed to load. Verify the schema for this document specification is deployed and is in the Global Assembly Cache.

Cause

The cause of this issue is the code of ESB.NorthAmericanServices/CustomerOrder.asmx refers to the old dll GlobalBank.ESB.DynamicResolution.Schemas V2.0.0.0.
Most likely Microsoft forgot to regenerate the service code after updating their assemblies to 2.1.0.0 version

Solution

The fix for this solution is to go to ESB.NorthAmericanServces\App_Code\CustomerOrder.asmx.cs file and go to submitOrder method code and change the following line of code:
string bodyTypeAssemblyQualifiedName = "GlobalBank.ESB.DynamicResolution.Schemas.NAOrderDoc, GlobalBank.ESB.DynamicResolu" +
"tion.Schemas, Version=2.0.0.0, Culture=neutral, PublicKeyToken=e457dd48ca33cd6f";

                To
string bodyTypeAssemblyQualifiedName = "GlobalBank.ESB.DynamicResolution.Schemas.NAOrderDoc, GlobalBank.ESB.DynamicResolu" +
"tion.Schemas, Version=2.1.0.0, Culture=neutral, PublicKeyToken=e457dd48ca33cd6f";


Error - The itinerary header could not be found Or There is an error in XML document (1, 2).


Once you resolve the above error then you may get this error depending on how are you calling this service:
NorthAmericanServices is nothing but a re-routing service to CanadianServices and that's why there is no corresponding orchestration.
If you look at closely at DynamicResolutionReqResp_SOAP receive location, it uses a ESBReceiveXML pipeline which uses ESB Dispatcher component to resolve the end points of canadian web service from BRE resolver and then it routes the service call to Canadian service. 

From here the call goes to DynamicResolutionSolicitResp send port, due to its filter on DynamicResolutionReqResp receive port. 

You may receive error "There is an error in XML document (1, 2)." This error occurs on DynamicResolutionReqResp receive port because it tries to route the request to Canadian web service while it receive request for NA web service, the schema for both are different. In order to resolve this issue, You need to make sure you have Inbound and Outbound Map on receive port to convert NA request to CN request on Inbound side and to convert CN response to NA response on outbound side. These maps are already present in Dynamic Resolution sample of ESB

Or
You may also receive "the itinerary header could not be found" on DynamicResolutionSolicitResp send port. Because this port uses ItinerarySendPassthrough pipeline it expects to have itineraryheader to be present in message context and if it does not find it throws this error.

If you call this service from an itinerary it will work on this send port. However in order to call the NorthAmericanServices directly from a .net app, you need to create another two-way send port which use XmlTransmit and XmlReceive pipelines.

Thursday, March 28, 2013

BizTalk ESB Portal Initial Setup Issue

While configuring ESB Portal on my machine I encountered few issues, few of those issues fixes are listed here:

1. The remote server returned an error: (404) not Found

This error details are logged in Eventview, the snippet of the error is shown below:

Application information: Application domain: /LM/W3SVC/1/ROOT/ESB.Portal-1-130089573102692686 Trust level: Full Application Virtual Path: /ESB.Portal Application Path: C:\Projects\Microsoft.Practices.ESB\ESBSource\Source\Samples\Management Portal\ESB.Portal\ Machine name: Process information: Process ID: 10524 Process name: w3wp.exe Account name: NT AUTHORITY\NETWORK SERVICE Exception information: Exception type: WebException Exception message: The remote server returned an error: (404) Not Found. Request information: Request URL: http://localhost/ESB.Portal/default.aspx Request path: /ESB.Portal/default.aspx User host address: 127.0.0.1 User: Is authenticated: True Authentication Type: Negotiate Thread account name: NT AUTHORITY\NETWORK SERVICE Thread information: Thread ID: 7 Thread account name: NT AUTHORITY\NETWORK SERVICE Is impersonating: False Stack trace: at System.Net.HttpWebRequest.GetResponse()

at System.ServiceModel.Channels.HttpChannelFactory.HttpRequestChannel.HttpChannelRequest.WaitForReply(TimeSpan timeout)

Possible Causes

- Database connectivity - Esb Portal Web.Config does not have the correct database settings.
- Underlying web service connectivity issues - Esb Portal uses few web services deployed on IIS, e.g. Esb.BAM.Service, Esb.Exceptions.Service, Esb.BizTalkOperationService etc and if there is any issue with connectivity to these services, then it results in above errors.

Solution

• Check the web.config file for correct database connection strings, if you are testing locally you can replace them from following:

Check now if Esb portal works fine. If not then try and check each of above (under cause) mentioned web service if they are running fine or not, if not and you are facing an error like:

“The requested content appears to be script and will not be served by the static file handler.”

Try following steps:

• In a command prompt, change to the C:\Windows\Microsoft .NET\Framework\v3.0\Windows Communication Foundation\ directory, and then run ServiceModelReg.exe /x /i.

Note: This will ensure that WCF support is fully installed and available.

• Go to C:\Windows\Microsoft .NET\Framework\v4.0.30319\ and run aspnet_regiis –i

• iisreset



2. Index (zero based) must be greater than or equal to zero and less than the size of the argument list.

This error usually comes from BizTalk operation Service which is accessed by Esb Portal. The following error details is from EventViewer.
Application information: Application domain: /LM/W3SVC/1/ROOT/ESB.Portal-3-130089589367504127 Trust level: Full Application Virtual Path: /ESB.Portal Application Path: C:\Projects\Microsoft.Practices.ESB\ESBSource\Source\Samples\Management Portal\ESB.Portal\ Machine name: Process information: Process ID: 8828 Process name: w3wp.exe Account name: NT AUTHORITY\NETWORK SERVICE Exception information: Exception type: SoapException Exception message: An unexpected error occurred during initialization of the BizTalk Operations Service. ---> Index (zero based) must be greater than or equal to zero and less than the size of the argument list.

Cause

It is an access right issue to retrieve information from BizTalk management database.

Solution

• Check BizTalk operation service application pool user account. This user account should be part of BTS_ADM_USERS Database role for BizTalk Management Database.

Monday, October 1, 2012

WCF Service Exception Handling Best Practice

I was working on a WCF service and I needed a way to handle uncaught exception raised during any service operation in a controlled way e.g. I wanted to log or email unhandled exception and send a valid response to client with information required to trace the problem.

One way was to have a try catch in each method and return the fault from there. This approach is simple and works however in case of lots of service operations or lots of services it become very tedious to repeat the same code block everywhere.

So I searched and finally implemented a new common error handler for my service based on WCF interface IErrorHandler. This interface provides two methods HandleError and ProvideFault which you can override to implement your own logic. Once hooked into your service, for any uncaught exception HandleError and ProvideFault methods are invoked. HandleError is the method where you log the errors, and ProvideFault creates a new fault message which becomes your service response.

There are two ways you can hook this handler to your service:
1) using Service Behavior attributes by implementing IServiceBehavior interface and inheriting from Attribute class. and then use the attribute on your service class similar to any other attribute

2) Use service behavior extension by inheriting from BehaviorExtensionElement, which allows to configure common error handler via service web.config file

I have attached here the complete code of this common handler. In order to use this either use method 1 or 2. A sample on how to use is given in ErrorBehaviorAttribute and ErrorBehaviorExtension classes as well.


Please note, this sample code also gives you a common ServiceException class which you need to use as faultContract type in your service contract e.g.
[FaultContract(typeof(ServiceException), Name = "serviceFault")]

If you decide to use this Common Error Handler, The same ServiceException should be used to return your business exceptions. You can always change implementation of these anytime you want, this code only gives you an idea on how to implement these.

Also last but not least, in order to upload the sample to make it available to all of you, I made some changes e.g. namespace and all you may want to change them as per your need.

Happy coding :-)









Monday, May 7, 2012

Convert ASMX web services to WCF


WCF provided much more features and functionality than asmx service out of the box e.g. it implements standards like WS Security, WS Addressing, WS Transaction etc. Performance wise its better than asmx services. See following links for WCF benefits:

http://msdn.microsoft.com/en-us/library/ff648122.aspx

http://msdn.microsoft.com/en-us/library/bb310550.aspx

http://msdn.microsoft.com/en-us/library/aa480190.aspx

For converting an asmx service to WCF we need to take following steps, This approach will choose appropriate serializer depending on the types defined in your asmx service.
  • Create a .wsdl file from current asmx service, you can do this by typing the service url?wsdl in IE and then save the file as .wsdl extension
  • Go to Visual Studio Command Prompt
  • Go to the directory where you saved wsdl file and run svcutil.exe with wsdl file name as argument e.g. svcutil.exe Queue.wsdl
  • The svcutil will generate two files .cs file and .config file. The .cs file will contain your service contract.



  • Create a new WCF Service Application in your solution, This template creates a service1.svc in your project, remove all files associated with Service1
  • Add a new WCF Service by using add item and name it as your own service e.g. Queue
  • Delete the interface file created in above step.
  • Copy your .cs file generated by svcutil to your WCF service application folder and include it in your project. Change the file name to indicate it as an interface e.g. IQueue.cs. You need to change the class name also and its references in the class.
  • In your generated interface file, remove , ReplyAction = “*” string for each operation, see the screen shot:




  • Implement the above interface in your implementation class
  • Build your project, and you should be good to go. 
  • You can now implement your methods by copying your old code to new one or by writing it new.
  • In order test, browse your service in browser or add a service reference to a test project, and it should generate similar interface at your end.

Migrate VB.NET code to C#


There are various reasons to migrate the code to C#, few of them are listed below:

  • C# is an ECMA standards compliant language with a formal definition and a corresponding abundance of third party and open source tools. VB.NET is at Microsoft’s mercy to do whatever they want with it – and they do. VB.NET makes it easy for VB programmer to move to .NET.
  • C# code is faster as generated MSIL from C# and VB.NET is not same always
  • Terseness and readability of code. C# follows the C, C++, Java syntax tradition, while VB is more verbose.
  • IDE Responsiveness – It is difficult to work with a large VB.Net project in Visual Studio
  • Improved Code Quality – C# catches many errors allowed in VB.Net, such as variable use before initialization and dead code. It also doesn’t allow undeclared variables, untyped variables, and untyped methods that are allowed in VB.Net.

We will be using an open source tool SharpDevelop developed by IC# (http://www.icsharpcode.net/). This tool is an open source IDE to develop .NET applications similar to Visual Studio and also gives the ability to convert your entire project from VB.NET to C#. We did a POC to convert eService application to C# and its results are very promising. The only compiler issues I found was the implicit type casting issues which C# does not allow. The steps to convert are listed below:


Note: A web site project first need to be converted to a web application project before you can convert the code to C#. You should also upgrade .NET framework before migrating the code to C#

Convert ASP.NET Web Site project to Web Application project

Web sites projects use visual studio template of web site project which has certain limitation in terms of managing it e.g. its difficult to maintain web.config file for different environments. Web Application template gives the ability to manage web.config file for different environment using transformation file. In this way, you only need to manage the differences in different environment, and do not copy entire web.config for different environment.
To read more about this go to this link http://msdn.microsoft.com/en-us/library/dd465326.aspx

In order to convert a web site to web application project follow the below steps:
  • Create a new Empty Web Application Project (.NET 4.0) in your solution
  • Add all assembly references and web references to the project. Make sure web references use the same name as in old project.
  • Copy all your files from old web site project to new project directory. Do not copy obj & bin directory and your old web.config files.
  • Include all copied files in your project
  • Right click on your new project and click on Convert to Web Application as shown below:
  • Visual Studio will convert your web site to web application project, after this you will notice that there will be a designer.vb or designer.cs will be created for each asp.net page or user control.
  • Compile your project and resolve any issues you have.
  • Copy the relevant and required section of web.config from your old project to the web.config of your new project. Do not copy paste entire stuff
  • You are done for your local development and testing
  • In the project you will notice two extra config files once you expand web.config file. As shown below, you should see two files by default 1) Web.Debug.config and 2) Web.Release.config. These two files are there to manage configuration differences in different build of the project. E.g. in release build you remove compilation attribute debug=true
  • In order to add new config for your test, production environment. Create a new Build Configuration from Configuration Manager.
  • o Right click on your solution, select Configuration Manager
  • o Select New from Active solution configuration drop down
  • o Type your configuration name e.g. QA and copy the settings from Release Configuration
  • o Once you have added the configuration, right click on web.config file and select Add Config Transforms. This option is only enabled if there is an extra configuration for which transformation can be added. As soon as you click on this it will create the web.QA.config file within web.config.
  • To add transformation rule or change configuration in different environments use transformation syntax. You can use msdn link http://msdn.microsoft.com/en-us/library/dd465326.aspx to learn more about those.
  • Once above step is completed, you can publish your web application (right click on project->publish) and web.config file will have the correct settings based on build configuration you selected from configuration manager.