I have 2 WCF services (different projects) sharing a class library with a MyExceptions defined.
Both services uses:
[OperationContract]
[FaultContract(typeof(MyException))]
void op();
When I add both references in the client project I get:
Type namespace.MyException already defines a member called MyException
with the same parameter types.
Basically the classes has the same name so the constructor is defined twice.
Any Idea of how to change the Exception namespace?
Please note that:
I am using svcutils
the namespace option doesn't work.
Thanks
Create the proxy using svcutil /reference:SharedLibrary.dll. This way svcutil won't generate classes that it finds in the SharedLibrary.dll, so the client uses the class definitions from the assembly.
Don't forget to add a reference to the DLL in the client project, if you haven't already done so.
Besides the namespace suggestion what can be done is to edit the proxy code generated by SVCUTIL and remove the duplicate code for the MyException class.
The steps:
1. Create a proxy file for Service1.
2. Create a proxy file for Service2.
3. Add the proxies to the client.
4. Compile and it gives error for having MyException already being declared.
5. Edit either one of the proxies and remove the MyException class code.
Related
Here is my issue: in a project I have to consume 3 third-party wcf services. 2 of those contain the same objects and largely the same methods.
The user's role within the application determines which service to use. For example: Let's say the 2 services are ServiceRoleA en ServiceRoleB. Both services contain the method GetInfo() end return the InfoDetails object. The InfoDetails object has the exact same signature for both services.
If I just add 2 service references to my project I'll get the objects ServiceRolaA.InfoDetails and ServiceRoleB.InfoDetails. Instead, I need just one object InfoDetails. I only want to write just one routine to handle the InfoDetails etc.
My initial thought was to create an assembly with the datacontracts of the services and reference the assembly in my project. This way the service references can use the common set of objects. For this to work I have create the datacontract classes using svcutil and the wsdl, but I get error upon error.
When I try the following:
svcutil *.wsdl /dataContractOnly /n:*,DataContracts
/language:C# /out:XxxData.cs
I get the following error:
"Error: Type 'AuthenticationBase' in namespace 'http://schemas.datacontract.org/2004/07/xxx' cannot be imported. It references 'KindOfModule' from namespace 'http://schemas.datacontract.org/2004/07/yyy' but schema does not contain appropriate statement. Either change the schema so that the types can map to data contract types or use ImportXmlType or use a different serializer.
If you are using the /dataContractOnly option to import data contract types andare getting this error message, consider using xsd.exe instead. Types generatedby xsd.exe may be used in the Windows Communication Foundation after applying the XmlSerializerFormatAttribute attribute on your service contract. Alternatively, consider using the /importXmlTypes option to import these types as XML types to use with DataContractFormatAttribute attribute on your service contract."
Exporting the datacontracts as XML types is no option for my so the next thing to try was:
svcutil *.wsdl /dataContractOnly /n:*,DataContracts
/serializer:XmlSerializer /language:C# /out:XxxData.cs
Which resulted in the exact same error. So I decided to try the other mentioned option to use XSD.exe. But that is also nog working since I only have a WSDL and XSD.exe requires a XSD file. Are there any more options I can try? Please help!
You don't need to add service references or using svcutil to create the client proxies, that is easily done by hand.
Create a contracts assembly that contains all service interfaces and data contracts.
Reference that assembly from both the server(s) and the client (be sure to update the web.config and .svc files to reflect these changes)
Create client proxy classes for your services.
A client proxy is as simple as adding a class like
public class ServiceRoleAClient : ClientBase<IServiceRoleA>, IServiceRoleA
{
public InfoDetails GetInfo(GetInfoRequest request)
{
return Channel.GetInfo(request);
}
}
The only drawback is that you'll have to maintain the system.serviceModel node in the app.config file yourself.
following a previous question I posted on StackOverFlow I have the following project structure to my Prism desktop application.
Class Library : Application.Common --> this contains all my DTOs and the service contracts that are defined in my WCF service layer which is an entirely different solution.
Modules: Application.Modules.ServicesModule --> in here I have added links to my WCF implementation using Add Service Reference. I also register the implementations of my types IMyServiceContract is defined in the Application.Common assembly so the initialise method looks as below:-
public void Initialise()
{
_container.RegisterType<IMyService, MyServiceClient>(new InjectionConstructor());
}
Finally I have another module Application.Modules.FunctionalityModule this has a constructor defined as follows
public FunctionalityModule(IMyService myService){}
when the application is trying to resolve the dependency in FunctionalityModule at runtime the following error occurs
Exception occurred while: while resolving.
Exception is: InvalidOperationException - The current type, AccountsSln.Common.ServiceContract.IMyService, is an interface and cannot be constructed. Are you missing a type mapping?
Normally, I have seen this error because a dependency has not been registered but on this occassion I know it has in the ServicesModule. Is this something to do with the registering being in different modules? Are there any other suggestions on how I can implement my project structure to support WCF services in a Prism desktop application?
Thanks
Alex
Edit:
As I wanted to use a Common assembly to define my service contracts I was having problems when using Add Service Reference. It turns out that if you use Add Service Reference the generated code uses the metadata to create client side types. These have the same signature as the ones in the Common assembly but are different. To enable me to use the contracts in the Common assembly I took inspiration from this post http://xaml.geek.nz/working-slightly-smarter-with-wcf. This got me started in the right direction but I think I will have to look into making the code more suited to a production environment.
The problem is that you have not specified the required mapping from the interface to the implementation type. (I prefer using UnityContainerExtensions).
unityContainer.RegisterType < IStudentSearchService, StudentSearchService > ();
You also need to specify module dependencies. Your FunctionalityModule is dependent on the ServicesModule. How this is accomplished depends on how the ModuleCatalog is created.
So either; in Bootstrapper's CreateModuleCatalog use moduleCatalog.AddModule, or decorating the IModules with ModuleAttribute and ModuleDependencyAttribute if using the DirectoryModuleCatalog.
Of course the UnityContainer can be configured through the app.config file.
The generated service proxy classes are partial classes. You might be able to just make them inherit from the IMyService in the Common assembly, by adding something like following in the project where the service references are:
using Application.Common.IMyService;
namespace Application.Modules.ServicesModule
{
public partial class MyServiceClient : Application.Common.IMyService
{
}
}
My first question so hope it is suitable:
Shared interface assembly - I have a 'shared' assembly which has an interface, let's call it IDocRepository. It's marked with [ServiceContract] and there are several [OperationContract]-marked methods.
WCF implementation assemblies - I have two WCF service projects, each referencing the shared assembly, each implementing that interface as a WCF service.
Consumer assembly - Finally, I have a 'client' project, also referencing the shared assembly, with a reference to each of the two WCF services.
However, the service references generated in the consumer assembly derive from an auto-generated version of the interface:
public partial class ExampleClient : System.ServiceModel.ClientBase<SomeNamespace.ExampleSvcRef.IDocRepository>, SomeNamespace.ExampleSvcRef.IDocRepository {
What I expected
I would have hoped that both references would instead automatically inherit the interface I defined, that the consumer/client assembly is also referencing. Kind of like the re-use of classes that it provides for parameter and return types, but for the service interface.
Why
So that I can create an instance of either service reference proxy and cast it to my interface type.
So I could modify the generated code by hand each time, but there should be better way...?
(edit: I do have 'Reuse types in referenced assemblies' and 'Reuse types in all referenced assemblies' options selected for both service references)
"Reuse types in referenced assemblies" only allows you to reuse Data Contracts, not Service Contracts. If you want to share Service Contracts, you don't need to use "Add Service Reference" at all. You can just use ChannelFactory directly.
// Supply the binding and address in code
Binding binding = new BasicHttpBinding();
EndpointAddress address = new EndpointAddress("http://tempuri.org/address");
IServiceContract channel = ChannelFactory<IServiceContract>.CreateChannel(binding, address);
// Or read them from the config file
ChannelFactory<IServiceContract> channelFactory = new ChannelFactory<IServiceContract>();
IServiceContract channel = channelFactory.CreateChannel();
The channel object will also implement ICommunicationObject, so you can cast it if you need to call methods like Open() or Close().
Visual Studio does not support reusing you existing interface when generating the proxy classes for you. Reuse types will not reuse the contract interface as Quartermeister pointed out.
We have solved it with inheritance. Quite similar to the partial class idea above suggested by Jester Software.
This is how we solved it:
In the project of your client just create a service reference as you would have done. Then add a class that serves as the replacement for the client:
internal class MyServiceProxy : MyServiceClient, MyLogicNamespace.IMyService
{}
This class inherits from the generated MyServiceClient but states that that client does implement the original interface.
(I suggest you put them in a folder named "ServiceProxies")
If the MyServiceClient class contains any methods that do not match with the original interface then you can add them in that proxy and do the conversion in code.
After this, just use the MyServiceProxy where you would have used MyServiceClient.
When you create the service reference, there is a box you can tick to make it reuse the shared definitions. Make sure the client project is already referencing the shared assembly, add the service reference again, and check all the options carefully.
If it still doesn't work, check the binding you use. I have a vague recollection that basic HTTP binding won't support re-using of types?
There is another good option, if you want to continue to use the proxy generator for it's limited-but-somewhat-useful functionality... Use a partial class:
namespace <same namespace as generated proxy>
{
public partial class MyClient : <namespace of "real" service contract>.IServiceContract
{
}
}
Ensure that the proxy is generating code the same way your Service Contract is defining it, ie, if it's using 'List', use that option in Configure Service References as well. In other words, make sure your generated Service Interface is exactly equal to your real Service Interface and the above code should work, and to update the reference you use right-click instead of writing code.
My service uses a type Foo defined in another DLL, and my client also uses that DLL to get that type. Rather than generating a proxy class for that type, I'd like the proxy code to just refer to the real type. I can accomplish this manually by generating the proxy with WSDL.EXE on the running service, manually editing out the partial class Foo definition from it, and adding a Using statement. I'd like to do it without hand-editing if possible.
It seems like maybe the answer is to use SVCUTIL.EXE instead of WSDL.EXE. There are two intriguing options: /R and /ET. I tried putting /ET:Foo and /ET:My.FQN.Util.Foo, and /ET:www.my.com.the.servicenamespace.Foo, and also adding the DLL filename to the option. But nothing changes in the ServiceWithFoos.cs proxy class that gets created. The partial class definition for Foo is still there.
Am I on the right track? What am I doing wrong?
Add [DataContract(Namespace = "http://anything.here")] to your Foo type, then use svcutil with the /r option taking the path of the library containing Foo. This way svcutil should see the same contract namespace and map Foo correctly.
I have a WCF Service project in Visual Studio 2008 that contains about 12 methods, some of which return primitive types like bool or string. I also have a Visual Studio Unit Test Project that references the published WCF Service. The Test Project compiles successfully when all the return types are primitive.
If I add a new method to the service that returns a custom class, publish it and update the service reference in the Test Project, it doesn't compile. The errors are: -
The type 'PublisherFaultException' already contains a definition for 'Reason'.
The type 'PublisherFaultException' already contains a definition for 'PropertyChanged'.
Type 'Publisher.Test.LibraryReference.PublisherFaultException' already defines a member called 'RaisePropertyChanged' with the same parameter types.
all in the auto-generated reference.cs file.
The contract for the method of the WCF Service is: -
Page GetItem(string path);
and the Page class has the DataContract attribute and it's public properties have the DataMember attribute.
I'm reluctant to modify the Reference.cs file as I'll need to do this every time the Service is updated.
Anyone know why this is happening?
Stuart.
When you Add Service Reference, you get a 'reuse types in assembly' option - this is likely to be the key to sorting out the duplication.
Or do you have some Test References that are causing the duplication?
Also, have a look in the References section of the project tree and see if there is anything unexpected in there (do you have references to 2 assemblies that both contain Service References in the same namespace?).
Using auto-generated proxy class it is always pain.
To handle situation like this I using separate assembly with data contract classes and service interface.
Contract dll will have:
public interface IService
{
[OperationContract]
List GetContentList();
}
[DataContract]
public class ContentItem
{
[DataMember] public string Name;
[DataMember] public object Data;
}
The client will have reference to the Contract.dll.
Proxy will be created manually:
class ServiceProxy : ClientBase<IService>, IService
{
public List GetContentList()
{
return Channel.GetContentList();
}
}
The server dll will have reference to the same Contract dll.
So we will be able to avoid any errors with auto generated proxy.
Also the manually created proxy will be simpler, more manageable.
When adding the Service Reference, try clicking Advanced, and select "Generate asynchronous operations".
I think what was happening was that there were some asynchronous methods in the web service, with names ending in "Async", which would conflict with the methods generated in the References.cs.
e.g. imagine the web service contains 2 methods: (1)SayHello and (2)SayHelloAsync.
Generating using the default task-based method produces:
SayHello and SayHelloAsync for (1)
SayHelloAsync and SayHelloAsyncAsync for (2).
The conflict occurred because there were 2 generated methods called SayHelloAsync.
At least I think that's what was going on. Anyway setting "Generate asynchronous operations" worked for me.