I am trying to play around with WCF and I think I've hit a block. My issue is that I am able to call Add(double,double)
and getPerson()
from the "Client". However, I am not able to call any methods of Person
object. I've stripped down the classes with bare methods. Here are my code snippets, please let me know what I am doing wrong..
Server Code
namespace Test.WebSvc{
[ServiceContract(Namespace = "http://Microsoft.ServiceModel.Sample")]
public interface ICalculator
{
[OperationContract]
double Add(double n1, double n2);
[OperationContract]
Person getPerson();
}
public class CalculatorService : ICalculator
{
public double Add(double n1, double n2) { return n1+n2 ; }
public Person getPerson(){
Person tempPerson = new Person();
return tempPerson;
}
}
[DataContract]
public class Person{
[OperationContractAttribute]
public string toString(){
return "This is a Person Object";
}
Client Code
ServiceRef1.CalculatorClient client = ServiceRef1.CalculatorClient();//works
Console.WriteLine(client.Add(1.0,2.0)); //this too works
ServiceRef1.Person p = client.getPerson(); // this is OK., but is not doing what I wanted it to do
Console.WriteLine(p.toString()); // I do not get "This is Person Object"
I am guessing something's wrong with my Person class' declaration.. but dint get a clue what should I do or what I am missing..
Thanks!
Yes, you've hit a barrier - WCF is a message-based system which only exchanges serialized data, either as XML or JSON, in text or binary format. It does not however pass around "full" .NET objects with their full capabilities like methods and all that (how should it?? It's designed to be interoperable, and I don't see how a Ruby or PHP client could call a method on a .NET object).
WCF is not designed to make it possible to remotely access objects - it just passes messages between client and server. Therefore, anything you can express in XML schema (atomic types, anything like inheritance and composition) can be serialized and sent between the two parties.
Anything that cannot be modelled in XML schema - like generics, interfaces, methods/code - cannot be passed between client and server.
There are ways and tricks to get around this if you control both ends of the communication and both of them are .NET based. Basically, you would have to put your service contract and all your data contracts (all your classes) into a separate assembly, which you then reference from both the server (implementing the service contract), and from the client calling the contract. You can tell WCF to re-use types that already exist in referenced assemblies, and in this case, the client will re-use the ready-made Person
class (with all its .NET goodness) from your common shared assembly instead of re-creating a client-side data proxy. With this trick, you can have WCF send serialized messages across the wire, yet on the client side, you're re-creating a full-fledged .NET object with all its methods and all.
Again: this works great as long as you control both ends of the communication, and both ends are using .NET. Any interoperability is out the window with this approach.
You are mixing up two concepts with your Person
type -- what you're doing will not work.
You've put a DataContract
attribute on the Person
type. This is correct, because you have a service that is returning a Person
. The Person
object will be serialized and returned to your service client (CalculatorClient
in this case).
You should define Person
like this:
[DataContract]
public class Person
{
[DataMember]
public string Description { get; set; }
}
And in your calculator service:
public Person getPerson()
{
Person tempPerson = new Person();
tempPerson.Description = "This is a Person Object";
return tempPerson;
}
This is because your Person
object's job is to hold data, and carry it from server to client. It is not its job to define methods / operations, which should instead be done in your Service classes (eg CalculatorService
). Adding the OperationContract
attribute does not magically turn the Data Transfer Object into a Service.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With