【问题标题】:How to prevent 'Specified' properties being generated in WCF clients?如何防止在 WCF 客户端中生成“指定”属性?
【发布时间】:2010-01-12 02:00:20
【问题描述】:

我有两个使用 VS2008 构建的 .NET 3.5 WCF 服务。

我在 Silverlight 中有两个 WCF 客户端来使用这些服务。客户端是使用“添加服务参考”生成的。我正在使用 Silverlight 4。

其中一个代理是使用每个属性的Specified 属性生成的。这是我的服务方法的“消息输入”类:

    // properties are generated for each of these fields
    private long customerProfileIdField;        
    private bool customerProfileIdFieldSpecified;        
    private bool testEnvField;        
    private bool testEnvFieldSpecified;

现在我的其他服务(仍然使用 Silverlight 客户端)不会生成 Specified 属性。

现在我不关心“良好 SOA 的原则”。我只是想摆脱这些该死的属性,因为在我正在做的事情的背景下,我绝对讨厌它们。

这两种服务之间肯定存在一些差异 - 但我不想为了找出差异而将它们完全分开。

similar question 之前的答案是“you cant do it”——这绝对不是真的,因为我知道了——我只是不知道我做了什么不同。

编辑:我现在的情况是,我将 Silverlight 4 代理重新生成到我的 3.5 WCF 服务(都在同一台 localhost 机器上),有时我得到“指定”属性,有时我没有。我不再认为(正如我最初怀疑的那样)这仅仅是由于某些端点配置或服务级别 [属性]。消息本身中有某些触发器会导致生成(或不生成)Specified。可能涉及很多因素,也可能很简单。

【问题讨论】:

  • 我实际上有 3 个服务没有创建指定的属性。只有第四个可以!
  • [XMLSerializerFormat] 添加到您服务的属性中:选中此answer

标签: wcf silverlight wcf-proxy


【解决方案1】:

在声明属性的 WCF 服务中尝试此操作

[DataMember(IsRequired=true)]
public bool testEnvField { get; set; }

IsRequired=true 将不需要 testEnvFieldSpecified 属性

【讨论】:

  • 在全球范围内这样做怎么样?现在我正在创建指定属性的服务刚刚神奇地停止创建它们。我刚刚添加了第二个带有非常相似消息的 OperationContract - 所以我仍然不知道是什么触发了这种全局行为
  • 我能看到为什么 2 个代理会使用 SpecifiedField 而不是生成的唯一原因是,因为 .n3.5 客户端应用程序不需要“IsRequired”属性,它们默认情况下假定它为 true,其中由于 .net2.0 应用程序需要该属性,它们读取 wsdl 的方式不同。两个应用程序都是 SL4 吗?
  • @neil 它是同一个应用程序!我现在已经到了一个地步,在重新编译我的 3.5 应用程序并为我的 SL4 客户端重新生成代理后,我有时会得到“指定”,有时不会。它变得非常令人沮丧!数据模型中的某些东西导致了这种行为
  • 使用 sl4 时,不要在 Visual Studio 中添加引用,转到 Program Files/Microsoft SDKs/Silverlight 4... 那里你会找到 slsvcutil,用它来生成代理,你可以自定义它更准确,每次都获得相同类型的行为
  • slsvcutil MyServer:8081/MyWCFService /out:Proxy.cs /enableDataBinding /n:*,"MyNamespace.Proxy" /ct:System.Collections.ObjectModel.ObservableCollection`1 /r:"%PROGRAMFILES%\参考 Assemblies\Microsoft\Framework\Silverlight\v3.0\System.Windows.dll" 试试看
【解决方案2】:

这些额外的指定属性是为在合同或属性标记中指定为可选的值类型生成的。

由于值类型在默认情况下具有值,因此为这些属性添加了额外的 Specified 标志,以允许客户端(和服务器)区分明确未指定或明确指定的内容 - 很可能设置为默认值。没有它,即使您没有在客户端代码中设置整数(因为映射到 int),整数最终总是为 0(并被序列化)。所以当你这样做的时候,你还需要确保将Specified标志设置为true,否则这些属性将不会被序列化。

因此,为了防止为值类型生成这些标志,您必须更改合同以使这些值类型属性是强制性的,而不是可选的。

希望这是有道理的。

【讨论】:

  • 对,这很有意义,除了我并不总是为值类型生成它们。目前我所有的(甚至不可为空的)布尔值和“整数”都没有生成这些属性,但偶尔我会无意中更改合同中的某些内容,从而导致它们生成(而且我绝对不会意外添加 [DataMember(IsRequired=true) ])。我真的很想知道如何永久禁用它们,使它们表现得像“正常”对象。
  • 不可为空的应该没问题,只有 optional 值类型才会有这个。
  • 相反。它是需要指定属性的不可空字段,否则您将不知道默认值(false 或 0)是否是用户真正想要的。可选的只是不存在,但它们是可选的事实说明没关系。在任何一种情况下,我的所有属性最终都会得到指定的属性,这基本上完全搞砸了我的所有代码。必须有一组规则来确定它们何时生成以及何时生成。不幸的是,它不像可空性那么简单(或者幸运的是,取决于你如何看待它)
  • 值类型不可为空是可以的。现在,如果您的布尔值可以为空,那么您将不知道整数的默认值 0 是否有意的区别。因此引入了Specified 标志。话虽如此,更多的是它们是必需的/强制性的,而不是可空性。
【解决方案3】:

好的,到目前为止,我发现了一件事会导致生成 Specified 属性:

  • 消息中存在XTypedElement

这些由 Linq2XSD 使用。我从 Linq2XSD 模型返回一个元素。

这触发了Specified 在我的所有类中生成所有属性:

    public XTypedElement Foo { get; set; }

但这并没有:

    public XElement Foo { get; set; }

仍然很好奇为什么会这样,以及是否有其他任何事情触发了这个。

【讨论】:

  • 我突然在 Web 服务中遇到了类似的问题,虽然我没有使用 XTypedElement 或 Linq2XSD,但我使用的是 .NET 4.0
【解决方案4】:

注意:我意识到这是一个老问题。我在此处添加此问题是因为此问题在 Google 上的搜索结果中排名靠前,并且对于任何前来查看的人来说都是有用的信息。

尝试将此行添加到您的运营合同声明中:
[XmlSerializerFormat]

它应该看起来像这样:

namespace WebServiceContract
{
    [ServiceContract(Namespace = "http://namespace")]
    [XmlSerializerFormat] //This line here will cause it to serialize the "optional" parameters correctly, and not generate the extra
    interface InterfaceName
    {
        /*...Your web service stuff here...*/
    }
}

【讨论】:

  • 请注意,这完全改变了用于 Web 服务的 XML 序列化引擎。 (从 DataContractSerializer 更改为 XmlSerializer)。不同的引擎使用不同的属性集来控制串行器输出,具有不同的兼容性限制和不同的性能特征。这不是一个小变化。
【解决方案5】:

我发现如果我将 DataTable 放入服务 DataContract 中,那么生成的客户端将使用 xml 序列化程序,从而生成 *IsSpecified 成员。

【讨论】:

    猜你喜欢
    • 2014-11-25
    • 2011-05-23
    • 2010-11-05
    • 2016-03-27
    • 2011-01-08
    • 1970-01-01
    • 2011-03-02
    • 2012-02-09
    • 2011-10-11
    相关资源
    最近更新 更多