WCF服务返回的对象层次结构与预期不同 [英] Object hierarchy returned by WCF Service is different than expected

查看:142
本文介绍了WCF服务返回的对象层次结构与预期不同的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的理解可能是错误的,但我认为一旦你应用了正确的属性,DataContractSerializer就会将完全限定的实例呈现给调用者。

My understanding may be wrong, but I thought once you applied the correct attributes the DataContractSerializer would render fully-qualified instances back to the caller.

代码运行和对象返回。但奇怪的是,一旦我看到返回的对象,我注意到命名空间消失了,通过(Web应用程序)服务引用公开的对象层次似乎变得平坦(不知何故)。现在,我希望这可以来自网络服务......但不是通过WCF。当然,我对WCF可以做什么的理解可能是错误的。

The code runs and the objects return. But oddly enough, once I look at the returned objects I noticed the namespacing disappeared and the object-hierarchy being exposed through the (web applications) service reference seems to become "flat" (somehow). Now, I expect this from a web-service…but not through WCF. Of course, my understanding of what WCF can do may be wrong.

...请记住我还在尝试所有这些。

所以我的问题是...

问:我可以做些什么在WCF服务中强制命名空间通过(服务引用)数据客户端代理呈现?

Q: Can I do something within the WCF Service to force the namespacing to render through the (service reference) data client proxy?

问:或许,我(仅仅)正在消费该服务?

Q: Or perhaps, am I (merely) consuming the service incorrectly?

问:这是否均匀可能吗?

Q: Is this even possible?

服务代码看起来像......

[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession)]
public class DataService : IFishData
{
    public C1FE GetC1FE(Int32 key)
    {
         //… more stuff here …
    }
    public Project GetProject(Int32 key)
    {
      //… more stuff here …
    }
}

[ServiceContract]
[ServiceKnownType(typeof(wcfFISH.StateManagement.C1FE.New))]
[ServiceKnownType(typeof(wcfFISH.StateManagement.Project.New))]
public interface IFishData
{
     [OperationContract]
     C1FE GetC1FE(Int32 key);

     [OperationContract]
     Project GetProject(Int32 key);
}

[DataContract]
[KnownType(typeof(wcfFISH.StateManagement.ObjectState))]
public class Project
{
      [DataMember]
      public wcfFISH.StateManagement.ObjectState ObjectState { get; set; }

      //… more stuff here …
}

[DataContract]
KnownType(typeof(wcfFISH.StateManagement.ObjectState))]
public class C1FE
{
      [DataMember]
      public wcfFISH.StateManagement.ObjectState ObjectState { get; set; }

   //… more stuff here …
}

[DataContract(Namespace = "wcfFISH.StateManagement")]
[KnownType(typeof(wcfFISH.StateManagement.C1FE.New))]
[KnownType(typeof(wcfFISH.StateManagement.Project.New))]
public abstract class ObjectState
{
      //… more stuff here …
}

[DataContract(Namespace = "wcfFISH.StateManagement.C1FE", Name="New")]
[KnownType(typeof(wcfFISH.StateManagement.ObjectState))]
public class New : ObjectState
{
      //… more stuff here …
}

[DataContract(Namespace = "wcfFISH.StateManagement.Project", Name = "New")]
[KnownType(typeof(wcfFISH.StateManagement.ObjectState))]
public class New : ObjectState
{
      //… more stuff here …
}

Web应用程序代码看起来像......

public partial class Fish_Invite : BaseForm
{
    protected void btnTest_Click(object sender, EventArgs e)
    {
       Project project = new Project();
       project.Get(base.ProjectKey, base.AsOf);

       mappers.Project mapProject = new mappers.Project();

       srFish.Project fishProject = new srFish.Project();
       srFish.FishDataClient fishService = new srFish.FishDataClient();

       mapProject.MapTo(project, fishProject);

       fishProject = fishService.AddProject(fishProject, IUser.UserName);

       project = null;
    }
}

如果我不清楚...

