我有一个WCF DataContract,如下所示:

namespace MyCompanyName.Services.Wcf
{
  [DataContract(Namespace = "http://mycompanyname/services/wcf")]
  [Serializable]
  public class DataContractBase
  {
    [DataMember]
    public DateTime EditDate { get; set; }

    // code omitted for brevity...
  }
}

当我在Visual Studio中添加对此服务的引用时,将生成以下代理代码:
/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.Xml", "2.0.50727.3082")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(Namespace="http://mycompanyname/services/wcf")]
public partial class DataContractBase : object, System.ComponentModel.INotifyPropertyChanged {

    private System.DateTime editDateField;

    private bool editDateFieldSpecified;

    /// <remarks/>
    [System.Xml.Serialization.XmlElementAttribute(Order=0)]
    public System.DateTime EditDate {
        get {
            return this.editDateField;
        }
        set {
            this.editDateField = value;
            this.RaisePropertyChanged("EditDate");
        }
    }

    /// <remarks/>
    [System.Xml.Serialization.XmlIgnoreAttribute()]
    public bool EditDateSpecified {
        get {
            return this.editDateFieldSpecified;
        }
        set {
            this.editDateFieldSpecified = value;
            this.RaisePropertyChanged("EditDateSpecified");
        }
    }

    // code omitted for brevity...
}

如您所见,除了生成EditDate的后备属性外,还生成了另一个<propertyname>Specified属性。一切都很好,除了在执行以下操作时:
DataContractBase myDataContract = new DataContractBase();
myDataContract.EditDate = DateTime.Now;

new MyServiceClient.Update(new UpdateRequest(myDataContract));

服务的端点未获取EditDate(未出现在传输的XML中)。

我调试了代码,发现尽管设置了EditDate,但EditDateSpecified属性并未像我期望的那样设置为true。因此,即使XML序列化器设置为有效值,它也忽略了EditDate的值。

作为一个快速技巧,我将EditDate属性修改为如下所示:
   /// <remarks/>
    [System.Xml.Serialization.XmlElementAttribute(Order=0)]
    public System.DateTime EditDate {
        get {
            return this.editDateField;
        }
        set {
            this.editDateField = value;

            // hackhackhack
            if (value != default(System.DateTime))
            {
              this.EditDateSpecified = true;
            }
            // end hackhackhack

            this.RaisePropertyChanged("EditDate");
        }
    }

现在代码可以按预期工作,但是当然每次我重新生成代理时,所做的修改都会丢失。我可以将调用代码更改为以下内容:
DataContractBase myDataContract = new DataContractBase();
myDataContract.EditDate = DateTime.Now;
myDataContract.EditDateSpecified = true;

new MyServiceClient.Update(new UpdateRequest(myDataContract));

但这似乎也浪费时间。

所以最后,我的问题是:是否有人对如何摆脱Visual Studio服务代理生成器的这种不直观(且IMO损坏)的行为提出建议,或者我只是缺少什么?

最佳答案

这可能有点不直观(并且也使我措手不及!)-但这是处理XML模式中可能指定或可能未指定的元素的唯一正确方法。

而且,您必须自己设置xyzSpecified标志似乎也很违反直觉-但是最终,这给了您更多的控制权,WCF就是关于Four Tenets of SOA非常明确和清楚您的意图的全部内容。

因此,基本上-这就是它的方式,请习惯它:-)不可能“粘贴”此行为-这是WCF系统的设计方式,也是有充分理由的。

您始终可以做的是捕获并处理this.RaisePropertyChanged("EditDate");事件,并在该事件的事件处理程序中设置EditDateSpecified标志。

关于c# - WCF服务代理未设置 “FieldSpecified”属性,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/1680356/

10-11 02:11