Archive

Archive for October, 2010

Functional Programming in .Net

October 21, 2010 Leave a comment

When I was developing my mobile port of Frozen Bubble, I noticed a behaviour that developers should be aware of when they do functional programming. At first I was wondered, but if you think a little bit about it is actually very logical.

I we have the following piece of c# functional code:

Func<IEnumerable<Func<int>>, int> Sum = (enumerable) =>
	{
		int sum = 0;
		foreach (Func<int> i in enumerable)
			sum += i();
		return sum;
	};

Func<int>[] data = new Func<int>[5];
for (int i = 0; i < data.Length; i++)
{
	data[i] = () => i * 2;
}

int result = Sum(data);
Console.WriteLine(string.Format("Result: {0}", result));

What do you think that the result will be?

1 * 2 + 2 * 2 + 3 * 2 + 4 * 2 + 5 * 2 = 30

You are wrong, the result is actually 50.

Because what computer is actually calculating:

5 * 2 + 5 * 2 + 5 *3 + 5 *4 + 5 * 5 = 50

The cause of this is the variable i, the variable is used after the for loop and at that moment the value of i is 5. So the Sum function receives 5 times the value 5. Very logical if you think about it, right?

So how can we fix it? You just have to declare a variable in the scope of the for loop. Then 5 different variables will be created, each containing a number from 1 to 5.

Func<IEnumerable<Func<int>>, int> Sum = (enumerable) =>
	{
		int sum = 0;
		foreach (Func<int> i in enumerable)
			sum += i();
		return sum;
	};

Func<int>[] data = new Func<int>[5];
for (int i = 0; i < data.Length; i++)
{
	int number = i
	data[i] = () => number * 2;
}

int result = Sum(data);
Console.WriteLine(string.Format("Result: {0}", result));

If we now execute the code we get the correct result 30.

Advertisements
Categories: C#, Uncategorized

Using the WCF Service Moniker to communicate between legacy COM applications and new .Net applications

October 5, 2010 29 comments

Introduction

Software engineering is maybe the only engineering discipline were building an entirely new wing to a building is considered maintenance. Applications are extended and modified for years. Applications that once used the most modern technologies of the organization have become legacy themselves, yet in a lot of the cases we want them to be able to communicate with their new siblings.

If your organization used Microsoft Visual Basic in the past, you will probably be migrated to .Net by now. Visual Basic is build around Microsoft’s COM technology, a technology that a lot of developers refer to as “the DLL hell”. With .Net Microsoft has made a clean start. At the same time they made interoperability between .Net and COM possible, but that means that your COM interop assemblies will suffer of the same problems as your old components did in the past.

Enterprise applications build today are using n-tier architectures, where the communication between the backend and the fronted in Microsoft environments is mostly done using (WCF) web service technology. Therefore I will present you another choice for interoperability between COM based applications and the new .Net applications: the COM Service Moniker.

The COM Service Moniker

The Microsoft COM Service Moniker is automatically installed when you install the .Net framework. It can be used in 3 ways:

  1. Using a typed contract
  2. Using a MEX endpoint
  3. Using the WSDL of the web service

In this article I will show you how to consume a simple WCF service using a typed contract and using the MEX endpoint. The COM client used for this demo will be developed in Excel VBA, but you could develop it in every programming language that supports COM components.

The demo WCF service

We will create simple WCF service that accepts a string as input and returns a strings as output. First we create a new “WCF Service Application”:

Inside the project: we create the following service contract:

[ServiceContract]
public interface IHelloName
{
 	[OperationContract]
	string Hello(string name);
}

We implement the service as follows:

public class HelloName : IHelloName
{
	public string Hello(string name)
	{
		return "Hello " + name;
	}
}

Although it is not mandatory anymore with WCF 4.0 to configure the end points, we need to do this for the tutorial because we will need a mex endpoint for the second example. This is not exposed by default in WCF. The configuration for our service is the following:

<system.serviceModel>
	<services>
		<service behaviorConfiguration="serviceBehavior"
		         name="HelloNameService.HelloName">
			<endpoint binding="basicHttpBinding"
				      bindingName="BasicHttpBinding_IHelloName"
			          contract="HelloNameService.IHelloName" />
			<endpoint address="mex"
					  binding="mexHttpBinding"
					  contract="IMetadataExchange" />
		</service>
	</services>
	<behaviors>
		<serviceBehaviors>
			<behavior name="serviceBehavior">
			    <serviceMetadata httpGetEnabled="true" />
				<serviceDebug includeExceptionDetailInFaults="false" />
			</behavior>
	    </serviceBehaviors>
	</behaviors>
	<serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
</system.serviceModel>

This needs to be added into the web.config of the WCF service project.

We are now done with our WCF service, so you can press F5 to start the WCF service.

Consuming a WCF service using a typed contract

Creating the typed contract

First we are going to use svcutil.exe to create the source for a WCF client application for our service. To do this, start the Visual Studio Command Line and use the following command:

Svcutil.exe http://localhost:49170/HelloName.svc /config:EXCEL.EXE.config

You should notice that the tool creates 2 files: “HelleName.cs” and “EXCEL.EXE.config”. The “.cs” file will in a minute be added to a Visual Studio class library project while the “.config” file must be placed in the same location as EXCEL.EXE.

Remark: Please make that the port number is the correct one for the WCF service running on your system.

Remark 2: If your COM application has another name then EXCEL.EXE, you should name the config file “<appname>.exe.config”.

