When I use svcutil or some other proxy generator it creates appropriate classes in client. I wonder what is the best way to store this classes to avoid conflicts.
In some other "Common" project and remove generated classes from proxy?
Or just use original classes in service and theese duplicated in proxy?
There are two ways to handle the code for service and data contract classes WCF clients.
Generate everything using svcutil.exe. Don't have any kind of reference from your client project to the service assembly. Just use the classes generated by svcutil.
Reference the assemblies containing the types directly. I sometimes use a separate assembly for my DTO classes, that is references from both the client and the server. When generating the client code with svcutil, use the /reference:<file path> option to tell svcutil to reuse the types from an existing assembly instead of regenerating them.
If you reference the origin assembly, without passing it with /reference to svcutil you'll end up with a mess of conflicts. I guess that's what happened to you.
Related
We are transitioning a WCF based solution over to use gRPC.
We require both the Service and Client code generation that the Grpc.Tools package provides. However, we need the Clients to target .NET Standard 2.0 for comparability reasons.
Services need to call other services, so those projects need to be able to consume both the service stubs and the client stubs.
We also don't really want the service stubs to be exposed to consumers just wanting to use the gRPC clients.
This is proving a challenging requirement to satisfy.
Trial 1:
Have two projects, both importing the same proto files, each set to generate either the Server or Client.
Problem: A consuming project can't reference both server and client project due to the generated messages having duplicate namespaces.
The C# namespace is defined in the proto file itself.
Trial 2:
Separate the proto files out into messages and services. Have a models project which only generates the messages into code.
Have the client and service projects reference the models project, and import the services proto files to have them generate the stubs they need.
Problem: gRPC generates the stubs inside of a static class, which again has the same namespace in both projects so a consumer is unable to determine which version to use.
I now have two routes I can go down.
Option A:
In both the client and server projects, create classes which inherit from the gRPC generated ones so they can be exposed onto a different namespace.
For the services, this isn't so bad. The clients however have two constructors and a instance generation method which would need to be brought over to the child class.
Option B:
Create duplicate proto files for the service definitions, one having a namespace for the service stub and the other having the namespace for the client stub.
Both options have their downsides. Option A is probably the least bad as it doesn't require two files to be manually kept in sync.
Does anyone have any alternative recommendations?
Ideally there would be a way to alter the namespace defined in the proto files somehow when using Grpc.Tools, but reading the documentation, there doesn't seem to be a way to do that.
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.
I have a class implementing some audit methods (AuditcClass.cs). I have also implemented a WCF service that uses the AuditcClass.dll methods.
Now I need to be able also to reference the WCF service from within the AuditcClass. However I cannot simply use the generated proxies to reference it, since there are several conflicts with namespaces.
As first approach, I encapsulated the proxy within another namespace, solving many conflicts, but still introducing new ones with other general classes (as example, Exceptions namespace).
Is there an approach by which I could reference the web service within the class, even if the service uses the same class' methods and enums?
I was able to solve my issue by using the parameter /reference:<file path> of the svcutil tool: References types in the specified assembly. When generating clients, use this option to specify assemblies that might contain types that represent the metadata being imported.
This allowed me to exclude from the generated proxy the shared dlls avoiding reference conflicts.
I have some member functions in three custom classes already created in my service. My objective is to use these custom classes on the client side to access the the member functions in the service. How do I expose these classes with all the member methods in them to the client?
I created these three classes in my service and marked them as "DataContract", and the member functions as "OperationContract". I created an Interface that defines these custom classes as OperationContracts returning an object of each of the classes through implementing them on a separate class.
Unfortunately, I couldn't achieve my objective because two of the classes have a constructor that takes some parameters, whereas the class with no constructor was accessible on the client side but I couldn't see the member methods in the class.
I need your hints on what to do.
That won't be easy to do. One way would be to share the DataContract-decorated types between the WCF server and its clients, i.e. add a reference to your service assembly in the client project and bind the service reference to that assembly reference.
However, that breaks contract implementation independence, as the exact same service assembly will need to exist on both the client and the server, and be kept synchronized every time it changes.
See here for more details.
By default and by design, WCF will only share contracts between client and server, e.g. your services ([ServiceContract]), their methods ([OperationContract]) and the data structures they operate on ([DataContract]).
WCF is a message passing system, so all the client and the server share in terms of the data being passed around is a XML serialized message format. When you add a service reference, the client-side proxy will generate a class for each [DataContract] that will look identical in XML serialized format - only the data is being moved back and forth - no behavior (no methods).
Basically, if you want to expose functionality, you need to have a service method decorated with a [OperationContract] attribute. Methods on your data classes will never be visible to the client - and that's by design.
If you control both ends of the communication and both are .NET based, you can "trick" your way around this limitation:
put all your service and data contracts into a separate class library assembly
use a reference to that common, shared assembly to create your service
before you do an Add Service Reference, add a reference to that common assembly on your client
In that case, the WCF runtime will reuse existing types from that common assembly, instead of re-creating them from the service description. And since that assembly contains the shared code that the server also uses, your classes also have their methods present.
It works ok in a .NET only scenario, but it's really kind of a dirty trick behind the proper service separation facade.
I have sortof the opposite of this question:
wsdl : Generate Proxy for the WebMethods but not the other dependent classes
How can one auto-generate other classes (utility classes) that are useful on the client side but are neither DataContracts nor ServiceContracts? In other words, wanting to extract specific classes instead of including entire DLL's.
Edit: Yes arbitrary classes. I think we will end up extracting those to a DLL other then the ones they're currently part of. Just wondering if there is a way using reflection or tool to copy out only specific classes from a source DLL to a destination DLL. "Proxy" is probably the wrong word because the methods wouldn't call WCF. Instead they would be normal classes, other than that they were copied from a source DLL. (The reason is, not wanting to share all of (decompilable) DLL's.)
If the source dll is something you control, then copying classes is really going to lead to problems down the road. The better approach would be to extract the shared classes to a "Shared" or "Interop" or "Common" dll that the client and server projects can both reference.
Doing this also helps separate data from logic since the shared/interop/common project shouldn't reference anything else and is very simply data containers.
You can't specify method implementaion thru WSDL. In order to accomplish what you are trying to do you would need to create a build script / marcro that creates and compiles a client library which has the proxy and your util methods.
HTH