C# 如何在RESTful.NETWCFWeb服务中返回XML?

C# 如何在RESTful.NETWCFWeb服务中返回XML?,c#,.net,asp.net,xml,wcf,C#,.net,Asp.net,Xml,Wcf,我使用4.0框架在VisualWebDeveloper2010Express中设置了一个WCFWeb服务,并将其转换为RESTful服务 我可以根据自己的喜好对其进行修改,以接受如下url参数: namespace RestServicePublishing { [ServiceContract] public interface IRestService { [OperationContract(Name="GetXML")] [WebGet(UriTemplate = "/{

我使用4.0框架在VisualWebDeveloper2010Express中设置了一个WCFWeb服务,并将其转换为RESTful服务

我可以根据自己的喜好对其进行修改,以接受如下url参数:

namespace RestServicePublishing
{
[ServiceContract]
public interface IRestService
{
    [OperationContract(Name="GetXML")]
    [WebGet(UriTemplate = "/{param1}/{param2}")]
    XmlDocument GetXML(string param1, string param2);
}
}
我遇到的问题是,在尝试返回如下Xml文档时,遇到“Type”System.Xml.XmlDocument“cannot serialized”错误:

namespace RestServicePublishing
{
public class RestService : IRestService
    {

    public  XmlDocument GetXML(string param1, string param2)
    {

        //I am not using the parameters currently, I would just like to see if 
        //i can return XML first with this simple example:

        StringBuilder sb = new StringBuilder();
        System.Xml.XmlWriter writer = XmlWriter.Create(sb);
        writer.WriteStartDocument(); 
        writer.WriteStartElement("People");
        writer.WriteStartElement("Person"); 
        writer.WriteAttributeString("Name", "Nick"); 
        writer.WriteEndElement(); 
        writer.WriteStartElement("Person"); 
        writer.WriteStartAttribute("Name"); 
        writer.WriteValue("Nick"); 
        writer.WriteEndAttribute(); 
        writer.WriteEndElement();
        writer.WriteEndElement(); 
        writer.WriteEndDocument(); 
        writer.Flush();

        XmlDocument xmlDocument = new Xml.XmlDocument(); 
        xmlDocument.LoadXml(sb.ToString());
        return xmlDocument; 
    }

}
}
[DataContract]
public class Person
{
    [DataMember]
    public string Name { get; set; }
}

[CollectionDataContract(Name = "People")]
public class People : List<Person>
{
}
我知道必须有更好的方法来设置XML文档并返回它。。非常感谢您的帮助


提前谢谢你

将其作为字符串返回,然后将该字符串加载到另一端的
XmlDocument


或者最好是,创建一个模仿代码中XML结构的
DataContract
类,然后WCF将其转换为XML。

将其作为字符串返回,然后将该字符串加载到另一端的
XmlDocument


或者最好是,创建一个模仿代码中XML结构的
DataContract
类,然后WCF将其转换为XML。

是-好的。。。。WCF的模型说,您不应该尝试返回XmlDocument本身。而是返回在编程环境中定义的自定义类型。需要标记该类型,以指定如何将其序列化为XML。然后,当该方法返回自定义类型时,WCF将其隐式序列化为XML文档

我想你想要的回报是这样的:

<People>
  <Person Name="Nick"/>
  <Person Name="Bonnie"/>
</People>
<People>
  <Person><Name>Nick</Name></Person>
  <Person><Name>Bonnie</Name></Person>
</People>
namespace RestServicePublishing
{
    [ServiceContract]
    public interface IRestService
    {
        [OperationContract(Name="GetXML")]
        [WebGet(UriTemplate = "/{param1}/{param2}")]
        List<Person> GetXML(string param1, string param2);
    }
}

但是DataContractSerializer不喜欢发出属性。因此,以正常的方式使用WCF生成XML web服务,您将得到如下结果:

<People>
  <Person Name="Nick"/>
  <Person Name="Bonnie"/>
</People>
<People>
  <Person><Name>Nick</Name></Person>
  <Person><Name>Bonnie</Name></Person>
