Highlighted
Absent Member.
Absent Member.
4010 views

Consuming WCF in NAtive Code via Managed Code in Visual COBOL

Hi Chris,

The objective is to Consume the WCF Created in .NET 4.5 in Visual COBOL.(In Native Code VIA Managed Code)

To Do this I have followed following Steps:

1. Created an Managed Project in Visual COBOL, Added the Service Reference of .NET WCF. 

2. Selected the Property of Managed project as "Register for COM Interop". I am getting couple of Warning for the same. (Type Library exporter warning Generic Code may not exported to COM.)

3. Created an managed program to create an object of WCF Client Class and call the WCF methods.

3. Created an Native Project and added a Native Program.

4. Provide the Class Control section to point to the OLE object created by Managed Project.

5. Tried to Invoke the Managed Program of Managed Project from Native Program.

I am able to reach to the Managed Program (getting a display from there) But when managed program tries to call the WCF method , I am getting following error " Could not find the default endpoint element that references the contract "IService1". in the service model Client Configuration Section.

this might be because no configuration file was found for your application , or because no endpoint element matching this contract could be found in the client element".

Hope you are able to understand the problem, Let me know if you require any additional info. 

Let us know what can be possible problem in this approach.

Regards,

Charan

0 Likes
7 Replies
Highlighted
Micro Focus Expert
Micro Focus Expert

Because the project which is calling the WCF service is a Class library so that it can be registered for COM it does not pick up the app.config file which is generated by adding the service reference. Only main programs read and use app.config so it is ignored.

To get around this you can set the endpoint parameters dynamically within the COM program when it instantiates the service:

Example:

       class-id WcfCOMTest.Class1.
       
       working-storage section.
       method-id callWCFTest.
       local-storage section.
       01 wcfservice type ServiceReference1.Service1Client.
       01 remoteAddress type System.ServiceModel.EndpointAddress value new System.ServiceModel.EndpointAddress("http://localhost:62048/Service1.svc").
             
       procedure division using by value theValue as binary-long
                          returning theString as string.

           set wcfservice to new ServiceReference1.Service1Client(new type System.ServiceModel.BasicHttpBinding(), remoteAddress)
           set theString to wcfservice::GetData(theValue)
           
           goback.
       end method.
0 Likes
Highlighted
Absent Member.
Absent Member.

Hi Chris,

I did the same what you suggested in the Managed Program which is instantiating & calling the WCF service.

Now i am getting the Error as "Cannot Register the Assembly ..\\ConsoleApplication2.dll. Synchronized Method in Value Type".

Please let me know where i am making the mistake.

Thanks

Charan

0 Likes
Highlighted
Micro Focus Expert
Micro Focus Expert

Not all assemblies can be registered for COM Interop. You must ensure that only COM compatible types are being passed in and out of the interface. I would suggest that you make your COM layer simple so it just accepts parameters calls the WCF service and then returns simple type parameters to the caller.

What does your ConsoleApplication2.cbl program look like?

0 Likes
Highlighted
Micro Focus Expert
Micro Focus Expert

I think that we might have discovered a problem in the area of calling a WCF Service when passing certain types of parameters by value in and out of the interface. The error message that we are receiving is similar to the one you are receiving.

Can you confirm what your service methods are using as parameters? The problem that we found occurs when trying to pass a data only object by value as a parameter in order to pass a COBOL group item. If we change this to set a byte array (type Byte occurs any) to the group item on the client side and then pass the byte array instead then it works ok.

If you would like to create a support incident with customer care and put it to my attention, I would be glad to take a look at your scenario to see if it is indeed the same problem?

Thanks.

0 Likes
Absent Member.
Absent Member.

Our Service methods are accepting Value by Reference and Binary Long parameters.But I am getting error as "Wrong Parameter or Parameter not correct".

Following is the scenario -

When i tried to use the default Method of WCF GetData which accept Input parameter as (by value) Binary Long and returns string (By Ref). then it is working fine.

But when i try to call other method Write it has 4 parameters :-

1. 1stparm  pic 9(2). type - i/p

2. 2ndparm pic 9(8) Comp-5. type -i/p

3. 3rdparm pic x(150). type -i/p

4. 4thparm pic 9. type -i/o

