【问题标题】:Force parameter as Service contract attribute强制参数作为服务合同属性
【发布时间】:2015-02-08 10:04:28
【问题描述】:

我需要为非常具体的 SOAP 布局编写服务合同(端点不受我们控制)。本质上我需要生成以下soap请求:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
    <soapenv:Body>
        <auth message-id="1">
            <login>
                <UserName>goLocalTeam</UserName>
                <Password>yeay!</Password>
            </login>
        </auth>
    </soapenv:Body>
</soapenv:Envelope>

我创建了以下合同:

[ServiceContract(Namespace="", SessionMode=SessionMode.NotAllowed)]
public interface IPrototype
{
    [OperationContract(Action="auth")]
    string auth([MessageParameter(Name = "message-id")]int messageId, Login login);
}

[DataContract(Namespace="")]
public class Login 
{
    [DataMember]
    public string userName { get; set; }
    [DataMember]
    public string Password { get; set; }

}

但是,当我构造一个客户端并调用时,message-id 参数被呈现为&lt;auth&gt; 内的一个节点,而不是一个属性。

<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
  <s:Header>
    <Action s:mustUnderstand="1" xmlns="http://schemas.microsoft.com/ws/2005/05/addressing/none">auth</Action>
  </s:Header>
  <s:Body>
    <auth>
      <message-id>0</message-id>
      <login>
        <userName>yay</userName>
        <Password>yoy</Password>
      </login>
    </auth>
  </s:Body>
</s:Envelope>

知道如何让 WCF 将简单类型参数从节点切换到属性吗?

【问题讨论】:

  • Action 和 To 标头不是从 wsdl 生成的,但是当我在没有这些标头的情况下请求时,它会抛出错误,但是当我在请求中手动添加这些标头时它可以工作!但是 wsdl 没有这些标头的任何信息。

标签: c# wcf soap


【解决方案1】:

使用XmlSerializerFormat 属性而不是DataContract

查看MSDN 以了解如何使用它,但基本上你用XmlAttributeXmlElement 标记成员,所以它看起来像:

[ServiceContract(Namespace="", SessionMode=SessionMode.NotAllowed)]
public interface IPrototype
{
    [OperationContract(Action="auth")]
    string Auth(AuthRequest authRequest);
}
[MessageContract(IsWrapped = false)] // notice the unwrapping
public class AuthRequest
{
    [XmlAttribute]
    public int message-id { get; set; }
    [XmlElement]
    public Login Login { get; set; }
}
[MessageContract]
public class Login 
{
    [XmlElement]
    public string userName { get; set; }
    [XmlElement]
    public string Password { get; set; }

}

【讨论】:

  • 不幸的是,当我省略“[MessageBodyMember]”时,该属性不会呈现,但是当我包含它时,生成客户端会引发运行时错误:“System.Xml.Serialization.XmlAttributeAttribute 无效。仅当 IsWrapped 为 false 时,支持 XmlElement、XmlArray、XmlArrayItem、XmlAnyAttribute 和 XmlAnyElement 属性。"当我将 IsWrapped 设置为 true 时,我得到了同样的错误,只有最后一个字发生了变化,这意味着这不是一个解决方案。
  • 虽然你的答案并不完全正确,但它帮助我指明了方向。所以我奖励你积分。
【解决方案2】:

好的,我解决了,部分感谢user3906922,使用 xml 序列化程序格式。我只需要更深入地构建信息:

[ServiceContract(Namespace="", SessionMode=SessionMode.NotAllowed)]
public interface IPrototype
{
    [OperationContract(Action = "auth")]
    [XmlSerializerFormat]
    authResponse auth(authRequest auth);
}

[MessageContract(IsWrapped = false)]
public class authRequest
{
    [MessageBodyMember]
    public authRequestBody auth { get; set; }
}

[MessageContract(IsWrapped = true, WrapperName = "auth")]
public class authRequestBody 
{
    [XmlAttribute(AttributeName = "message-id"), MessageBodyMember]
    public int messageId { get; set; }

    [MessageBodyMember]
    public Login login { get; set; }
}

[MessageContract]
public class Login 
{
    [MessageBodyMember]
    public string userName { get; set; }

    [MessageBodyMember]
    public string Password { get; set; }

}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-04-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-08
    • 2013-01-31
    • 1970-01-01
    相关资源
    最近更新 更多