出现的问题是我希望看到(返回)的命名空间与实际返回的命名空间不同。

The issue arises in that the namespacing I expect to see (returned) is different from what is actually returned.

fishProject.ObjectState应该看起来像......

srFish.StateManagement.Project.New

srFish.StateManagement.Project.New

fishC1FE.ObjectState应该看起来像......

srFish.StateManagement.C1FE.New

srFish.StateManagement.C1FE.New

fishProject.ObjectState ACTUALLY看起来像......

srFish.New1

srFish.New1

fishC1FE.ObjectState ACTUALLY看起来像......

srFish.New

srFish.New

推荐答案

确定 - WCF服务的默认行为是:

OK - default behavior for a WCF Service is this:


  • 一旦服务启动,您就可以在服务器上定义服务合同,操作和数据合同(例如在命名空间Server.MyService)

  • 运行,在您的客户端上,您创建服务引用

  • 这样做,Visual Studio或 svcutil.exe 做什么,是询问该服务的元数据(服务方法和数据的描述)

  • 基于该元数据,生成客户端代理(名称空间Client.MyService)并且它包含服务的副本合同(方法)和数据合同

  • you define your service contracts, operations, and data contract on the server (e.g. in namespace "Server.MyService")
  • once the service is up and running, on your client, you create a service reference
  • when doing so, what Visual Studio or svcutil.exe do, is interrogate that service for its metadata (description of service methods and data)
  • based on that metadata, the client side proxy is generated (namespace "Client.MyService") and it contains replicas of the service contract (the methods) and the data contract

重要提示:它包含那些东西的副本!它们看起来是一样的,它们在线上串行化为相同的XML格式 - 但它们是不同的 - 在不同的命名空间中,最值得注意的是。

Important: it contains replicas of those things! They look the same, and they serialize into the same XML format on the wire - but they are different - in different namespaces, most notably.

这就是它的本质WCF - 您所做的只是在客户端和服务器之间交换序列化消息 - 所有来回的都是文本消息。没有更多 - 没有对象引用,没有远程对象 - 没有这样的东西。把它扔出你的脑海! :-)

This is the very nature of WCF - all you do is exchange serialized messages between client and server - all that goes back and forth are textual messages. Nothing more - no object references, no remote object - nothing like that. Toss that out of your mind! :-)

如果您控制电线的两端,这可能会很痛苦 - 如果您需要更改任何内容,则必须在服务器端更改它,更新客户端引用等等。

If you control both ends of the wire, this can be a pain - if you need to change anything, you have to change it on the server side, update the client references and so forth.

因此,如果您控制线路的两端 - 服务器和客户端 - 并且它们都是基于.NET的,那么您可以执行以下操作:

So if you control both ends of the wire - both the server and the client - and they're both .NET based, you can do the following:


  • 将您的服务合同和数据合同(仅合同 - 无实施!)放入单独的程序集中

  • 来自您的服务实现,合同程序集的引用

  • 将合同程序集复制到您的客户端,并在您的客户项目中引用它

现在,如果添加服务引用,默认情况下,Visual中的添加服务引用函数Studio将在引用的程序集中重用现有类型 - 因此,如果您引用了常见的Contracts程序集,那么这些类型(完整的荣耀,包括它们的名称空间) )将被重用 - 不会创建额外的副本。

Now, if you add the service reference, by default, the Add Service Reference function in Visual Studio will reuse existing types in referenced assemblies - so if you have referenced your common "Contracts" assembly, those types (in their full glory, including their namespace) will be reused - no additional copies will be created.

这样,您可以创建服务器端代码使用的单个共享契约程序集,以及您的客户,您不必混淆任何重复的数据结构。但是又一次:只有当你控制线的两端,并且两者都是.NET

That way, you can create a single, shared contracts assembly used by both the server side code, as well as your client, and you don't have to mess with any duplication of data structures. But again: that only works if you are in control of both ends of the wire, and both are .NET

这篇关于WCF服务返回的对象层次结构与预期不同的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