WCF Custom Class Arguments - wcf

I have a WCF method which takes an argument that is a custom class, say,
void MyWCFMethod(MyCustomClass MethodArgument)
In the above, MyCustomClass has a number of constructor overloads. The service has a reference to the class but not the client. I want to allow the client to use the other overloads but the default constructor is the only one that seems to be allowed. Is there a way to do this?

You can certainly do this, but I think it is important to know why the Data Transfer Objects (DTOs) do not expose logic over the service reference.
The WSDL\XSD metadata that is used in order to generate the client proxy to access the WCF Service only describes the web service by the operations exposed and the datatypes exchanged.
Specifically, XSD only describes the structure of your DTOs and not the logic - that is why there is only the default constructor and public properties/fields available on the client proxy.
So the solution is to put all of your custom classes exchanged between the client and service in a separate shared library. This way both sides of the wire have access to the additional logic (like your parameterized constructors) that you could not obtain via WSDL\XSD.

I guess - no!
As I understand MyCustomClass is data contract and marked by [DataContract] attribute.
So WCF runtime will use DataContractSerializer (by default) to deserialize data from received message to the instance of object.
So where can DataContractSerializer get additional parameters for your specific constructors?
Instance of data contract must have public parameter-less constructor to be instantiated.
But maybe you can write own serializer (but keep in mind that DataContractSerializer cannot be inherited)... and provide additional data to constructor. But if you can get that information somewhere just do it in public parameter-less constructor of your data contract.
So I guess you are doing something wrong. Try to specify what is the goal to pass data in constructor in your case. Maybe your app can use some another solution.

Related

Database entity exposed as object in WCF service

I have a WCF service in which I have a method which returns an IQueryable of an object representing a database table (Accommodation) using Entity Framework. When I try and use that method on the client side the method does not return IQueryable but object. I looked at the code for the service and the Accommodation class that Entity Framework generates has this attribute
[DataContractAttribute(IsReference=true)]
So, AFAIK the client should be able to see that class. What is going wrong here?
Thanks,
Sachin
The type will only appear in the metadata if it is used on the contract. The metadata has no idea what IQueryable is - its a definition of behavior whereas the contract only defines state so the generated code will use somethingit does understand in this situation - i.e. object
It is really not a good idea to use the EF generated types on your service contract - you, in effect, tightly couple your service consumers to your data access layer. Use EF internally in the service and use types which define the data you want to pass around on the service boundary

Making an interface visible across WCF web services

I would like to declare an interface in my Web Service layer and then have the caller create objects of this interface type via proxy and use them to call the service methods.
However, when I decorate the interface with DataContract attribute, I get an error saying this attribute can only be applied to class, struct and enum. I don't think that ServiceContract attribute makes sense, as the interface I am trying to expose is used only for data transfer purposes. I also noticed that when the interface was decorated with ServiceContract, it wasn't displayed in the proxy class created.
What is the best practice to go about this?
You cannot do that. "DataContract" interface cannot be exposed as part of metadata. Also even if you share the interface (in assembly) your clients will not be able to send their implementation back to your service because receiving side needs real type for deserialized instance.
The service contract is used on the interface, that is the name of the services. The data contract is used on the class, the data that you are sending over.
ServiceContract on the interface
OperationContract on the methods
DataContract on Class
DataMember on properties
See: http://msdn.microsoft.com/en-us/magazine/cc163647.aspx

Generic DataContract in Agatha WCF

