Sunday 30 March 2014

Programmatically configuring an WCF service without using .config files (using FluentSharp REPL)

This post will show how to consume an WCF service directly, firstly using VisualStudio and secondly using the O2 Platform C# REPL environment.

The VisualStudio example will use the FluentSharp – C# REPL NuGet package (which will also show how to dynamically program the WCF service in a REPL environment

Part 1) The WCF test service

In VisualStudio start by creating a new WCF Service Library project called WcfServiceLibrary1

image

Running this project will open the WCF Test Client

image

Create a new Windows Form project called WCF_Consumer

image

Open the NuGet Package manager and add the FluentSharp – C# REPL package (just searching for REPL will show it)

image

Open the Add Service Reference and add a reference to the WcfServiceLibrary1 :

image

This will add the Reference.cs file shown below to the project (usually hidden from the main VisualStudio project explorer, but easily seen if you click on the Show All Files button for the current project)

image

The app.config file now contains the WCF configuration mappings:

image

Part 2) Consuming the WCF service (inside Viausl Studio)

Now that we have the WCF client in place let’s use the FluentSharp REPL to script it.

To do that follow these steps:

1) set the project target framework to be .NET Framework 4 (by default it is .Net Framework 4 Client Profile)

image

2) delete the Form1.cs file

image

3) open the Program.cs file

image

4) delete the default code

image

5) create a new instance of the WCF ServiceReference1.Service1Client  object and call the FluentSharp .script_Me() Extension Method

image

6) make the WCF_Consumer the Startup Project and press F5 to run the project (i.e Start Debugging)

image

7) The FluentSharp REPL environment will appear (created via the .script_Me() method), and the auto compilation will fail due to a missing reference (note the error message)

image

8) add the line //O2Ref:System.ServiceModel.dll  to the script (note that this is a C# comment that tells the REPL engine to add that reference), and click on the Execute button

image

9) the service1Client object is live instance of the ServiceReference1.Service1Client object, so if we start typing (for example “.Get”) we will get the Code Complete popup, which in this case shows the GetData(int value) method:

image

10) In this case if we execute

           return service1Client.GetData(42); 

... we will get

           You entered: 42

.... in the Output window

image

To confirm that we are actually running the WCF web service, let’s put a breakpoint on the GetData method:

image

… which will be hit when we click on Execute:

image

11) We can also create, send and receive WCF objects (see in the example below the creation of the CompositeType object , its use on the invocation of GetDataUsingDataContract and the modified value in the Output panel)

image


Part 3) Configuring the WCF service programmatically

In the examples shown above the WCF client service was configured using the data set in the app.data file.

In order to access the WCF programmatically, we must first delete the app.config file (or comment out the WCF section)

image

Once that is done, if we try to run the application we will get an InvalidOperationException :

image

The exception was caused by the call to new ServiceReference1.Service1Client(), so lets call .script_Me() on the CompositeType instead

image

Running the WCF_Consumer project will now open the script_Me popup:

image

… which (as before) needs an extra reference to compile ok:

image

If we call the WCF_Consumer.ServiceReference1.Service1Client(); constructor, we will get the same error as before:

image

Note: as with the //O2Ref: special comment added before, you can use the //using:  to indicate an namespace import.

The code bellow is the same as the example shown above (except that there is no need to use the full qualified name on the Service1Client constructor call)

image 

The solution is two create the WSHttpBinding and an EndpointAddress objects, which are then used on the ServiceClient constructor (note how in the example below the binding and endpoint values match the old app.config values:

image

We can also use the same technique to call the GetDataUsingDataContract method:

image

Since the REPL script is a full C# code, we can use Lamda methods to refactor the creation of the service and its invocation:

image


Part 4) Consuming WCF service from the O2 Platform

If you have the O2 Platform installed you can also access this service reference from its C# REPL environment:

1) In VisualStudio find the Reference.cs file and add two compilation references (using the syntax: //O2Ref:{assemblyname}}   (also copy this full path to this file)

image

2) In the O2 Platform open the C# REPL Script UI:

image

3) add an //O2File reference to the Reference.cs  file (in this case you will need to use the full path (you should get no compilation errors):

image

4) Create a Service1Client object and note that it throws the same ‘Could not find default endpoint’ we saw before:

image

5) use the WSHttpBinding and an EndpointAddress objects to configure the Service reference, call the GetDataUsingDataContract  and (in the example below) set the textBox value to the returned object StringValue property

image

Part 5) Creating an standalone exe

1) change the way the topValue variable is created (using the .popupWindow method instead of the injected panel variable)

image

2) execute the script and confirm that there is now a popup window showing with the TextBox containing the StringValue of the WCF service call

image

3) right click on the script and chose the option ‘package current script as StantAlone Exe’

image

… a new window will appear containing the created exe file (note: the reason the file was called tmp999A.tmp.exe is because we didn’t save the script, if we had, the exe name would had been based on the script name);

image

4) click on the tmp999A.tmp.exe (which is 667 Kb) and confirm that the WCF call was successfully made

image


Source code for samples

See this gist for the main code snippets used in this post: