Ambiguous reference in WCF and client application - wcf

I've managed to reproduce one of the errors in a test project with a similar structure to my production code. It consists of three simple projects:
Common (class library):
namespace Common
{
public enum PrimaryColor
{
Red,
Green,
Blue
};
}
Library (WCF service library), which has a reference to Common:
using Common;
namespace Library
{
[ServiceContract]
public interface ILibrary
{
[OperationContract]
PrimaryColor GetColor();
}
public class Library : ILibrary
{
public PrimaryColor GetColor()
{
return PrimaryColor.Red;
}
}
}
ClientApp (console application), which has a reference to Common, and a service reference to Library called "LibraryServiceReference":
using Common;
using ClientApp.LibraryServiceReference;
namespace ClientApp
{
class Program
{
static void Main(string[] args)
{
LibraryClient client = new LibraryClient("WSHttpBinding_ILibrary");
PrimaryColor color = client.GetColor();
}
}
}
The app.config files in ClientApp and Library are auto-generated and I have not modified them, and I have not changed the default configuration for the LibraryServiceReference in ClientApp.
When I compile this solution, I get the following errors in the ClientApp project:
Error 1
'PrimaryColor' is an ambiguous reference between 'Common.PrimaryColor' and 'ClientApp.LibraryServiceReference.PrimaryColor'
Error 2
Cannot implicitly convert type 'ClientApp.LibraryServiceReference.PrimaryColor' to 'Common.PrimaryColor'. An explicit conversion exists (are you missing a cast?)
please help me to fix this.

Make sure that 'Reuse types in all referenced assemblies' is selected in the Advanced options of Add service reference or Configure Service Reference.

it's because you're building x64 not "AnyCpu". I am running across this right now, and am trying to figure out if it's a bug, or if it's expected behavior.

Decorate your enum like this:
namespace Common
{
[DataContract]
public enum PrimaryColor
{
[EnumMember]
Red,
[EnumMember]
Green,
[EnumMember]
Blue
};
}
Update Your service reference (with checking reuse types just like Mark stated).
Rebuild your client code.

I have had this issue arise in innocuous, unpredictable manners so many times! I thought I'd share how I "fixed" it this last time.
I am using Visual Studio 2013 - but have had the issue down rev.
The ambiguous reference seems to come on by itself. I did nothing of note to cause it. In the latest instance I was debugging some code behind and suddenly I had 7, then 22 then 49 errors - all of the same nature.
I deleted the service reference altogether and re-added it. Simply modifying the re-use type did nothing. My solution has a WCF service, Class Library, UI and a Control Library. I also removed the using - in some code behind, of the class library.
This is an exceptionally troublesome issue which thankfully only occurs about every few weeks. Why this worked? Beyond my pay grade. I feel your pain! Hope this helps. In this case, the error came on, again, when I opened some code behind on a xaml page.

It sounds like you control both the client and the server code. Why do you want to create a service reference, is there a specific reason or is it just deemed easier?
In projects where you control both sides of the client server application you are better of creating a "contract assembly" (which is probably your common assembly). This contains the interfaces and objects that are involved with the contract and should be referenced by both your client and your server. In order to communicate with the service the client creates a proxy class using the ChannelFactory, there is no need to have a dedicated WCF client.
Example:
ChannelFactory<ISampleService> factory = new ChannelFactory<ISampleService>("Binding_from_config");
ISampleService sampleService = factory.CreateChannel();
sampleService.SomeCall();
factory.Close();
The factory pattern also makes it an ideal candidate for injecting your proxy in via IoC.
The benefits of referencing a common assembly over creating a service reference are:
No ambiguous reference as there will be no need for auto generated classes.
You will not have to update your service reference every time you change the contract.

For what it's worth, I was running in to this same error after moving my data contracts to a separate library. Updated the service references multiple times and tried all combinations of the settings for assembly reuse, to no avail.
What eventually fixed it for me was to 1) restart Visual Studio and 2) update the service reference. The auto-generated code in Reference.cs in the service definition looked very different and did not duplicate my data contract class. It used the proper reference from my library. So something must be getting cached in the IDE.
Hopefully someone else finds this useful.

I was able to fix this by right-clicking on the Service Reference and then changing from "Reuse types in all referenced assemblies" to "Reuse types in specified referenced assemblies" and then checking the specific common assembly.

Just remove the reference to Common project from your ClientApp project and the error should go away. When you're creating a proxy for your service, all dependent code from the service must be injected into the proxy. If you want your types to be same as those on the service side, just enable the 'Reuse types' option while generating the proxy code (otherwise they will be put under a different namespace).

The problem here is that PrimaryColor exists in both Common and ClientApp.LibraryServiceReference and you are referencing both namespaces in your class.
To overcome this issue, either explicitly reference the instance that you require, i.e.
Common.PrimaryColor color = ....
or set up an alias:
using Service = ClientLibraryServiceReference;
...
Service.PrimaryColor color = ......

When making the service reference aren't there some options that say something like: "inlcude common types in generated service contract" ?
I have the idea that in your service reference the classes are "copied" and that's why you get this error. Inspect the generated service files, remove then and add them again with "Add Service Reference" and see what options you have there.
EDIT
Although I'm almost sure that the Type PrimaryColor is defined twice. One time in the common project and one time in your service reference, you can also try this in your clientApp (to more explicitely specify the PrimaryColor Type):
Common.PrimaryColor color = client.GetColor();

Related

Share POCO types between WCF Data Service and Client Generated by Add Service Reference

I have a WCF Data Service layer that is exposing POCO entities generated by the POCO T4 template. These POCO entities are created in their own project (i.e. Company.ProjectName.Entities) because I'd like to share them wherever possible.
I have a set of interfaces in another project (Company.ProjectName.Clients) that reference these POCO types by adding an assembly reference to the Company.ProjectName.Entities.dll. One of the implementation of these interfaces is a .NET client that I want to consumes the service using the WCF Data Service Client Library.
I've used the Add Service Reference to add service reference. This generated the DataServiceContext client class and the POCO entities that are used by the service. However, these POCO types gemerated by the Add Service Reference utility now have a different namespace (i.e. Company.ProjectName.Clients.Implementation.WcfDsReference).
What that means is that the POCO types defined in the interfaces cannot be used by the types generated by the utility without have to cast or map.
i.e. Suppose I have:
1. POCO Entity: Company.ProjectName.Entities.Account
2. Interface: interface IRepository<Company.ProjectName.Entities.Account>{....}
3. Implementation: ServiceClientRepository : IRepository<Company.ProjectName.Entities.Account>
4. WcfDsReference: Company.ProjectName.Clients.Implementation.WcfDsReference
& Company.ProjectName.Clients.Implementation.WcfDsReference.Account
Let's say I want to create a DataServiceQuery query on the Account, I won't be able to do this:
var client = new WcfDsReference(baseUrl);
var accounts = client.CreateQuery<Company.ProjectName.Entities.Account>(...)
OR: client.AddToAccounts(Company.ProjectName.Entities.Account)
, because the CreateQuery<T>() expects T to be of type & Company.ProjectName.Clients.Implementation.WcfDsReference.Account
What I currently have to do is to pass the correct entity to the CreateQuery method and have to map the results back to the type the interface understands. (Possible with a mapper but doesn't seems like a good solution.)
So the question is, is there a way to get the Add Service Reference utility to generate methods that use the POCO types that are in the Company.ProjectName.Entities namespace?
One solution I am thinking of is to not use the utility to generate the DataServiceContext and other types, but to create my own.
The other solution is to update the IRepository<T> interface to use the POCO types generated by the utility. But this sounds a little bit hacky.
Is there any better solution that anyone has come up with or if there's any suggestion?
Ok, a few hours after starting the bounty I found out why it wasn't working as expected on my end.
It turns out that the sharing process is quite easy. All that needs to be done is mark the model classes with the [DataServiceKey] attribute. This article explains the process quite well, in the 'Exposing another Data Model' section
With that in mind, what I was trying to do is the following:
Placing the model on a separate class library project C, sharing it with both webapplication projects A and B
Create the data service on project A
Add the service reference on project B
Delete the generated model proxies out of the service reference, and update it to use my model classes in project C
Add the DataServiceKey attribute to the models, specifying the correct keys
When I tried this it did not work, giving me the following error:
There is a type mismatch between the client and the service. Type
{MyType} is not an entity type, but the type in the
response payload represents an entity type. Please ensure that types
defined on the client match the data model of the service, or update
the service reference on the client.
This problem was caused by a version mismatch between project C (which was using the stock implementations on the System.Data.OData assemblies) and the client project B that was calling the service (using the Microsoft.Data.OData assemblies in the packages). By matching the version on both ends, it worked the first time.
After all this, one problem remained though: The service reference procedure is still not detecting the models to be shared, meaning proxies are being created as usual. This led me to opt out of the automatic service integration mechanic, instead forcing me to go forward with a simple class of my own to serve as the client to the Wcf Data service. Basically, it's a heavily trimmed version of the normally autogenerated class:
using System;
using System.Data.Services.Client;
using System.Data.Services.Common;
using Model;
public class DataServiceClient : DataServiceContext
{
private readonly Lazy<DataServiceQuery<Unit>> m_units;
public DataServiceClient(Uri _uri)
: base(_uri, DataServiceProtocolVersion.V3)
{
m_units = new Lazy<DataServiceQuery<Unit>>(() => CreateQuery<Unit>("Units"));
}
public DataServiceQuery<Unit> Units
{
get { return m_units.Value; }
}
}
This is simple enough because I'm only using the service in readonly mode. I would still like to use the service reference feature though, potentially avoiding future maintenance problems, as evidenced by the hardcoded EntitySet name in this simple case. At the moment, I'm using this implementation and have deleted the service reference altogether.
I would really like to see this fully integrated with the service reference approach if anyone can share a workaround to it, but this custom method is acceptable for our current needs.

Error when consuming service : The type name ‘AAA' does not exist in the type ‘YYY.YYY’

I'm trying to consume a WCF 4.0 service in my application. I built, tested, and deployed the service from the ground up. The service works in the WCF test client and can be consumed in any other test project I built. The problem is this one particular application... the only one that matters as it's the reason I built the service.
When I build the application after referencing the service I get an error. The error is "The type name 'AAA' does not exist in the type 'YYY.YYY' ".
The project consuming the service is named 'YYY.Web' and is in the 'YYY' namespace.
The service was initially created in the 'YYY.ReportingService' namespace. It has been changed to a different namespace once this problem started. Is now in the 'MMM' namespace.
I added a using directive 'YYY.Service1'. I also tried aliasing the using directive (using test = YYY.Service1)
To make sure something wasn't messed up with my service and its namespaces, I built a new service with a single method. It takes a string parameter and returns "Hello, " and whatever string is passed. This services also works in the WCF test client and the couple of test projects I created. This service is in the SimpleTestService namespace, BasicService class, with a methiod named GetGreeting. Naming was done intentionally to avoid any possible naming collisions. The error still occurs with this new service.
Any thoughts on this? Thanks!
This one took me a while. Turned out, that "The type name 'AAA' does not exist in the type 'YYY.YYY' " was caused by the YYY.YYY - my consuming class sharing name with its containing namespace.
Solution: rename the consuming class to something that is not equal to the full name of its namespace, i.e. YYY.XXX.
I realize it's and old question, but I just had this problem and the issue was a namespace conflict.
In my case AAA was named ServiceClient and that generated the same error you experienced. Once I removed the namespace conflict (called it ConsoleClient instead) all worked as expected.
I have another issue. Imagine two projects with different namespaces and following classes
Project 1
[DataContract(Namespace="SomeNamespace")]
public class A
{
[DataMember]
public class B { get; set; }
}
Project 2
// Here no DataContract attribute
public class B
{
//...
}
In this case you'll get same error as above. Hopefully this will help someone.
Do you have an old version of the service DLL in the GAC? Your application might be referencing another version of the assembly hence the missing types.
I hope you have updated the service reference after renaming the namespace in the service. Usually you get this error when the client side proxy is not updated with the latest types form the server. You can try updating the service reference.

Reference Windows Form Project From another Windows Form Project in same Solution

I have a solution with several projects most of which are code or control libraries. I have a main windows forms application that references and uses these libraries. What i am trying to do is create a 2nd windows application that extends the main one, but i would like to be able to deploy them as separate exe's.
When i try to add a reference to the new app referencing the main app; all seems fine until i try to run the new app i get several error msgs similar to below:
Error 1 Could not find file 'ADODB.dll' referenced by assembly 'D:\Visual Studio 2005\Projects\X\XX\bin\Debug\XXX.exe.manifest'. <newAppName>
i have tried adding references to all the dll's in the error messages and they are still listed when i try to run the new app. I thought of a few work arounds but they require user changes to maintain separate exe's at deployment. I would like to avoid this if possible. Any ideas?
Thanks in advance, Jeff
Your windows forms applications should not be the point that you extend, the exe files should really just be a shell for launching your process (as much as possible anyways). So this response doesn't answer your specific problem of reference exes as this is not considered good practice.
All the extensions should be made to your code or control libraries off a known interface or contract. Generally the process for extending applications like this is to use alternate or additional DLLs which are loaded at runtime.
Say you have an application called clock which is to display the time.
You can structure your application with a set of contracts (or interfaces) in a referenceable DLL "Clock.Contracts.dll":
public interface ITimeService
{
public string Name { get; }
public Date GetTime();
}
You then have each implementation of this in another DLL ("Clock.LocalComputer.dll", "Clock.InternetTime.dll"
public class LocalTime : ITimeService
{
public string Name
{ get { return "Local Time"; }}
public Date GetTime()
{ return Date.Now; }
}
In the UI/EXE you always reference the interface don't call the implementation.
How do you get an instance of the implementing class, using Reflection to identify if a class in a DLL implements the interface and Activator.CreateInstance to generate the class.
http://gsraj.tripod.com/dotnet/reflection.html
There are patterns like Inversion of Control and Dependency Injection which help to address these things in a standardized way in your application. 3rd party libraries like Castle Windsor, Spring can assist. A google search on these will give you some reading material.
I will say that it can take a while to fully get your head around these things.
ok i found a reasonable work around. Basically you add all the reused forms as existing items, but instead of just clicking add you click the drop down arrow and choose add as link.
It would be great to redesign as JTew suggested above but this gets me where i need to be without having to move code.
You can find more information here
Thanks for all your time looking this over and hopefully is helpful to more
Jeff Spo

Change Casing in WCF Service Reference

I'm creating a service reference to a web service written in Java. The generated classes now follow the Java casing convention used in the web service, for example class names are camelCase rather than PascalCase.
Is there a way to get the desired casing from the service reference?
CLARIFICATION:
With WSE based services, one could modify the generated Reference.cs to provide .NET standard casing and use XmlElementAttribute to map to the Java naming presented by the external web service, like this:
[System.Xml.Serialization.XmlElementAttribute("resultType", Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
[System.Runtime.Serialization.DataMember]
public virtual MyResultType ResultType
{ ... }
Not terribly maintenance-friendly without writing custom code to either generate the proxy code or modify it after it's been generated.
What I'm after is one or more options to present a WCF generated client proxy to calling applications using the .NET casing conventions, achieving the same as I did previously with WSE. Hopefully with less manual effort.
Well, since your WCF client proxies are partial classes, you could always add a second file for the same class, which implements the PascalCasedMethodName for each javaCasedMethodName and then just call the Java method from your new method.
public partial class MyClientProxy
{
......
public MyResultType GetResultType(string inputParam)
{
return this.getResultType(inputParam);
}
......
}
Seems a bit redundant - but that should really work, I think. Since your code is stored in a separate file, it won't be overwritten if you re-create the client proxy - and since it's the second part of a partial class, it will be "merged into" the class definition for your client code to call.

Web services and interface compatibility

Adding a service reference to a web service (this is all WCF) in Visual Studio produces some generated code including a client-side restatement of the interface being exposed.
I understand why this interface is generated: you might be consuming a 3rd party service and not have access to the actual interface.
But I do, and the two are not assignment compatible even though the transparent proxy does indeed exactly implement the interface to which I want to cast.
I can use reflection, but that's ugly. Is there some way to defeat this faux type safety and inject metadata to so I can use an interface with a class?
My specific problem departs from the norm in complicated ways that have to do with a single client that uses some derivatives of a base class directly and uses others remotely via service references. The base class for each server needs to keep references to subscribing clients in a collection for enumeration to notify events, and the problem was type varied due to the use of proxies.
None of these answers solves my specific problem, yet every single answer was instructive and helpful. I found my own solution (use a dual binding) but I would never have figured it out if you hadn't radically improved my understanding of the whole business.
Three excellent answers. How to choose just one? I choose the first, because it directly solves the problem I first thought I had.
If you already have the contract dll at the client, you don't even need a service reference (unless you are using it to write the setup code for you) - you can simply subclass ClientBase and expose the Channel, and use that directly - something like (no IDE handy...):
public class WcfClient<T> : ClientBase<T> where T : class
{
public new T Channel {get {return base.Channel;}}
}
Then you can just do things like:
using(var client = new WcfClient<IFoo>())
{
client.Channel.Bar(); // defined by IFoo
}
You still need the configuration settings in the config to determine the address, binding, etc - but less messy than proxy generation. Also, you might choose to re-implement IDipsoable to deal with the fact that WCF proxies can throw in Dispose() (which is bad):
public class WcfClient<T> : ClientBase<T>, IDisposable where T : class
{
public new T Channel {get {return base.Channel;}}
void IDisposable.Dispose() {
try {
switch(State) {
case CommunicationState.Open: Close(); break;
// etc
}
} catch {} // swallow it down (perhaps log it first)
}
}
When you add the service reference, go to "Advanced" and make sure "Reuse types in referenced assemblies" is selected and that the assembly containing your interface definition is selected. You can also do this with an existing service reference by right clicking on it and going to "Configure".
In order to return an interface from a service you need to use the KnownType attribute:
http://weblogs.asp.net/avnerk/archive/2006/07/31/WCF-Serialization-part-1_3A00_-Interfaces_2C00_-Base-classes-and-the-NetDataContractFormatSerializer.aspx
If you want to return a custom type from the service:
http://msdn.microsoft.com/en-us/library/bb628653.aspx
Does any of that help?