1

I have started with this project in an attempt to learn CQRS and write maintainable WCF services. However, I have some general questions on WCF. Every time I add a command/query handler contract and handler, I build the projects and then right click the service reference on the client in Visual Studio and choose "Update Service Reference". This usually allows me to work with the new command/query with no issues.

However, more often than I would like, I have to actually delete the entire service reference and then add it back. That is the only way I can get around this error:

There was an error while trying to serialize parameter http://tempuri.org/:query. The InnerException message was 'Type 'Contract.Queries.Countries.GetCountriesStartingWithLetterQuery' with data contract name 'GetCountriesStartingWithLetterQuery:http://schemas.datacontract.org/2004/07/Contract.Queries.Countries' is not expected. Consider using a DataContractResolver or add any types not known statically to the list of known types - for example, by using the KnownTypeAttribute attribute or by adding them to the list of known types passed to DataContractSerializer.'. Please see InnerException for more details.

Then sometimes, I can NEVER get the new command/query to work even if I delete the service reference and re-add it. If I try to add a breakpoint in the WCF service code where the known types are being registered, it never gets hit. It seems the service reference is failing because the new command/query is not registered as a known type.

What is the proper way to refresh a service in this CQRS WCF model? Thanks.


Update 1: all of my trouble comes from EF generating proxy objects and trying to send them through the WCF service. The service doesn't know about proxies, just the POCOs.

@Peter - I'm using EF 5 Code First. I have all of my POCOs in a separate project. I use the repository pattern to retrieve an entity from the database. When I say countryRepository.GetById(myId), a proxy object is retrieved, not a POCO. If I disable ProxyCreation, a POCO is returned but the navigation properties are always null while their respective foreign key ids are populated. Maybe I just need to use .Include for the nav properties when getting something out of the repository? I will have to check tomorrow since I don't have access to the code right now.

Alternatively, I've read a lot about AutoMapper. Could that be used to map my proxy objects to POCOs? Just an idea but that doesn't seem correct.


Edit 2: Turns out I can use ValueInjector to map my dynamic proxy objects to POCOs very easily. I can then send the POCOs over the wire with no issues. See this post for further reference.

Community
  • 1
  • 1
BBauer42
  • 3,549
  • 10
  • 44
  • 81

3 Answers3

3

Don't use add service reference. You can use channel factory and no service reference. This assumes that you can share your data and service contract with the client via add project (or dll) reference.

Add reference to the client. Then build a channel factory. Here is simple article from MSD How to: Use the ChannelFactory

If you cannot share your references you can take a look how to implement generic contract resolver WCF Extensibility – Data Contract Resolver from Carlos Figueira.

Edit 1:

You can use POCO pattern with EF to get navigation properties and divorce yourself from EF specifics.

Petar Vučetin
  • 3,555
  • 2
  • 22
  • 31
  • Thanks for the links. However, after much reading it turns out that my EF DbContext is actually trying to send a proxy object back over the wire. This is causing the problem. I can do this: db.Configuration.ProxyCreationEnabled = false; and the error goes away. However, I then lose the ability to drill into the navigation properties. For example, my State object has a relationship to country. The data the client receives as a CountryCode (the foreign key) populated, but the actual Country object (State.Country) is null. How should these entities be returned to the client? – BBauer42 Feb 04 '13 at 21:27
0

You are not supposed to send entities over the wire. Create DTO/message objects instead that are specific to service methods and map them from/to entities inside the service.

Dmitry S.
  • 8,373
  • 2
  • 39
  • 49
0

The problem is probably caused by Visual Studio's edit and continue feature. Visual Studio spins up an IIS Express or Cassini instance with your WCF service and when accessed for the first time, the WCF service initializes (this is when the container is created and when the GetKnownTypes method is called).

But when adding new types and recompiling, Visual Studio changes the assemblies of the WCF service, but doesn't restart that AppDomain, keeping the web service initialized (since initialization only happens once) but with an invalid configuration.

You can solve this by killing the IIS Express instance every time you start to debug, but of course this is quite annoying. Perhaps you can automate this, but at least the problem will never exist in production, since there's no edit and continue.

Nowadays I usually don't expose my commands and queries as part of the WCF contract anymore. The client and server now just send JSON objects back and forward, while what the WCF service is concerned, it's just a string. Sending JSON over the wire has proven to be very beneficial to me, because:

  • The serializer of JSON.NET is much more flexible than WCF's SoapSerializer (which is just utter pain). JSON.NET can serialize/deserialize immutable objects, collections, dictionaries, simply everything you'll ever need.
  • Not exposing command and query objects as part of the WCF contract removes the complete edit and continue problem completely.
Steven
  • 166,672
  • 24
  • 332
  • 435