【问题标题】:Null values for object properties de-serialized by WCF由 WCF 反序列化的对象属性的空值
【发布时间】:2011-05-02 17:34:01
【问题描述】:

我有一个 使用 可以正常工作的 WCF Web 服务。在某个地方它停止了,我不知道为什么。代码和界面从未改变过,web.config 也没有改变(至少与 web 服务部分无关)。我有一堂课:

[DataContract]
public class QuizServiceArgs
{
    [DataMember(IsRequired = true, Order = 1)] 
    public int Category1 { get; set; }

    [DataMember(IsRequired = true, Order = 2)] 
    public int Category2 { get; set; }

    [DataMember(IsRequired = true, Order = 3)] 
    public int Category3 { get; set; }

    [DataMember(IsRequired = true, Order = 4)] 
    public int Category4 { get; set; }
}

而且服务接口简单:

public interface IQuizService
{
    [OperationContract]
    [WebInvoke(Method = "POST",
       BodyStyle = WebMessageBodyStyle.WrappedRequest,
       ResponseFormat = WebMessageFormat.Json)]
    ServiceResult Save(QuizServiceArgs answers, string strvalue, int intvalue);
}

添加后两个参数strvalueintvalue 仅用于故障排除,以查看它们是否被反序列化 - 确实如此。当我点击服务时,我收到一条错误消息,提示我缺少请求中的 Category1 参数,但正如您可以看到这个 Fiddler 屏幕截图,值在那里。

我可以获取要传入的原始值,但对象似乎都被实例化为 null 或默认值。我做错了什么?

更新

我从来没有真正回答过我原来的问题,这很糟糕,但 Sixto 建议我将我的序列化转换为 JSON。 JSON 是最初的设计,但在我遇到问题时被否决了。在我成功切换回 JSON 后,一切都在正确序列化和反序列化。现在我只是在等待它中断,没有任何解释,所以我可以切换回 XML....

【问题讨论】:

  • 顺便说一句,我从 fiddler 请求中裁剪出一些我认为是噪音的标头。如果图片中没有 Content-length 属性,请不要担心,请求中有一个 :)
  • 您是否更改了数据成员属性的 Order 属性?或者任何命名空间?或者删除任何成员?
  • @Marc 属性在 POST 中的顺序与在代码中指定的顺序相同。我没有任何命名空间——我在其他项目中将其保留为空,并且运行良好。我没有删除任何成员。这实际上是我的整个QuizServiceArgs 课程。

标签: c# wcf web-services serialization deserialization


【解决方案1】:

您遇到了命名空间问题。默认情况下,当您为 servicecontract 创建接口时,它会为其分配一个命名空间。命名空间就像 SOAP xml 元素的范围,如果它不在同一范围内,它认为它不存在。可能是帖子停止提供命名空间(?)的代码。您必须在发布 XML 时引用它 - 但我不完全确定它分配了什么(特定于服务器的东西),所以最好总是定义一个命名空间,如下所示:

[ServiceContract(Namespace = "your namespace")] public interface IQuizService { [OperationContract] [WebInvoke(Method = "POST", BodyStyle = WebMessageBodyStyle.WrappedRequest, ResponseFormat = WebMessageFormat.Json)] ServiceResult Save(QuizServiceArgs answers, string strvalue, int intvalue); }

然后帖子应该在 SOAP 请求中包含命名空间。

<Save xmlns="your namespace">.....</Save>

命名空间还应与您在 web.config 中的服务声明相匹配。

在数据合约中也需要它

[DataContract(Namespace = "your namespace")]

【讨论】:

  • 我在三个地方添加了一个命名空间:接口上的ServiceContract、请求的根节点和web.config中的端点bindingNamespace。一样的回应。我之前使用过没有命名空间的 WCF 没有问题,所以我对我仍然遇到问题并不感到非常惊讶。
  • 我仍然相当肯定它是一个命名空间问题。正如我所提到的,分配了一个默认值,如果匹配应该可以正常工作。哦,您还需要在数据合同中 - [DataContract(Namespace = "your namespace")]。他们都得排队上班……
  • 你为我节省了很多时间! 300 的赏金正在给你 M.R.
【解决方案2】:

DataMember IsRequired 属性告诉 WCF 反序列化程序在消息 XML 中预期具有该名称的元素(至少对于 soap 反序列化是这样)。听起来生成消息请求的客户端代码不再发送所有 Category... 元素。这并不意味着您不能为标记为 IsRequired 的 DataMember 发送空值,它只是意味着该元素需要存在于消息中。

更新:更仔细地查看 XML,XML 中不应该有 QuizServiceArgs 元素吗?

【讨论】:

  • 我还没有真正到客户端代码的地步。我使用 Fiddler 手动制作我的请求。在屏幕截图中,您可以看到 CategoryX 值位于发送到服务器的 XML 模式中。我了解服务器认为我没有发送这些属性。我只是不知道它为什么会这样想。
  • 我不太熟悉 WebInvoke 的 XML 应该是什么样子,但错误消息是说反序列化程序在到达答案元素结束标记之前没有找到 Category... 元素。
  • 其实我认为主要问题是您将 WebInvoke 格式化程序设置为 json 而不是 XML :)
  • 响应是 JSON。请求默认为 XML。我本来希望请求和响应都是 JSON,但是为了简单起见,我无法让请求为 JSON 工作,只是将其留在 XML 中。也许是时候重新审视 JSON 请求了。
  • 您没有直接回答我的问题,但我通过将所有内容切换到 JSON 而不是混合 JSON 和 XML 来完成所有工作。我的所有 AJAX 请求都通过我的包装 ajax 函数传递,因此修改整个应用程序的所有内容都很容易。谢谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-03-27
  • 1970-01-01
  • 1970-01-01
  • 2017-03-21
相关资源
最近更新 更多