WCF common types not reused
Asked Answered
E

7

19

Hint: This questions has many duplicates, but none of the solutions works for me.

What I have is a web service and a client, both having references to a shared assembly "DataModel". I'm creating the service proxy using the "Add service reference..." dialog and select "Reuse types in all referenced assemblies", but still it creates new types instead of reusing mine.

  • It used to work, but now suddenly it's not reusing types anymore
  • Referencing the shared assembly before adding the service reference does not work
  • Restarting VS2010 does not help (I have all updates)
  • I tried with a simple POCO class (just a simple class containing an integer property), also no luck
  • Deleting and re-adding the service reference (or the shared assembly reference) did not help
  • Only selecting the shared assembly in "Reuse types in specified referenced assemblies" - no luck
  • svcutil.exe /reference yields the same result

I'm at wit's end somehow. Are there any other solutions?

EDIT: I should add that I just reset my project to earlier commits, and whichever commit I use, still the same problem. And I know it worked with earlier commits!

Elect answered 27/11, 2011 at 15:50 Comment(1)
I also faced this Problem. The Problem in my solution was the fact that one library was using another .NET Framework VersionTampon
K
17

Referencing the shared assembly before adding the service reference does not work

You would need to do this, or at least update the service reference after adding the reference.

Deleting and re-adding the service reference (or the shared assembly reference) did not help

and you shouldn't need to do this, but I would've tried it too.

In order for the 'reuse' to work both projects (client and service) need to be using the same version of the assembly. You're referencing the project, which is good - I've encountered this before when referencing the assembly directly because of different versions.

Here's some other things to try

  • Open 'Configuration Manager' for your solution - make sure that the shared assembly is configured to build.
  • Ensure you're using a project reference for both client and service - using the latest assembly on the client won't help if the service is using an older version.
  • Delete the project reference and build, and expect the build to fail - if it doesn't fail then you must be referencing something else.
  • Manually check that the latest 'shared assembly' is being included in the build in both service and client - check the bin folder, check the assembly version / build date.

If all else fails, the best way to force the same object on both sides is to remove the 'service reference' proxy altogether and use the ChannelFactory method. See Simpler Explanation of How to Make Call WCF Service without Adding Service Ref and VS2010 Advantages of Add Service Reference over direct ClientBase<>. This is my preferred WCF pattern because it removes the need to 'Update service reference...', and removes all that generated proxy code.

Kym answered 28/11, 2011 at 0:30 Comment(5)
Good suggestions! Checked all this, and the shared DLLs are the very same build in both service and client. So, my conclusion is that this feature is just not reliable enough for me and I will try and replace the proxy by the IChannelFactory<IMyService> solution.Elect
@Elect The svcutil codegen tool is generally really good but I've had a few problems with it myself; once you use the ChannelFactory pattern you'll see its elegance and probably never go back to 'Service Reference...'Kym
I now changed my implementation to use ChannelFactory<IMyService> with very little effort. This is really a good solution if the contract (IMyService) can be in a shared assembly. Thanks!Elect
How to change the implementation to use ChannelFactory patter? can anyone point me to sample code.Neman
ChannelFactory pattern is a lot easier to share types between project if you have reference to the service dll. For more infomation about the pattern: msdn.microsoft.com/en-us/library/ms734681(v=vs.110).aspxEnergetic
E
14

I just went through an entire day trying to find out why the Types in my shared dll were not being reused when I added a Service Reference in VS2013. It turns out that the service had several problems related to serialization. I had a couple of enumerations that did not have the EnumMember attribute. The way I solved my issues were by trying the following steps:

  1. Commenting out all operations (methods decorated with OperationContract attribute) in my ServiceContract that did not return atomic Types.
  2. Then updating my Service Reference in my client project. I realized that the problem had been resolved when in my client project, I was able type "[MyServiceReferenceName]." and my Types did not appear in the [MyServiceReferenceName] namespace. I verified this by opening the generated XSD files in the XML Schema Browser just to be certain.
  3. One by one, uncomment a method that was commented in Step 1. Then update your Service Reference each time to see if the types are or are not being resued.
  4. Once you find the method that is causing the Service Reference to fail to reuse Types, go to each class for the the Types that are either input or output to the method. Check that all classes that you wish to serialize are decorated with the [DataContract] attribute. Ensure that all fields and properties are decorated with the [DataMember] attribute. Also, ensure enums are decorated with [DataContract] and that each enumeration value is decorated with [EnumMember].