</People>
namespace RestServicePublishing
{
    [ServiceContract]
    public interface IRestService
    {
        [OperationContract(Name="GetXML")]
        [WebGet(UriTemplate = "/{param1}/{param2}")]
        List<Person> GetXML(string param1, string param2);
    }
}

刻痕
邦妮
要做到这一点,请像下面这样编写C代码:

<People>
  <Person Name="Nick"/>
  <Person Name="Bonnie"/>
</People>
<People>
  <Person><Name>Nick</Name></Person>
  <Person><Name>Bonnie</Name></Person>
</People>
namespace RestServicePublishing
{
    [ServiceContract]
    public interface IRestService
    {
        [OperationContract(Name="GetXML")]
        [WebGet(UriTemplate = "/{param1}/{param2}")]
        List<Person> GetXML(string param1, string param2);
    }
}
命名空间RestServicePublishing
{
[服务合同]
公共接口IRestService
{
[运营合同(Name=“GetXML”)]
[WebGet(UriTemplate=“/{param1}/{param2}”)]
List GetXML(字符串param1、字符串param2);
}
}
那么类型应该如下所示:

namespace RestServicePublishing
{
public class RestService : IRestService
    {

    public  XmlDocument GetXML(string param1, string param2)
    {

        //I am not using the parameters currently, I would just like to see if 
        //i can return XML first with this simple example:

        StringBuilder sb = new StringBuilder();
        System.Xml.XmlWriter writer = XmlWriter.Create(sb);
        writer.WriteStartDocument(); 
        writer.WriteStartElement("People");
        writer.WriteStartElement("Person"); 
        writer.WriteAttributeString("Name", "Nick"); 
        writer.WriteEndElement(); 
        writer.WriteStartElement("Person"); 
        writer.WriteStartAttribute("Name"); 
        writer.WriteValue("Nick"); 
        writer.WriteEndAttribute(); 
        writer.WriteEndElement();
        writer.WriteEndElement(); 
        writer.WriteEndDocument(); 
        writer.Flush();

        XmlDocument xmlDocument = new Xml.XmlDocument(); 
        xmlDocument.LoadXml(sb.ToString());
        return xmlDocument; 
    }

}
}
[DataContract]
public class Person
{
    [DataMember]
    public string Name { get; set; }
}

[CollectionDataContract(Name = "People")]
public class People : List<Person>
{
}
[DataContract]
公共阶层人士
{
[数据成员]
公共字符串名称{get;set;}
}
[CollectionDataContract(Name=“People”)]
公共阶层人士:名单
{
}

是-嗯。。。。WCF的模型说,您不应该尝试返回XmlDocument本身。而是返回在编程环境中定义的自定义类型。需要标记该类型,以指定如何将其序列化为XML。然后,当该方法返回自定义类型时,WCF将其隐式序列化为XML文档

我想你想要的回报是这样的:

<People>
  <Person Name="Nick"/>
  <Person Name="Bonnie"/>
</People>
<People>
  <Person><Name>Nick</Name></Person>
  <Person><Name>Bonnie</Name></Person>
</People>
namespace RestServicePublishing
{
    [ServiceContract]
    public interface IRestService
    {
        [OperationContract(Name="GetXML")]
        [WebGet(UriTemplate = "/{param1}/{param2}")]
        List<Person> GetXML(string param1, string param2);
    }
}

但是DataContractSerializer不喜欢发出属性。因此,以正常的方式使用WCF生成XML web服务,您将得到如下结果:

<People>
  <Person Name="Nick"/>
  <Person Name="Bonnie"/>
</People>
<People>
  <Person><Name>Nick</Name></Person>
  <Person><Name>Bonnie</Name></Person>
</People>
namespace RestServicePublishing
{
    [ServiceContract]
    public interface IRestService
    {
        [OperationContract(Name="GetXML")]
        [WebGet(UriTemplate = "/{param1}/{param2}")]
        List<Person> GetXML(string param1, string param2);
    }
}

刻痕
邦妮
要做到这一点,请像下面这样编写C代码:

<People>
  <Person Name="Nick"/>
  <Person Name="Bonnie"/>
</People>
<People>
  <Person><Name>Nick</Name></Person>
  <Person><Name>Bonnie</Name></Person>
