I wanted to track which IP addresses were sending requests to my WCF service. So I did some investigation and apparently it’s not so hard to retrieve this data. The RemoteEndpointMessageProperty class makes the client IP address and port number associated with the remote endpoint from which a message was sent available. Underneath is a snippet of code that will show how it works.
Today I created a method in my WCF service that would process an ArrayList.
There was no possibility to pass a generic list due to interoperability reasons.
In this ArrayList I would place objects of a certain type. This would then be processed server side.
When calling this simple method my client threw a ProtocolException with the following message:
The formatter threw an exception while trying to deserialize the message: There was an error while trying to deserialize parameter http://tempuri.org/:handlingunits. The InnerException message was ‘Error in line 1 position 342. Element ‘http://schemas.microsoft.com/2003/10/Serialization/Arrays:anyType’ contains data of the ‘http://schemas.mshelp.com/HandlingUnit:HandlingUnit’ data contract. The deserializer has no knowledge of any type that maps to this contract. Add the type corresponding to ‘HandlingUnit’ to the list of known types – for example, by using the KnownTypeAttribute attribute or by adding it to the list of known types passed to DataContractSerializer.’. Please see InnerException for more details.
The problem here is that WCF does not know how to serialize the type of the object that is contained within the ArrayList.
The solution to this is actually very simple, you just need to make the type known to your service.
You can do this by using the ServiceKnownType attribute. You need to place this above your service interface. This looks like this:
In this post I will explain to you how you can configure your WCF proxy client to return a generic list as a collection type instead of an array. When you specify in your service contract that an operation should return a generic list, WCF will by default send your collection over the wire as an array.
If WCF sends this to the client you will lose the point of trying to pass a generic collection to your client. So let’s say you have the following operation:
Now if you are going to consume the service and try to call the method that we just created you will see that you will not receive your generic collection. Instead you will just receive an array of Materials.
You can actually let the WCF service return all sort of collection types, it’s just a matter of configuration. So let’s properly configure it!
Right mouse click on the service reference that we created and select “Configure Service Reference”. Here you will immediately see that you can specify something for the Collection type and the Directory collection type. That’s right…here we can set the correct collection type that the service should return. The directory collection type can also be set here. Let’s configure it to return a generic list.
Now when you hover over the function call, you will see the following:
If you want to use the svcutil.exe to generate your proxy class, you need to use the /collectionType (/ct) switch to specify the correct collection.
For more details check out the ServiceModel MetaData Utility Tool on MSDN library
The DataContractSerializer class is the successor of the XmlSerializer class. Introduced together with WCF. This one is also being used by WCF for serialization by default. You can of course always switch back to the good old XmlSerializer if you want to.
Anyway, if you wanted to serialize a collection with the XmlSerializer you had to use the XmlArrayAttribute.
With the DataContractSerializer you get the CollectionDataContractAttribute class. Personally, I think that serializing a generic list via the DataContractSerializer is easier then with the XmlSerializer. Even with the DataContractSerializer I think they could have done it easier. Youâ€™ll see what I mean in a minute.
Letâ€™s look at some code.
The example will be a simple to-do list. You can specify a name, a due data and multiple tags.
Creating the necessary classes
The class TodoList will contain all the different todoâ€™s and the Todo class contains the properties we already discussed. As you can see I also have two other classes. The TagList and the InternalTodoList, both marked with the CollectionDataContract attribute. You also see that these classes contain the generic lists. I did this because you can only add the CollectionDataContract attribute to a class or struct.
How to Serialize
As you can see I use the XmlDictionaryWriter class, which was also introduced with .NET 3.0.
How to Deserialize
For the desrialization weâ€™ll use the XmlDictionaryReader class together with the DataContractSerializer.
Testing the code
Now for a simple test, letâ€™s add some to-doâ€™s. Donâ€™t forget to define the _myTodoList, which is of course an instance of the TodoList class.
The aforementioned code will generate the following XML.
Hope this post was informative and if you have comments, remarks. Please let me know, any constructive feedback is welcome.
Currently I’m working on a web application project that also uses a WCF service for some operations. We are a big fan of using ALT.NET and are using Castle Windsor to do IoC (Inversion of Control)/Dependency Injection. The problem we were having was the small delay to start up the worker process in IIS. Which is not much you can do about within IIS. (As far as I know) Except for maybe making a wake up service that calls a simple method every x minutes. Just to keep the worker process alive.
If you don’t want to wake up the IIS worker process you can always host your WCF service in a managed application, a windows service for instance. This is something that is always running (if it automatically starts and is not stopped manually of course).
I’m not going to go into the details on why you should use Castle Windsor. Maybe another post. The main goal of this post is to get the WCF service that uses Castle Windsor hosted within the Windows Service. You’re maybe wondering..is this then so complex? Well it can give some problems. You will find many posts on the Internet concerning this matter. However many of these posts focus on hosting the WCF Service in IIS.
What I’m not going to discuss
Like I’m not going to go into the details of Windsor, I’m also not going to say how you create a WCF service or how you create a Windows Service. MSDN Library is a very handy resource for this.
Make Windsor work
To make Castle Windsor work you’ll need to do several things:
- Reference the necessary libraries
- Create a windsor.config or windsor.boo file (or both)
- Create a windsor container
- Add a facility
- Load the config file
- Register the container
One thing I’m going to say is that the Castle project has done a lot of effort into making it all work out. To make WCF and Windsor play nice together you have to use Castle.Facilities.WcfIntegration. This contains a factory for hosting the service, namely the ServiceHostFactory.
The difference between IIS and a managed application
The difference isn’t really all that big..you just have to do the proper config and make sure you do all the aforementioned prep work like you would do it when hosting the service via IIS.
When you would host the WCF service in IIS, you would do all the prep work in the global.asax. You don’t have this in a Windows Service or a console application. So just do this somewhere else. I’m not saying hosting the WCF service in IIS is bad..it has it’s advantages.
Let’s put this into practice
1) Reference the necessary libraries:
2) Create a windsor.config or windsor.boo file (or both)
3) Create and register the WindsorContainer (IWindsorContainer). Normally you would do this in the global.asax. Now you need to define a method where you will do this part.
Now I’ll create a method that will create and register the necessary container. This method looks like this:
Declare a public WindsorContainer:
Create the method, PrepWindsor (This will be called in our main method):
Now we have done all of the prepwork for Windsor. Now let’s create the ServiceHost. We will use the following class for this: Castle.Facilities.WcfIntegration.DefaultServiceHostFactory
As you can see I don’t create any endpoints programmatically. This happens via a config file that I have added. My App.config looks like this:
Ok that should be it! Now you should be able to properly host the service in the managed application.
I would love to hear some feedback or if you have questions/remarks, please let me know.