【问题标题】:WCF service - update operation best practiceWCF服务——更新操作最佳实践
【发布时间】:2015-10-28 19:41:07
【问题描述】:

假设我们有一个简单的 DTO,我们想将其用作 CustomerUpdate 方法的输入参数:

[DataContract]
public class CustomerUpdateDTO
{
    [DataMember(IsRequired = true, Order = 0)]
    public int CustomerId { get; set; }

    [DataMember(Order = 1)]
    public string FirstName { get; set; }

    [DataMember(Order = 2)]
    public string LastName { get; set; }

    [DataMember(Order = 3)]
    public string Address { get; set; }
}

只需要一个文件 - CustomerId - 这很明显,因为我们必须知道要更新哪个客户。我想实现以下目标:

如果传入的 SOAP 消息包含给定值(例如:Joe),则表示客户端想要更新此属性。如果 SOAP 消息不包含值,则不应更新该值。如果属性的值应该被删除(为空),客户端应该使用 nil="true" 属性显式声明它(因此显式传递一个空值)。

例子:

<CustomerUpdateDTO>
  <CustomerId>1</CustomerId>
  <FirstName>Joe</FirstName>
  <Address xsi:nil="true" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" />
</CustomerUpdateDTO>

这样格式的消息意味着,客户端只想更新 FirstName,保持 LastName 不变,并将地址设置为 null。

问题是,在默认配置下,这样的消息被反序列化为:

CustomerId = 1
FirstName = "Joe"
LastName = null
Address = null

所以 LastName 和 Address 都以 null 结尾。

有没有办法判断哪个“null”是由省略 SOAP 消息中的值引起的,以及哪个“null”是显式设置的?

如果不是,对于这种情况,什么是“最佳实践”?

【问题讨论】:

    标签: c# wcf soap


    【解决方案1】:

    在谷歌搜索了一下之后,我终于找到了我的问题的答案:)

    Data member default values, how to figure out whether something was really sent?

    这是一个非常优雅和简单的解决方案。现在对我来说似乎很明显:)

    [DataContract]
    public class CustomerUpdateDTO
    {
    
        private string firstName;
        public bool FirstNameSpecified { get; set; }
    
        ...
    
        [DataMember(Order = 1)]
        public string FirstName
        {
            get
            {
                return firstName;
            }
    
            set
            {
                FirstNameSpecified = true;
                firstName = value;
            }
        }
    
        ...
    
    }
    

    当 SOAP 消息被反序列化并且值存在时,...Specified 标志设置为 true。

    就是这样!纯粹的敬畏:)

    【讨论】:

      【解决方案2】:

      这样格式的消息意味着,客户端只想更新 FirstName,保持 LastName 不变,并将地址设置为 null。

      将更新操作分解为几个不同的更新操作:

      class FirstNameUpdate
          public Customer as integer
          public FirstName as string
      end class 
      
      class LastNameUpdate
          public Customer as integer
          public LastName as string
      end class
      
      class AddressUpdate
          public Customer as integer
          public Address as string
      end class
      

      或重新发送不变的已知值

      dim Customer = Service.GetCustomer(10)
      
      dim CustomerUpdate as new CustomerUpdateDTO with {
          .CustomerID = Customer.ID,
          .FirstName = "Joe",
          .LastName = Customer.LastName,
          .Address = Nothing}
      
      Service.Update(CustomerUpdate)
      

      通知LastName 取自Customer DTO,并在CustomerUpdate DTO 中发送回服务。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2010-09-19
        • 1970-01-01
        • 2011-08-28
        • 1970-01-01
        • 1970-01-01
        • 2018-02-11
        • 1970-01-01
        相关资源
        最近更新 更多