Friday, April 18, 2008

Error: System.ServiceModel.Channels

Recently I came across interesting error messages while calling a WCF Service Hosted in IIS 6.0 on Windows 2003 Server. From the error message, I could not figure out the real cause. But after doing some research and changing few configuration information and changing the code, it appears that these solutions fixed these errors.

 Errors

System.ServiceModel.Channels.ServiceChannel.ThrowIfFaultUnderstood(Message reply, MessageFault fault, String action, MessageVersion version, FaultConverter faultConverter)     at System.ServiceModel.Channels.ServiceChannel.HandleReply(ProxyOperationRuntime operation, ProxyRpc& rpc)     at System.ServiceModel.Channels.ServiceChannel.Call(String action, Boolean oneway,  ProxyOperationRuntime operation, Object[] ins, Object[] outs, TimeSpan timeout)     at System.ServiceModel.Channels.ServiceChannel.Call(String action, Boolean oneway, ProxyOperationRuntime operation, Object[] ins, Object[] outs)  at System.ServiceModel.Channels.ServiceChannelProxy.InvokeService( IMethodCallMessage methodCall, ProxyOperationRuntime operation)     at System.ServiceModel.Channels.ServiceChannelProxy.Invoke (IMessage message)    Exception rethrown at [0]:   at System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage( IMessage reqMsg, IMessage retMsg)     at System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type) 
 Or
System.ServiceModel.Channels.RequestChannel.Request(Message message, TimeSpan timeout)     at System.ServiceModel.Dispatcher.RequestChannelBinder.Request(Message message, TimeSpan timeout)      at System.ServiceModel.Channels.ServiceChannel.Call(String action, Boolean oneway, ProxyOperationRuntime operation, Object[] ins, Object[] outs, TimeSpan timeout)     at System.ServiceModel.Channels.ServiceChannel.Call(String action, Boolean oneway, ProxyOperationRuntime operation, Object[] ins, Object[] outs)     at System.ServiceModel.Channels.ServiceChannelProxy.InvokeService(IMethodCallMessage methodCall, ProxyOperationRuntime operation)     at System.ServiceModel.Channels.ServiceChannelProxy.Invoke(IMessage message)    Exception rethrown at [0]:      at System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg)     at System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type)
Solutions
1.       Increase the default value of maxConcurrentCalls from 16 to 50 and maxConcurrentSessions from 10 to 50. You can increase even higher based on your need.
<serviceBehaviors>
    <behavior name=" ServiceBehavior1">
     <serviceMetadata httpGetEnabled="true" />
     <serviceDebug includeExceptionDetailInFaults="true" />
      <serviceThrottling maxConcurrentCalls="50" maxConcurrentSessions="50"/>     
     <serviceTimeouts />
    </behavior>  
   </serviceBehaviors>
 
2.       Use “Using Block” in Service Client to gracefully dispose the object. Also, explicitly close ChannelFactory and Client.
          Using svcClient As ServiceReference1.Service1Client = New ServiceReference1.Service1Client()
           ' Or  Using svcClient As ServiceReference1.Service1Client = New ServiceReference1.Service1Client("EndPointConfigName", "ServiceRemoteAddress")
            'Do the Service related stuff here
            'Before you end the process explicitly Close Client's ChannelFactory and Client
            'Note: Closing the ChannelFactory Closes Client as well but Closing Client does not close the ChannelFactory
            svcClient.ChannelFactory.Close()
            svcClient.Close()
        End Using

Thursday, April 17, 2008

Error: Could not establish trust relationship for the SSL/TLS secure channel with authority

I got this error when calling a WCF Service over HTTPS. A Similar error can also occurs when you try calling a web service programmatically over SSL (HTTPS) and certificate is either not valid or Certificate is attached to a domain and you are not using the domain name but the machine name or IP address. So, what to do in that case if you don’t care about certificate and would like to accept all certificates. I found that it can be done using one of two ways. 

Main Class – Where you are calling the Web Service, add following Import Statements
Imports System.Security.Cryptography.X509Certificates
Imports System.Net.Security
Imports System.Net
 
Public Class MyWebServiceCall
 
    Public Sub CallServiceUsingFunction()
        'Instanciate the Service here
        'Set all paramaters which you need to pass
        'Before You call the Service
        ServicePointManager.ServerCertificateValidationCallback = AddressOf TrustAllCertificatesCallback
        'Call your service Now.......
    End Sub
 
 
    Public Shared Function TrustAllCertificatesCallback(ByVal sender As Object, ByVal cert As X509Certificate, _
                                                 ByVal chain As X509Chain, ByVal errors As SslPolicyErrors) As Boolean
        Return True
    End Function
    Public Sub CallServiceUsingClass()
        'Instanciate the Service here
        'Set all paramaters which you need to pass
        'Before You call the Service
        Dim CertOverride As New CertificateOverride
        ServicePointManager.ServerCertificateValidationCallback = AddressOf CertOverride.RemoteCertificateValidationCallback
        'Call your service Now.......
    End Sub
