代码之家  ›  专栏  ›  技术社区  ›  David Boike

手动写入WCF POX日志

  •  1
  • David Boike  · 技术社区  · 16 年前

    假设我有一个WCF合同,比如

    [ServiceContract]
    public interface IContract
    {
        [OperationContract]
        [WebInvoke(Method="POST", RequestFormat=WebMessageFormat.Xml, BodyStyle=WebMessageBodyStyle.Wrapped)]
        string ComplexPost(string name, ComplexType data);
    }
    

    数据合同:

    [DataContract(Name="ComplexType", Namespace="")] // don't know if those atts are req'd or not but saw them in another example
    public class ComplexType
    {
        public string StringData { get; set; }
        public int IntData { get; set; }
        public DateTime DateValue { get; set; }
    }
    

    我知道为了拥有多个输入参数,必须对请求进行包装,显然,不能拥有具有多个根的XML文档。

    问题是,文档对于您必须用什么来包装它是非常稀疏的。

    目标不是将其与WCF一起使用,而是将其作为通用XML Web服务供客户端访问。他们可能不了解WCF,甚至不使用.NET。

    显然,我可以从收到的异常中看出,它期望名称空间为complexPost(与方法名称相同)的元素 http://tempuri.org/ 因为我还没有指定其他内容,所以我知道我需要:

    <ComplexPost xmlns="http://tempuri.org/">
    
    ...what exactly?
    
    </ComplexPost>
    

    我们的目标并不是特别坚持休息原则。我不想寻找将一些参数嵌入到uritemplate中的答案,只留下一个复杂的对象,从而使工作变得简单。我正在寻找一个将所有数据都包含在post主体中的通用解决方案。

    用小提琴找到的

    根据我用小提琴找到的结果,这里大概是结果。

    <ComplexPost xmlns="http://tempuri.org/">
        <name>Value of name parameter</name>
        <data xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
            <StringData>The StringData property value</StringData>
            <IntData>10</IntData>
            <DateValue>2009-07-07T15:38:39.7738012-05:00</DateValue>
        </data>
    <ComplexPost>
    

    所以wrapper元素是方法名,其XML名称空间在servicecontract中指定,如果不是,则是temppuri.org。

    每个参数依次成为一个子元素,基本类型很容易序列化为字符串表示形式。

    我用可以为空的值进行了测试,包括可以为空的日期时间。显然,xmlns:i=“http://www.w3.org/2001/xmlschema-instance”的声明必须在需要之前出现,然后对于空值,它是一个封闭元素,其中i:nil=“true”,例如

    <NullableDateProperty i:nil="true" />
    

    对于DataContract对象来说,拥有子复杂类型甚至复杂对象列表也是非常容易的。

    ....
    <ChildObjectPropertyName>
        <PropertyOfChildObject>value</PropertyOfChildObject>
        ...
    </ChildObjectPropertyName>
    <ListProperty>
        <ObjectType>
            <ObjectProperty>value</ObjectProperty>
            ....
        </ObjectType>
        ...
    </ListProperty>
    

    这可能还不完整,但教训肯定是让WCF客户端工作,然后检查与fiddler的交换。谢谢你,奇索!

    2 回复  |  直到 9 年前
        1
  •  1
  •   Cheeso    16 年前

    如果我这样做的话,发布一个基于WCF的REST/POX服务,并且我想让“任何人和任何事”都可以使用它,比如 Fiddler2 ,并捕获从WCF REST客户端到WCF REST服务器的成功请求。

    这可能是文档和示例以及一组脚本测试开始的基础。

    还有一种方法可以在WCF本身中打开消息跟踪,但我不知道。我总是用小提琴。实际上我把它打开了 马上 .

        2
  •  1
  •   marc_s    16 年前

    我不太明白你的目标……

    一个“正常”的WCF服务是一个SOAP服务,它本质上可以与任何讲SOAP的其他操作(例如Java、PHP)一起命名。难道你不能创建一个完整的SOAP服务,并与客户机进行互操作吗?

    如果不是-如果使用REST,基本上将发生的情况是,DataContract(服务的数据表示形式)将被DataContractSerializer序列化为XML。您可以使用以下代码段在代码中轻松地手动测试:

    DataContractSerializer dcs = new DataContractSerializer(typeof(YourDataContract));
    
    FileStream outputFile = new FileStream(@"C:\output.xml");
    dcs.WriteObject(outputFile, yourTestDataInstance);
    

    “yourtestdatainstance”(类型为“yourdatacontract”)的序列化输出将写入C:\output.xml并准备好进行检查。

    当然,当您浏览到服务URL时,您可以看到其余的结果。所以你可能需要稍微调整一下结果——但是你应该能够很容易地达到你感兴趣的目标。

    DataContract上的“name=”属性允许您为XML中的根元素指定不同的名称-例如,如果您希望“root”而不是“yourdataContract”,请使用“name=root”属性。

    namespace=attribute允许您将数据协定放入自己的单独XML命名空间中-就像.NET命名空间一样,它允许您消除数据的歧义,使其完全唯一,并确保自己的“customer”不会与其他地方的另一个名为“customer”的XML元素冲突。

    这两个属性都是可选的-如果不想,您不需要指定它们。

    马克