避免在REST服务中序列化某些属性

时间:2010-09-23 08:25:24

标签: .net wcf nhibernate rest serialization

我在客户端和服务器端分割了.Net应用程序,服务器提供REST服务(使用WCF)。我有这样的服务定义:

[WebGet(UriTemplate = "/Customers/{id}")]
Customer GetCustomerById(string id);

[WebGet(UriTemplate = "/Customers")]
List<Customer> GetAllCustomers();

使用Fluent NHibernate和Lazy Loading将Customer类及其朋友映射到数据库。如果我从会话范围之外的服务返回,则服务调用将失败,因为它无法序列化引用的延迟加载的Orders属性(请参阅末尾的类def)。问题是我需要延迟加载,因为我不希望我的GetAllCustomers - 服务获取所有引用的订单。所以我想做的是以某种方式通知序列化程序,以便它不会尝试序列化GetAll上的Orders。但请注意,必须在GetCustomerById上序列化相同的属性 - 因此我必须在服务上指定此属性。可以这样做吗?!

课程:

public class Customer
{
    public virtual int Id { get; set; }
    public virtual string Name { get; set; }
    public virtual IList<Order> Orders { get; set; }
}

public class Order
{
    public virtual int Id { get; set; }
    // ++ 
}

4 个答案:

答案 0 :(得分:3)

如果您正在使用WCF的默认序列化 - 我认为您这样做 - 您将明确标记要通过网络发送的属性,并保留其余部分。这是使用[DataMember]完成的,我假设你这样做:

[DataContract]
public class Customer
{
    [DataMember]
    public virtual int Id { get; set; }

    [DataMember]
    public virtual string Name { get; set; }

    // not decorate 
    public virtual IList<Order> Orders { get; set; }
} 

<强>更新 好的,你需要有时发送而不发送其他时间。显然,您可以拥有CustomerBase类(没有订单),然后是Customer(订单未装饰)和CustomerWithOrders(装饰订单)。从每个操作中发送每个操作。

如果这不适合您,请在此处使用DataContractSerializerOperationBehaviorIDataContractSurrogate查看自定义序列化:

http://msdn.microsoft.com/en-us/library/system.runtime.serialization.idatacontractsurrogate.aspx

http://msdn.microsoft.com/en-us/library/system.servicemodel.description.datacontractserializeroperationbehavior_members.aspx

答案 1 :(得分:2)

为不同的场景设置不同的DTO,然后使用Automapper将你的nhib对象转移到DTOs - 这样你就可以为每个案例设置一个特殊的对象图,然后你就无法进行迭代,从而为你的集合提供保湿不想。

答案 2 :(得分:1)

我要为GetAllCustomers服务返回不同的数据协定。如,

[DataContract]
public class CustomerSummary
{
   // Have properties that represent the summary of the customer
}

WebGet(UriTemplate = "/Customers/{id}")]    
Customer GetCustomerById(string id);    

[WebGet(UriTemplate = "/Customers")]    
List<CustomerSummary> GetAllCustomers();

或者,在将EmitDefaultValue属性应用于DataMember属性时使用Orders

[DataContract]       
public class Customer       
{       
   [DataMember]       
   public virtual int Id { get; set; }       

   [DataMember]
   public virtual string Name { get; set; }       

   [DataMember(IsRequired = false, EmitDefaultValue = false)]
   public virtual IList<Order> Orders { get; set; }       
}

然后在GetAllCustomers返回数据时将Orders属性保留为null。

答案 3 :(得分:0)

延迟加载仅适用于hibernate会话的范围。没有机会通过电线做这件事。您需要急切地获取集合或使用OOP继承,并从Web方法返回一个根本没有此集合的类,特别是如果消费者不需要它。