I am trying to use Generic DataContract class so that I don't have to implement several types for a collection of different objects.
Exp :
I have a Profile object which contains a collection of objects.
So I want to have one Profile<Foo> and Profile<Foo1> where profile contains a collection of Foo or Foo1 objects.
I have been reading that WCF does not support generic classes and actually the error that I get is the following.
Type 'GL.RequestResponse.ProfileResponse1[T]' cannot be exported as a schema type because it is an open generic type. You can only export a generic type if all its generic parameter types are actual types.`
Now the ProfileResponse is this Profile object that I am trying to use.
Now in my host I am doing the following. :
ServiceConfig(typeof(ProfileHandler<EducationResponse>).Assembly,
typeof(ProfileRequest).Assembly,
typeof(Container)).Initialize();
This is dhe definition of the handler with the datacontract.
public class ProfileHandler<T> : RequestHandler<ProfileRequest,
ProfileResponse<T>>
The Container is using Windsor Container to register the objects.
The registration works fine but after I instantiated the Service Host for WCF processor, and call Open Method of the host I get the above error.
Is there really no way for me to write generic response requests for wcf with agatha ?
It feels like such a waste to have to define a Profile container class for each type being contained in that collection.
thanks.
One cannot have open generic handlers, because the server side needs to know what the type is.
One can use so called closed generic methods. This way the server side knows the types for witch to load the handler.
Also, one could potentially configure Agatha so that it allows to receive extra information related to the request. In this case, it would be the type wrapped in the response.
One could do this by defining a a BaseRequest class and having all the request extend this class. This class can have a property which takes the type of the response. Or the type to be wrapped in the response.
In the process, when examining the request, the process can get the type to be wrapped in the Response, so that i knows how to load the class.
I have not implemented this, since it would take too much time and I am not sure I want to be responsible for maintaining Agatha for our application, but this is how I would do it.

WCF Web Service parameter

I have a WCF web service that implements a parameter List<ICustomObject>. In the generated client code, the parameter is List<Object>?!? How can I make it accept the List<ICustomObject>, as an interface, or do I have to use a concrete class? I have the concrete class marked as [KnowType] and [Serializable]
You should use concrete class, because you should set DataMember and DataContract for it to serilize it, and with interface you can't do this.
WCF works with anything that is expressible in XML schema - interfaces per se are not.
You need to define your lists to be lists of concrete types - otherwise the client will not be able to know what to do with the list and will fall back to a List<Object>.

Adding methods to DataContract objects for WCF

Are DataContracts in WCF nothing more than DTOs? I was reading up about WCF and just had a couple of thoughts. It would be nice if some of the DataContract objects could have methods on them so that the client could do basic things with them before or after sending or retrieving back to the service.
To me this just doesn't seem possible or logical. I could be wrong, I learn new things everyday. So would the next best thing be to treat DataContracts as DTOs and provide libraries for the clients that would create real objects from the DTOs. Objects that would contain methods.
Any guidance would be really appreciated.
Not sure if I correctly understood your answer, so correct me if I'm wrong.
You can create a class library with your DataContracts classes and share the library between the client and server. In this way class marked [DataContract] will have methods (behavior) and [DataMember] fields/properties (state).
When you will pass such objects between client and server via WCF state will be persisted, but since class library is shared you will have methods on both sides.
DTOs that are decorated as DataContract classes are real objects. They can have methods in them, but the methods are not part of the serialization process.
The main time this will cause you issues is when:
you are relying on the generated proxy version of the DataContract objects (like when you have a Silverlight client calling a WCF service, or you are calling a third party service that you have no access to the code or its libraries). The generated proxy versions will not have the methods in them, just the DataMember properties. The way to get round that is to use objects from a shared library (as already mentioned by #Insomniac).
your properties in the DataContract objects are more than just a simple get/set operation, i.e. you may have included some logic to do other operations when a property value is set. In this case even the proxy generated version will not have that logic included. The ways to get round this is to either have the shared library, or have a partial class on the client side that extends the proxy generated class.
Sharing your classes between client and server projects is the way to go. Do not forget to check in your service reference that it tries to reuse types in referenced assemblies. That way, the service reference will not generate proxy classes for the shared objects.
WCF at its core is a message-based system: your client proxy catches the call to a method, wraps up the method and all its parameters into a serialized message, and send that across the network to the service to be processed.
So yes - in the end, all that goes from client to server in WCF is a serialized message - typically in XML format. You cannot serialize behavior or methods with this approach.