WCF 将对象返回给客户端
我正在尝试使用 WCF,但我认为我遇到了障碍。我的问题是我可以从“客户端”调用 Add(double,double)
和 getPerson()
。但是,我无法调用 Person
对象的任何方法。我用简单的方法剥离了类。这是我的代码片段,请让我知道我做错了什么..
服务器代码
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";
}
客户端代码
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"
我猜测我的 Person 类的声明有问题..但是没有知道我应该做什么或我错过了什么..
谢谢!
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!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
是的,您遇到了障碍 - WCF 是一个基于消息的系统,它仅以 XML 或 JSON 形式、文本或二进制格式交换序列化数据。然而,它不传递“完整”的.NET对象及其完整功能,如方法和所有这些(应该如何?它被设计为可互操作,我不知道看不到 Ruby 或 PHP 客户端如何调用 .NET 对象上的方法)。
WCF 的设计初衷并不是为了远程访问对象,它只是在客户端和服务器之间传递消息。因此,您可以在 XML 模式中表达的任何内容(原子类型、继承和组合之类的任何内容)都可以序列化并在两方之间发送。
任何无法在 XML 模式中建模的内容(例如泛型、接口、方法/代码)都无法在客户端和服务器之间传递。
如果您控制通信的两端并且两者都基于 .NET,则有多种方法和技巧可以解决此问题。基本上,您必须将服务契约和所有数据契约(所有类)放入单独的程序集中,然后从服务器(实现服务契约)和调用契约的客户端引用该程序集。您可以告诉 WCF 重用引用程序集中已存在的类型,在这种情况下,客户端将重用您的现成的
Person
类(及其所有 .NET 优点)公共共享程序集而不是重新创建客户端数据代理。通过这个技巧,您可以让 WCF 通过网络发送序列化消息,而在客户端,您可以重新创建一个成熟的 .NET 对象及其所有方法。再次强调:只要您控制通信的两端,并且两端都使用 .NET,这种方法就很有效。通过这种方法,任何互操作性都被排除在外。
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.
您将两个概念与您的
Person
类型混淆了——您所做的将不起作用。您已在
Person
类型上放置了DataContract
属性。这是正确的,因为您有一个返回Person
的服务。Person
对象将被序列化并返回到您的服务客户端(在本例中为CalculatorClient
)。您应该像这样定义
Person
:在您的计算器服务中:
这是因为您的
Person
对象的工作是保存数据,并将其从服务器传送到客户端。定义方法/操作不是它的工作,而应该在您的服务类中完成(例如CalculatorService)。添加OperationContract
属性并不会神奇地将数据传输对象转变为服务。You are mixing up two concepts with your
Person
type -- what you're doing will not work.You've put a
DataContract
attribute on thePerson
type. This is correct, because you have a service that is returning aPerson
. ThePerson
object will be serialized and returned to your service client (CalculatorClient
in this case).You should define
Person
like this:And in your calculator service:
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 (egCalculatorService
). Adding theOperationContract
attribute does not magically turn the Data Transfer Object into a Service.