WCF服务 - 更新操作最佳实践

时间:2015-10-28 19:41:07

标签: c# wcf soap

假设我们有一个简单的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结尾。

有没有办法通过省略SOAP消息中的值以及明确设置“null”来判断哪个“null”?

如果没有,对于这样的情况,什么是“最佳做法”?

2 个答案:

答案 0 :(得分:0)

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

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。

就是这样!纯粹的超赞:)

答案 1 :(得分:0)

  

格式化的消息意味着,客户端只想更新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中的服务。