End Class
 CertificateOverride Class - An Alternate Option
Public Class CertificateOverride
    Public Function RemoteCertificateValidationCallback(ByVal sender As Object, ByVal certificate As X509Certificate, ByVal chain As X509Chain, _
            ByVal sslPolicyErrors As SslPolicyErrors) As Boolean
        Return True
    End Function
End Class

 

Saturday, April 05, 2008

Make a .NET Component accessible in Classic ASP or VB6

I came across a situation again to use exactly same .NET component as COM component in classic ASP page. I had totally forgotten these steps but finally managed to make it work. Later, I thought to put these steps together on my blog, so that if anyone else also don’t know or forget these steps, this will help.


 

1.       In AssemblyInfo.vb -- Add Following NameSpaces, you will have to add their corresponding references
Imports System.Runtime.InteropServices
Imports System.EnterpriseServices
 
2.       Add Following Assembly Attributes
<Assembly: ApplicationName("AppName")>
<Assembly: ApplicationActivation(ActivationOption.Server)>
<Assembly: ApplicationAccessControl(False, AccessChecksLevel:=AccessChecksLevelOption.ApplicationComponent)>
<Assembly: ComVisible(True)>
 
3.       Make sure AssembyVersionAttribute is set to a static value (i.e. 1.0.0.0 not 1.0.0.*)
<Assembly: AssemblyVersion("1.0.0.0")>
 
4.       Make Sure you class has a Public Default Constructor, thus no singleton design pattern or shared Methods.
 
5.       In Signing tab Check Sign the assembly and give a name for strong name key.
 
6.       Compile your project and create the dll.
 
7.       Go to C:\Windows\Microsoft.NET\Framework\v2.0.50727 folder and then run following command to create and register type library,  on command prompt type appropriate path and dll name
 
>RegAsm <PathName>\ProjectName.dll /tlb /codebase
 
Note: You will get a message that Types Registered Successfully. It will create a .tlb (type library file) in the same folder where your dll exist.
8.       Now you can refer the type library file into your Classic ASP Page.
 
9.     If you change and recompile first unregister by adding a switch /unregister of Command Line Param in #7, If you deploy this component on a different machine, perform the step #7 again on that machine.
 
10.   You are ready to use the .NET component in ASP Page now.
 
If Component reads Web.Config file, then you have to do some extra steps
1. In "bin" folder - Create 2 files
              a. Create "application.manifest" file with following content
                          <?xmlversion="1.0"encoding="UTF-8"standalone="yes"?>
                         <assemblyxmlns="urn:schemas-microsoft-com:asm.v1"manifestVersion="1.0"/>

 

 

                       b. Create "application.config" with needed section(s) from Web.Config

       2.  Go to COM+ package through Component Services

                     a. Add your type library file (.tlb ) in your package

                     b. In Properties of the Package go to "Activation" tab  and  change Application Root Directory to <APP_PATH>\bin


     Working Example:  For example let’s create a Class Library Project – Vishwa.Example.ComTest

File: AssemblyInfo.vb
 Class Name : TestProcess.vb
   1:  Imports System
   2:  Imports System.Reflection
   3:  Imports System.Runtime.InteropServices
   4:  Imports System.EnterpriseServices
   5:   
   6:  #Region "Assembly Attributes"
   7:  <Assembly: AssemblyTitle("Vishwa.Example.ComTest")> 
   8:  <Assembly: AssemblyDescription("")> 
   9:  <Assembly: AssemblyCompany("")> 
  10:  <Assembly: AssemblyProduct("Vishwa.Example.ComTest")> 
  11:  <Assembly: AssemblyCopyright("Copyright © 2008")> 
  12:  <Assembly: AssemblyTrademark("")> 
  13:  <Assembly: ApplicationName("ComTest")> 
  14:  <Assembly: ApplicationActivation(ActivationOption.Server)> 
  15:  <Assembly: ApplicationAccessControl(False, AccessChecksLevel:=AccessChecksLevelOption.ApplicationComponent)> 
  16:  <Assembly: ComVisible(True)> 
  17:  <Assembly: Guid("1e411fb7-d23f-4246-99da-4200e999e030")> 
  18:  <Assembly: AssemblyVersion("1.0.0.0")> 
  19:  <Assembly: AssemblyFileVersion("1.0.0.0")> 
  20:  #End Region
   1:  Public Class TestProcess
   2:   
   3:  #Region "Default Public Constructor"
   4:      Public Sub New()
   5:      End Sub
   6:  #End Region
   7:   
   8:  #Region "Public Methods"
   9:   
  10:      Public Function Add(ByVal value1 As Integer, ByVal value2 As Integer) As Integer
  11:          Return value1 + value2
  12:      End Function
  13:   
  14:  #End Region
  15:   
  16:  End Class

In Order to Test in Classic ASP page
Dim obj: Set obj = Server.CreateObject("Vishwa.Example.ComTest.TestProcess")
Dim returnValue
returnValue = obj.Add(2, 3)
Note: I was not able to see the method name Add in intellicense  but it works.