C# WCF服务代理未设置";“指定字段”;财产
我有一个WCFC# WCF服务代理未设置";“指定字段”;财产,c#,.net,wcf,C#,.net,Wcf,我有一个WCFDataContract,看起来如下所示: namespace MyCompanyName.Services.Wcf { [DataContract(Namespace = "http://mycompanyname/services/wcf")] [Serializable] public class DataContractBase { [DataMember] public DateTime EditDate { get; set; }
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...
}
}
DataContractBase myDataContract = new DataContractBase();
myDataContract.EditDate = DateTime.Now;
new MyServiceClient.Update(new UpdateRequest(myDataContract));
/// <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中添加对此服务的引用时,将生成以下代理代码:
/// <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
(未显示在传输的XML中)
我调试了代码,发现尽管我正在设置EditDate
,但EditDateSpecified
属性并没有像我预期的那样设置为true
;因此,XML序列化程序忽略了EditDate
的值,即使它被设置为有效值
作为一种快速攻击,我修改了EditDate
属性,使其看起来如下所示:
namespace MyCompanyName.Services.Wcf
{
[DataContract(Namespace = "http://mycompanyname/services/wcf")]
[Serializable]
public class DataContractBase
{
[DataMember]
public DateTime EditDate { get; set; }
// code omitted for brevity...
}
}
DataContractBase myDataContract = new DataContractBase();
myDataContract.EditDate = DateTime.Now;
new MyServiceClient.Update(new UpdateRequest(myDataContract));
/// <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));
但这看起来也像是在浪费时间
最后,我的问题是:有人对如何克服VisualStudio服务代理生成器的这种不直观(而且我认为是坏的)行为有什么建议吗?还是我只是缺少了一些东西?这可能有点不直观(也让我措手不及,不知所措!)-但这是处理XML模式中可能指定或可能未指定的元素的唯一正确方法 您必须自己设置
xyzSpecified
标志,这似乎也有违直觉,但最终,这会让您拥有更多的控制权,而WCF的目的就是非常明确和清楚地表达您的意图
所以基本上-这就是它的方式,习惯它:-)没有办法“超越”这种行为-这是WCF系统的设计方式,也是有理由的
您总是可以捕获并处理this.RaisePropertyChanged(“EditDate”)代码>事件,并在该事件的事件处理程序中设置EditDateSpecified
标志。,
请忽略我之前的回答,我正在解释如何吸鸡蛋。我投票决定删除它们
您能告诉我您使用的是哪个版本的Visual Studio吗
在VS2005客户机中-在生成的代码中,我获得指定的标志,但在值更改时没有引发任何事件。要传递数据,我必须设置指定的
标志
在VisualWebDeveloper2008Express客户端中-在生成的代码中,我没有得到指定的标志,但我确实得到了值更改时的事件
在我看来,这个功能已经发展,WebDev2008更接近您所追求的,并且更直观,因为一旦设置了值,您就不需要设置标志
试试这个
[DataMember(IsRequired=true)]
public DateTime EditDate { get; set; }
这应该省略EditDateSpecified
属性,因为该字段是按要求指定的这里有一个简单的项目,可以修改生成的WCF代码中可选属性的设置器,以便在设置相关值时自动将*指定标志设置为true
显然,在某些情况下,您需要手动控制*指定的标志,因此我并不向所有人推荐它,但在大多数简单的用例中,*指定的标志只是一个额外的麻烦,自动设置它们可以节省时间,而且通常更直观
请注意,如果您控制Web服务发布点,这里的另一个答案将为您解决这个问题。然而,我通常不控制Web服务发布,而只是使用一个,并且必须在一些简单的软件中处理*指定的标志,我希望这是自动化的。因此,此工具。将代理类属性更改为可空类型
例:
布尔?证实
约会时间?checkDate您可以使用扩展类来“autospecify”(绑定更改处理程序事件),而不是更改自动生成代码的设置程序。这可能有两种实现——一种是“惰性”实现(Autospecify
),它使用反射来查找基于属性名指定的字段,而不是在某种类型的switch语句(如Autonotify
)中列出每个类的所有字段:
懒惰的
然后每个类自己定义行为:
public partial class MyRandomClass: IAutoNotifyPropertyChanged
{
public void WhenPropertyChanges(string propertyName)
{
switch (propertyName)
{
case "field1": this.field1Specified = true; return;
// etc
}
}
}
当然,这样做的缺点是,属性名的神奇字符串使重构变得困难,您可以通过表达式解析?了解更多信息
在MSDN上
在她的回答中,Shreesha解释说:
“指定”字段仅在结构的可选参数上生成。(int、datetime、decimal等)。所有这些变量都将生成具有指定名称的附加变量
这是一种了解客户机和服务器之间是否真的传递了参数的方法
更详细地说,如果不传递一个可选整数,那么它的dafault值仍然是0。您如何区分此值与实际传递的值为0的值?“指定”字段让您知道是否传递了可选整数。如果“指定”字段为false,则不会传递该值。如果为true,则传递整数
因此,从本质上说,设置这些字段的唯一方法是手动设置它们,如果对于已设置的字段,这些字段没有设置为true,那么该字段将在web服务调用的SOAP消息中丢失
我最后做的是构建一个方法来循环对象的所有成员,如果已经设置了属性,并且指定了一个名为name\u的属性,则将其设置为true。如果有人忘记了指定的XYZ,则生成警告是否会违反规则?同意这是答案,不同意这是唯一的方法/好的设计。这是垃圾设计。他们需要提供一个选项,以便在简单用例的属性设置器中自动设置这些属性。将[XMLSerializerFormat]
添加到服务的属性中:如果您从@MustafaMagdy的注释中复制/粘贴,请检查此选项——如果我们在本地代理中添加该属性,则为[XMLSerializerFormat]
(请注意此情况),它不会被覆盖吗