如何在soap格式WCF中设置属性

时间:2014-01-07 14:44:09

标签: wcf soap xml-attribute

如何设置soap消息的属性:

例如我的肥皂混乱看起来像下面的

<doPaymentResult xmlns:a="http://schemas.datacontract.org/2004/07/MemoService" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
        <a:errors i:nil="true"/>
        <a:messages>
           <a:MessageEntity>
              <a:codeField>Payment Request Successful</a:codeField>
              <a:textField i:nil="true" xmlns:b="http://schemas.microsoft.com/2003/10/Serialization/Arrays"/>
           </a:MessageEntity>
        </a:messages>
        <a:requestTrackCode>20130430T125904R14646</a:requestTrackCode>
        <a:status i:nil="true"/>
     </doPaymentResult>
  </doPaymentResponse>

但我需要一条肥皂信息,它取的属性不是元素 喜欢以下

<doPaymentResult xmlns:a="http://schemas.datacontract.org/2004/07/MemoService" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
        <a:errors i:nil="true"/>
        <a:messages>
           <a:MessageEntity codeField="Payment Request Successful">
              some text here
           </a:MessageEntity>
        </a:messages>
        <a:requestTrackCode>20130430T125904R14646</a:requestTrackCode>
        <a:status i:nil="true"/>
     </doPaymentResult>
  </doPaymentResponse>

我在课堂上使用datacontract。

1 个答案:

答案 0 :(得分:4)

这是一个常见问题 - 您希望将对象从WCF服务返回为XML,但您希望或者需要将部分或全部属性值作为XML属性而不是XML元素提供;但你不能,因为DataContractSerializer不支持属性(如果你进行了网络搜索,你很可能已经看过这个StackOverflow QA)。您很可能已将所有WCF服务代码迁移到使用XmlSerializer(包含所有XmlElement / XmlAttribute / XmlType属性等) - 并且您已大声诅咒。

好吧,我来这里是为了拯救你,因为它是可能的 - 问题的答案实际上是从MSDN文章“数据合同序列化程序支持的类型”中推断出来的。

我要给出的例子纯粹仅用于说明目的。我没有很多时间,所以和我一起工作吧! •创建一个新的Asp.Net WCF服务应用程序,您可以使用Cassini作为您的Web服务器(可能更容易 - 否则您可能必须启用Asp.Net兼容模式)。 •打开web.config并删除为新服务创建的元素。 •此示例的界面和实现模型过度。将[ServiceContract]和[OperationContract]声明从为新服务创建的接口移动到也创建的类。删除界面。 •打开.svc标记文件并在末尾添加以下内容:Factory =“System.ServiceModel.Activation.WebServiceHostFactory” - 这将为此服务启用零配置WCF模型(我们将创建RESTful服务)。 •将以下类声明粘贴到您的svc代码隐藏中:

public interface IExampleData

{

    string Description { get; set; }

    string Name { get; set; }

    int ID { get; set; }

}

public class ExampleData : IExampleData

{

    public string Description { get; set; }

    public string Name { get; set; }

    public int ID { get; set; }

}

public class ExampleDataAttributed : ExampleData, IXmlSerializable

{

    #region IXmlSerializable Members

    public System.Xml.Schema.XmlSchema GetSchema()

    {

        return null;

    }

    public void ReadXml(System.Xml.XmlReader reader)

    {

        //implement if remote callers are going to pass your object in

    }

    public void WriteXml(System.Xml.XmlWriter writer)

    {

        writer.WriteAttributeString("id", ID.ToString());

        writer.WriteAttributeString("name", Name);

        //we'll keep the description as an element as it could be long.

        writer.WriteElementString("description", Description);

    }

    #endregion

}



Just to demonstrate the point, the class that will be part-serialized to attributes simply derives from one that will be serialized as normal.


•Now add the following two methods to your service class: 
[OperationContract]

[WebGet(UriTemplate = "/test1")]

public ExampleData Test1()

{

    return new ExampleData() { ID = 1, 
           Name = "Element-centric", 
           Description = 
"The contents of this item are entirely serialized to elements - as normal" };
}


[OperationContract]

[WebGet(UriTemplate = "/test2")]

public ExampleDataAttributed Test2()

{

    return new ExampleData_Attributed() { ID = 2, 
          Name = "Mixed", 
          Description = 
"Everything except this description will be serialized to attributes" };

}

盖上盖子,烘烤40分钟(即 - 构建它)。

如果您将服务保留为Service1.svc,则运行它并打开IE并浏览到http:// localhost:[cassini端口] / test1

结果应如下所示:

<JSLabs.ExampleData 

 xmlns="http://schemas.datacontract.org/2004/07/ExampleNamespace" 

 xmlns:i="http://www.w3.org/2001/XMLSchema-instance">

    <Description>

        The contents of this item are entirely serialized to elements - as normal

    </Description>

    <ID>

        1

    </ID>

    <Name>

        Element-centric

    </Name>

</JSLabs.ExampleData>

现在浏览到http:// localhost:[cassini端口] / test2

<JSLabs.ExampleDataAttributed id="2" name="Mixed" 

  xmlns="http://schemas.datacontract.org/2004/07/JobServe.Labs.Web">

    <description>Everything except this description will be 

    serialized to attributes</description>

</JSLabs.ExampleDataAttributed>

WCF数据合同序列化程序自动放入类型的那个令人讨厌的“可怕的”xmlns =“属性使得它变得不那么令人印象深刻 - 但是,正如您所看到的,'ID'和'Name'属性确实已经被推出属性!

我们可以让两个方法返回IExampleData,然后在该接口上使用KnownType属性以使其支持(根据返回的方法代码)。

为了支持从属性反序列化对象,您所要做的就是实现IXmlSerializable.ReadXml方法。

最后,正如前面提到的MSDN文章所述的支持类型 - 您还应该能够使用XmlElement / XmlNode类型作为直接表示XML的方式 - 像这种情况一样,DataContractSerializer采用短路径并简单地获取Xml。

如果您为XML或JSON客户端双输出对象,这也不应影响JSON格式。

Check the source of this article