</People>
namespace RestServicePublishing
{
    [ServiceContract]
    public interface IRestService
    {
        [OperationContract(Name="GetXML")]
        [WebGet(UriTemplate = "/{param1}/{param2}")]
        List<Person> GetXML(string param1, string param2);
    }
}
命名空间RestServicePublishing
{
[服务合同]
公共接口IRestService
{
[运营合同(Name=“GetXML”)]
[WebGet(UriTemplate=“/{param1}/{param2}”)]
List GetXML(字符串param1、字符串param2);
}
}
那么类型应该如下所示:

namespace RestServicePublishing
{
public class RestService : IRestService
    {

    public  XmlDocument GetXML(string param1, string param2)
    {

        //I am not using the parameters currently, I would just like to see if 
        //i can return XML first with this simple example:

        StringBuilder sb = new StringBuilder();
        System.Xml.XmlWriter writer = XmlWriter.Create(sb);
        writer.WriteStartDocument(); 
        writer.WriteStartElement("People");
        writer.WriteStartElement("Person"); 
        writer.WriteAttributeString("Name", "Nick"); 
        writer.WriteEndElement(); 
        writer.WriteStartElement("Person"); 
        writer.WriteStartAttribute("Name"); 
        writer.WriteValue("Nick"); 
        writer.WriteEndAttribute(); 
        writer.WriteEndElement();
        writer.WriteEndElement(); 
        writer.WriteEndDocument(); 
        writer.Flush();

        XmlDocument xmlDocument = new Xml.XmlDocument(); 
        xmlDocument.LoadXml(sb.ToString());
        return xmlDocument; 
    }

}
}
[DataContract]
public class Person
{
    [DataMember]
    public string Name { get; set; }
}

[CollectionDataContract(Name = "People")]
public class People : List<Person>
{
}
[DataContract]
公共阶层人士
{
[数据成员]
公共字符串名称{get;set;}
}
[CollectionDataContract(Name=“People”)]
公共阶层人士:名单
{
}

我使用了“将其作为字符串发送回去”方法。。谢谢以字符串形式返回XML通常不是一个好主意。最好返回一个自定义类型,该类型以您喜欢的形状为您序列化。@那么您是下选者吗?请重新阅读,我提供了您的解决方案作为替代方案。我不认为这是一个“坏主意”,您不知道什么系统连接到此服务,也不知道构造响应XML有多容易。在这种情况下,否决票是没有理由的。是的,我否决了,我认为这是个坏主意。我尊重你不同意我意见的权利。我读过备选方案,但我认为将其定性为备选方案是错误的。这是主要的选择。正确的选择。就好像我会告诉你,“嗯,你可以成为一个海洛因瘾君子,在街上生活,为了维持你的习惯而犯罪,然后染上疾病。或者,你可以上大学,获得学位,找到工作,过一种理智的生活。”当然,这并不是那么极端,但你明白了重点。后者是首选选项,我总是建议反对前者。很公平,尽管这个类比有点不协调,但从某种程度上说,发送原始XML似乎是终极选择。不,坦率地说,这没有什么错。创建包装器类型并不总是可能的,而原始XML作为解决方案也没有什么问题。也许这是唯一受影响的方法?也许XML直接来自实际的XML文件?谁知道呢?无论哪种方式,发送原始XML都不值得投反对票,因为答案并不危险、不具误导性或不正确。。。但每个人都有自己的选择。这就是我的烦恼结束的地方,我已经将我的答案修改为明确的:-)我使用了“将其作为字符串发送回去”方法。。谢谢以字符串形式返回XML通常不是一个好主意。最好返回一个自定义类型,该类型以您喜欢的形状为您序列化。@那么您是下选者吗?请重新阅读,我提供了您的解决方案作为替代方案。我不认为这是一个“坏主意”,您不知道什么系统连接到此服务,也不知道构造响应XML有多容易。在这种情况下,否决票是没有理由的。是的,我否决了,我认为这是个坏主意。我尊重你不同意我意见的权利。我读过备选方案,但我认为将其定性为备选方案是错误的。这是主要的选择。正确的选择。就好像我会告诉你,“好吧,你可以成为一个海洛因瘾君子,住在街上