This is method is defined in .NET WCF as iWrite - int32(By Ref String, Binary Long, By Ref String,By Ref String) it returns an int32 value.

When i am trying to call this via Native --> Managed Class --> Class Method -->WCF

My Managed class is register for Interop COM.

when I am invoking it in Native code as after referring it using Class Control and then invoking it as

invoke obj "Class method" using

                                                    1st parm

                                       by value 2ndparm  

                                                    3rdparm

                                                    4thparm

                                     returning  retrun-int (Defined as pic 9(8))

Now in Managed Class Library, in the Method of Class Program

i am calling the WCF like

Procedure Division using

                                       1st parm as string

                          by value 2ndparm  as binary-long

                                       3rdparm  as string

                                       4thparm  as string

                          returning return-int as binary-long

I am getting the Parameter mismatch/not found error , when i am trying to call it from native code.

Let me know how we can solve it.

Regards,

Charan

0 Likes
Highlighted
Micro Focus Expert
Micro Focus Expert

I believe the problem is that you are trying to pass in certain non-managed data types to the web service when they should be managed.

I would recommend packaging these separate parameters into a COBOL group item and then passing the entire record as a string or a byte array. You can then set these back to the group item for processing.

Examples:

01 myparams.
     03 1stparm  pic 9(2).
     03 2ndparm  pic 9(8) Comp-5.
     03 3rdparm  pic x(150).
     03 4thparm  pic 9.  
01 mystring string.  
01 myret binary-long.

          move 50 to 1stparm
          move 987 to 2ndparm
          move "from com" to 3rdparm
          move 5 to 4thparm
          set mystring to myparams
          set myret to wcfservice::TestCall(mystring)
          set myparams to mystring

In the service:

      method-id TestCall public.
      01 myparams.
           03 1stparm  pic 9(2).
           03 2ndparm  pic 9(8) Comp-5.
           03 3rdparm  pic x(150).
           03 4thparm  pic 9.      
      procedure division using mystring as string
         returning myret as binary-long.

          set myparams to mystring
          move 99 to myret
          move "test" to 3rdparm
          set mystring to myparams

          goback.

      end method.

0 Likes
Highlighted
Absent Member.
Absent Member.

Thanks Chris!!! I was able to solve the problem.

It was related to the type of parameter passed (By Ref, By Value). Was wrongly passing by Value data type as By reference.

I have one more query for the example you provided to me in the above thread to handle EndPoint error.

 class-id WcfCOMTest.Class1.

      working-storage section.

      method-id callWCFTest.

      local-storage section.

      01 wcfservice type ServiceReference1.Service1Client.

      01 remoteAddress type System.ServiceModel.EndpointAddress value new System.ServiceModel.EndpointAddress("localhost/Service1.svc").

      procedure division using by value theValue as binary-long

                         returning theString as string.

          set wcfservice to new ServiceReference1.Service1Client(new type System.ServiceModel.BasicHttpBinding(), remoteAddress)

          set theString to wcfservice::GetData(theValue)

          goback.

      end method.

in the example above you have hard coded the endpoint address as "localhost/Service1.svc"

and while creating the object of Service1Client we have provided the (Binding and remote address) parameters.

here we are using the one constructor of Service.

       public Service1Client(Binding binding, EndpointAddress remoteAddress) :  {  }

       public Service1Client (string endpointConfigurationName) :  {  }

      public CalculatorClient(string endpointConfigurationName, string remoteAddress) :  { }

     public CalculatorClient(string endpointConfigurationName, EndpointAddress remoteAddress) : { }

Is there a way where we can use the second consturctor and avoid using the hard coded http address?

we want to use the second constructor by providing only endPointConfigurationName parameter. but not sure how to do it and it will work or not.

Rgerads,

Charan

0 Likes
The opinions expressed above are the personal opinions of the authors, not of Micro Focus. By using this site, you accept the Terms of Use and Rules of Participation. Certain versions of content ("Material") accessible here may contain branding from Hewlett-Packard Company (now HP Inc.) and Hewlett Packard Enterprise Company. As of September 1, 2017, the Material is now offered by Micro Focus, a separately owned and operated company. Any reference to the HP and Hewlett Packard Enterprise/HPE marks is historical in nature, and the HP and Hewlett Packard Enterprise/HPE marks are the property of their respective owners.