This is my service generated class:
public partial class MyClass : object,
System.Runtime.Serialization.IExtensibleDataObject,
System.ComponentModel.INotifyPropertyChanged
{ }
I'm using my own service. In MyClass I have overridden ToString() but I don't have it in my client. I want either to generate it or as MyClass is partial am I able to override ToString myself?
I know that I can write in generated .cs file. What is the best way to do it and at all should I do it?
If you are defining both the client and the service, you don't need to use the WSDL-generate classes. Move the shared objects into a separate assembly, and reference it from both client and server projects. When you create the service reference, there's an "advanced" option (which I think is on by default) that reuses any known classes from the WSDL instead of generating new ones.
Even better, if you move the service contract into your shared library, you don't even need to create the service reference, you can just call the ChannelFactory directly and eliminate the entire auto-generated proxy class.
I have a demonstration on how to do both of these things on my blog: http://blog.kutulu.org/2012/03/proxy-free-wcf-ditching-proxy.html
If you absolutely need to use the WSDL from the service (e.g. you don't have control over the service side and it could change on you), then you can extend the partial classes that VS creates (as you suggested). Most auto-generate classes you get from VS these days are partial classes specifically to make this kind of extension possible. The downside, of course, is that nothing guarantees client and server's additional partial class methods are the same. I'd definitely consider this a last-resort option.
If you share the dll where overriden method exixts between client and server project, you can use the method. By default, WCF generates each class with only properties declared in the service interface. No method is generated.
You can just create a seperate dll file and put what you want to share between service and client into this dll; and add this dll as a reference to both client and service projects. By default, when you generate the proxy, it will not auto generate the shared classes.
Related
I'm writing a simple command line .NET application that retrieves data from a SOAP endpoint. I'm using WCF and Visual Studio 2017.
The SOAP service has about about 20 endpoints, each with its own WSDL. So far I was able to add a single working endpoint by adding a Service Reference in VS 2017. When I go to the Service Reference dialog, and add the WSDL for the endpoint, VS helpfully generates a Reference.cs with implementation for an Interface, Client, Collection, and Record. So far so good. As long as we're only dealing with a single endpoint.
The problem is that, now all of this auto-generated code is blown out, I need to write some semi-generic code to iterate through and call each of these endpoints. Clearly there's got to be some way to call client.process(requestMessage) without explicitly handling 20+ types.
The problem is that none of these generated classes have any sort of common base class or interface. For example, VS generates client, collection, and record classes for SuperDuperService:
superDuperInterfaceClient
responseMessageSuperDuperCollection
responseMessageSuperDuperCollectionSuperDuperRecord
The signatures for the above types are:
public partial class superDuperInterfaceClient : System.ServiceModel.ClientBase<the_project.SuperDuperService.superDuperInterface>, the_project.SuperDuperService.superDuperInterface {
public partial class superDuperCollection : object, System.ComponentModel.INotifyPropertyChanged {
public partial class responseMessageSuperDuperCollectionSuperDuperRecord : object, System.ComponentModel.INotifyPropertyChanged {
So... what gives? I'm sure I'm missing something completely obvious, but haven't been able to find anything that addresses what you'd think would be pretty straightforward. Apologies in advance most of my exposure to the .NET and C# world has been pretty ad hoc. Thanks!
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 a class as DataContract in my webservice and it inherit from IEquatable.
But my siverlight webservice generated proxy class does not have equals. Can any one tell me why this is happening and is there a way achieve this?
WCF serializes only data from data contracts - no methods or behavior.
That's by default and by design - after all, WCF is a message passing system - you pass around serialized messages only.
WCF is NOT a "remote-procedure call" or "object remoting" system and thus, when creating a proxy, it will make sure the data signature on the wire will be identical (by means of XML serialization) - and that's all it does.
The only option to achieve what you're looking for would be to:
create a separate class library assembly that contains the service and data contract classes
reference that common contract assembly from both your server-side service code, as well as your client-side Silverlight app
when creating a service reference now, Visual Studio will reuse the common, shared classes in the assembly, and not re-create proxy data classes (and loosing the methods in the process)
I've got a situation where I have several web services that I need to consume. I need the ability to perform custom actions in the constructor of the proxy before any calls are made (assigning the configured URL, assigning the SOAP header, etc.).
My first solution is to create a child class that derives from the generated proxy, then make those actions in the constructor of the child class. That way, app code can call the constructor of the child, and get a valid proxy that has the stuff I need.
I'm trying to prevent the app code from calling the constructor of the generated proxy, so people don't accidentally instantiate the proxy without doing my custom stuff. My first thought is to move the generated code into a separate assembly from the child, and make sure the app code only has a reference to the child assembly. This works for the most part, but...
The services contain complex types, defined in the proxy. I need the app code to reference these classes, which means the app code needs a reference to the base assembly anyway, which means they now have access to the generated constructor.
I've tried an overly-complex solution of wrapping each of the generated complex types in an interface, and then hiding the real calls and replacing them with copies of the object as the interface type. This worked once or twice, but it gets ugly really quick.
It seems that the only way I can have everything I want is to remove the public constructor of the generated proxy, and replace it with a protected constructor, then allow a reference to this assembly - they'll be able to work with the complex types, but won't be able to call the constructor. My problem is that the only way I can think of to do this is to manipulate the generated code to change the constructor.
Any ideas? I'm using WSDL.exe to generate the proxies, and there's no option there to hide the constructor. Is there another way that I'm just missing? I suppose I can write a tool to automatically modify the proxy immediately after it's generated, but that just feels ugly to me.
Thanks
Are you stuck using .NET 2.0? If not, then you shouldn't be using WSDL.EXE. You should be using SVCUTIL.EXE or "Add Service Reference".
Instead of creating a derived class, you should create your own wrapper classes, which use the proxy classes. One would use something like MyWrapper.CreateProxy(), which would return a properly-configured instance of the proxy class.
BTW, WSDL.EXE creates proxies using the legacy "ASMX" technology, which has no ability to use the types from the service.
I ended up going with modifying the proxy generated code to make the constructor protected instead of public. The call to WSDL.exe was handled in an automated project already, so it wasn't that big of a deal. This was really the only way I could get everything I wanted.
Instead of doing that, why can't you override the GetWebRequest method? It will be called before the service method call anyways.
If you have added a service reference, implementing message inspector will do same thing.
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.