I hope this helps others who are going through this frustrating process and this problem is not necessarily related to a shared dll. My issue was not really an issue with using Add or Update Service Reference. The problem lied with my entity (model) classes not being decorated with the proper attributes to notify the DataContractSerializer to serialize those types. It seems that if any part of serialization fails, adding the Service Reference adds all the Types.

Eccles answered 18/2, 2014 at 16:18 Comment(3)
Here's my experience: It was sharing types, for sure. I had 3 types - 2 classes and an enum where one class references instances of the other class and one property for the enum. I commented out the service code I added, then added a dummy method with [OperationContract] to each one, got the service, verified that there was not a copy, then deleted that code and uncommented the code from before. Oddly enough, that fixed it. I don't know why and to be frank it freaks me out a little.Kaiak
Thank you - I found an enum that I had forgotten to make a DataContract and make EnumMembers for.Rusty
Good advice. It turns out DataContract or lack thereof was my issue as well.Unfix
S
2

It is a bit of a long shot, but one possibility is that an old version of the shared dll is in the GAC.

It tries to use the shared dll, finds a dll with types missing, and then reverts to creating types.

Speckle answered 27/11, 2011 at 19:41 Comment(1)
I'm not using the GAC at all, instead I have a solution with all of my projects, and am using project references.Elect
T
2

OBJECTCEPTION!

We recently had the same problem where I work. It took us four hours to hunt down the problem, but we eventually discovered that an enum on an object within the same dll as the object it was refusing to copy had the same name as another enum that was being used in the service, so it refused to reuse any types from that dll.

Suggestion(solution?): Make sure that there are no other objects in the dlls, or objects on those object, or... etc. that have the same name as one in your service.

Tyro answered 22/8, 2012 at 19:40 Comment(0)
S
1

This is an old topic, but since I ran into the same problem today I want to share my fix.

For me the problem was that the shared assembly was correctly added in both projects (service and client), but on service side this shared assembly referenced another assembly that was not present on client side.

I noticed the error using Svcutil.exe with below statement. Open the commandline in the folder where SvcUtil.exe is located (for me this is C:\Program Files (x86)\Microsoft SDKs\Windows\v10.0A\bin\NETFX 4.6.1 Tools) and execute below statement after changing below segments (marked with <>):

SvcUtil.exe /t:code /language:cs  /r:<path of the .dll that contains the types to reuse on client side> <wcf service url>

make sure that the .dll of the types you want to reuse physically exist in the /bin folder (maybe not there due to build error,...). If needed copy a correct build from the service.

SvcUtil will try to generate service and/or data contracts based on the WSDL document from the specified service. The /r tag specifies where the .dll is located on the client side that contains the reusable types (just like you specify when using "Add service reference").

if there is a problem with reusing types it will be displayed in the command line when the statement is executed.

This can point you in the right direction where the problem lies in your shared assembly.

Scent answered 21/8, 2018 at 14:6 Comment(0)
G
0

After checking all the answers here, nothing worked. Then I realized that my service had an error when viewing the wsdl in the browser. This should be obvious right? Well, see what happened is I opened the service's solution file as a different(none admin) user and updated the name of one of the reusable types. Built my solution and everything built successfully. Which is when I ran into the issue described by the OP.

What happened was, because I logged in with a non-admin account and I wasn't using IIS express. My WCF project did not load. Meaning that the rename of the type did not take effect in the WCF project. Thus causing the issue.

TLDR; make sure your service actually starts and works correctly, before looking for issue in the consuming application.

Geriatrician answered 4/10, 2018 at 10:31 Comment(0)
R
0

I thought I would add another situation to the list of answers: if you have any types that inherit from a common collection, like Dictionary<K, V>, when you choose to reuse types, you either need to choose to Reuse types in all referenced assemblies, or, if you choose to Reuse types in specified referenced assemblies, make sure you choose the System assembly (home to the generic collections) in addition to the assembly that contains your data contracts.

In our situation our class definition was along the lines of:

public class FooMetadata : Dictionary<Guid, FooMetadataType>
{
}

Where FooMetadataType was a [DataContract]. Also note that you cannot decorate this class with [DataContract] because Dictionary is already marked as [Serializable]; your service will compile but upon deployment you will get a YSOD when browsing to the .svc file.

Retiary answered 14/8, 2020 at 17:16 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.