Next we create a cryptographic key pair with: “sn.exe –k helloKey.snk”.  You only need to perform this step once; if you recompile our recreate your typed contract you should reuse the same key pair.

Now we are going to create the class library that will contain our typed contract: create a new Class Library project and the source file generated in step 1 to I and modify the AssemblyInfo.cs to set ComVisible to true.

[assembly: ComVisible(true)]

To compile the class library we must also add a reference to “System.ServiceModel”.

 

 

<!–[if gte mso 9]> <![endif]–><!–[if gte mso 9]> Normal 0 21 false false false NL-BE X-NONE X-NONE <![endif]–><!–[if gte mso 9]> <![endif]–> <!–[endif]–>First we are going to use svcutil.exe to create the source for a WCF client application for

And the cryptographic key created must be added in the signing tab:

Now we can just compile our assembly with Visual Studio and afterwards we register the types in the compiled assembly with “Regasm.exe”. This allows the types to be used in the COM environment:

Regasm.exe <projectpath>\bin\Release\HelloNameContract.dll /tlb

After the tlb is created we are going to open it to view its UUID; therefore enter “oleview” in the Visual Studio command prompt to launch the Microsoft OLE/COM Object Viewer and choose File > View TypeLib and choose the tlb file generated in the previous step. Write down the UUID for IHelloName, because we will need it in a minute.

Finally, we register our assembly inside the GAC:

Gacutil.exe /i <projectpath>\bin\Release\HelloNameContract.dll

Creating the COM client

Now it is time to fire up Microsoft Excel and to open the VBA editor. First to add a reference to typelib we just created for the typed contract.

Finally add the following code to create the service moniker:

Sub ServicemonkercallTyped()
    Dim service As IHelloName
    Dim monString As String

    monString = "service4:address=http://localhost:49170/HelloName.svc," & _
                "binding=basicHttpBinding, bindingConfiguration=BasicHttpBinding_IHelloName," & _
                "contract={3EA9FDEB-1AC5-324D-A7CA-F74422CF4415}"

    Set service = GetObject(monString)

    MsgBox (service.Hello("Excel Typed"))
End Sub

We are now ready to launch the VBA code. You should see the following message:

Remark: In my example I have used Visual Studio 2010 to compile and sign the assembly, but of course you could automate all the steps completely by using MSBuild.

Consuming a WCF service using a MEX endpoint

If you don’t mind static typing or if you don’t want to have a dependency on the type library; using a MEX endpoint can be a good alternative. If you have not done this already, first configure the WCF service to expose the MEX endpoint.

Finally we must add the following code inside our VBA client:

Sub ServicemonkercallMex()
    Dim service As Object
    Dim monString As String

    monString = "service4:mexaddress=http://localhost:49170/HelloName.svc/mex" & _
                ", address=http://localhost:49170/HelloName.svc" & _
                ", contract=IHelloName, contractNamespace=http://tempuri.org/" & _
                ", binding=BasicHttpBinding_IHelloName_IHelloName, bindingNamespace=http://tempuri.org/"

    Set service = GetObject(monString)

    MsgBox (service.Hello("Excel Mex Endpoint"))
End Sub

If you should have customized the contract namespace or the binding namespace, then you should modify them in the connection string. Otherwise “http://tempuri.org/” is always the default value in WCF for both namespaces.

If you launch the VBA code, you should see the following message:

Debugging the COM Service Moniker

If you have made errors while implementing the samples yourself; you will have noticed that exceptions returned by the GetObject call are rather cryptic. Is hard to discover the cause error with a rather general message like “Automation error, Invalid syntax”.

Luckily I have found 2 ways to debug the COM Service Moniker. The moniker is implemented in C# which allows you to intercept its exceptions using the Visual Studio debugger. To do this: we must first configure our Visual Studio debugger to also break on external code, goto: “Tools > Options > Debugging > Enable Just My Code (Managed only)” and uncheck it.

Next we must attach our debugger to the Excel process: “Debug > Attach to process”.

Now, we are ready to relaunch our VBA code, when an exception occurs inside the Service Moniker the Visual Studio will break and show you the managed message.

Although the Visual Studio debugger is a good choice for use in a developer environment; it is impractical in a test or server environment. By using Relfector; I discovered that the Service Monikes uses the System.Diagnostics framework. We can thus configure the moniker to trace its activity. We will configure this with a tool that is part of the Windows SDK: “Microsoft Service Configuration Editor”. The default location for this tool is “C:\Program Files\Microsoft SDKs\Windows\v7.1\Bin\SvcConfigEditor.exe”.

Open the EXCEL.EXE.config created earlier with the Service Configuration Editor and go to the diagnostics information. On that screen you need to enable the tracing and the auto flush.

Besides the Service Configuration Editor, the Windows SDK also contains a tool to view the WCF trace files. You can find it at “C:\Program Files\Microsoft SDKs\Windows\v7.1\Bin\SvcTraceViewer.exe”. When we now restart Excel and relaunch our VBA code, we can see the more readable description of the exception in the trace viewer.

Remark: In a production environment you should not enable auto flush because it will hurt performance.

Conclusion

In this article I have shown a lesser know method for communication between COM based applications and their .Net cousins. Hopefully the examples where clear for all to understand and I hope that I made my point clear that the Service Moniker is a very powerful feature. Altough I have used Visual Studio 2010, you could also use Visual Studio 2008 and .Net 3.5 for the implementation of the WCF service. If you have further questions, don’t hesitate to contact me.

Categories: C#, WCF Tags: , , ,