在REST API服务中将对象作为参数问题

时间:2012-01-18 02:13:59

标签: xml wcf rest

编辑: 显然我的工作正在发挥作用。我一直在测试使用从序列化对象生成的xml,这不起作用。我刚才更乱用它并决定尝试使用我正在创建的动态XML(与此处发布的相同),并且它有效。我想也许是因为当我在使用相同名称空间之前尝试它时... 但是,如何使用序列化对象中的xml不起作用?我注意到它在从对象创建时在xml中使用不同的命名空间。那是为什么?

原帖: 我遇到了将自定义对象传递给我正在创建的REST API的问题。现在我只是试图通过将一个类型为Lead的对象发布到WebInvoke方法来测试它。 我的服务是用WCF编写的。 Lead对象位于我的业务逻辑层的单独的类库项目中。

我使用常规ASP .net页面发布。您将在下面的代码部分中看到我尝试以两种方式手动构建xml,并将对象序列化为xml并将其用作POST数据。没有工作,我收到此错误: 远程服务器返回错误:(400)错误请求。

我知道服务配置正确,因为我能够调用并从我编写的其他WebInvoke方法获得响应,这是一种GET方法。

以下是相关代码: 服务接口代码:

[ServiceContract(Namespace = "http://www.mytestnamespace.com/test")]
public interface IRESTService
{
    [OperationContract]
    [WebInvoke(Method = "POST",
        UriTemplate = "leads",
        RequestFormat = WebMessageFormat.Xml,
        ResponseFormat = WebMessageFormat.Xml)]
    string AddLead(Lead lead);

    [OperationContract]
    [WebInvoke(Method = "GET",
        UriTemplate = "lead/{id}",
        ResponseFormat = WebMessageFormat.Xml)]
    string LeadData(string id);
}

服务代码:

public class RESTService : IRESTService
{
    public string AddLead(Lead lead)
    {
        return "AddLead Hit";
    }

    public string LeadData(string id)
    {
        return "LeadData was hit, id=" + id;
    }
}

主要对象代码:

[DataContract(Name="Lead",
    Namespace = "http://www.mytestnamespace.com/test")]
public class Lead
{
    [DataMember(Name="FirstName")]
    public string FirstName { get; set; }
    [DataMember(Name = "LastName")]
    public string LastName { get; set; }
    [DataMember(Name = "Email")]
    public string Email { get; set; }
    [DataMember(Name = "Phone")]
    public string Phone { get; set; }
}

最后我在aspx页面上使用的代码发布数据:

try
    {
        Lead l = new Lead();
        l.FirstName = "John";
        l.LastName = "Doe";
        l.Email = "John.Doe@gmail.com";
        l.Phone = "5555551234";

        XmlSerializer ser = new XmlSerializer(typeof(Lead));
        StringWriter sw = new StringWriter();
        ser.Serialize(sw, l);

        string s = sw.ToString();




        /*XmlDocument doc = new XmlDocument();
        XmlDeclaration dec = doc.CreateXmlDeclaration("1.0", "utf-8", null);

        XmlElement root = doc.CreateElement("Lead");
        root.SetAttribute("xmlns", "http://www.mytestnamespace.com/test");
        //root.SetAttribute("xmlns:xsd", "http://www.w3.org/2001/XMLSchema");
        doc.InsertBefore(dec, doc.DocumentElement);
        doc.AppendChild(root);

        XmlElement firstName = doc.CreateElement("FirstName");
        XmlElement lastName = doc.CreateElement("LastName");
        XmlElement email = doc.CreateElement("Email");
        XmlElement phone = doc.CreateElement("Phone");

        firstName.AppendChild(doc.CreateTextNode("John"));
        lastName.AppendChild(doc.CreateTextNode("Doe"));
        email.AppendChild(doc.CreateTextNode("John.Doe@gmail.com"));
        phone.AppendChild(doc.CreateTextNode("8885551234"));

        root.AppendChild(firstName);
        root.AppendChild(lastName);
        root.AppendChild(email);
        root.AppendChild(phone);*/

        HttpWebRequest req = (HttpWebRequest)WebRequest.Create(new Uri("http://localhost:54966/RESTService.svc/leads"));
        req.Method = "POST";
        req.ContentType = "application/xml";
        //byte[] formData = UTF8Encoding.UTF8.GetBytes(doc.InnerXml);
        byte[] formData = UTF8Encoding.UTF8.GetBytes(s);
        req.ContentLength = formData.Length;

        using (Stream post = req.GetRequestStream())
        {
            post.Write(formData, 0, formData.Length);
        }

        string result = null;
        using (HttpWebResponse resp = (HttpWebResponse)req.GetResponse())
        {
            StreamReader reader = new StreamReader(resp.GetResponseStream());
            result = reader.ReadToEnd();
        }
    }
    catch (Exception exc)
    {
        throw exc;
    }

1 个答案:

答案 0 :(得分:1)

虽然您可以使用DataContractSerializer序列化IXmlSerializable,[Serializable],POCO等类型,就好像它们已经使用其本机序列化器序列化一样,但事实并非如此。您无法使用其他序列化程序序列化/反序列化[DataContract]类型,仍然可以获得您实际想要获得的结果。在这种情况下,XmlSerializer完全忽略[DataContract]属性,但它不会抛出异常。这是因为它假设它类似于具有公共字段和属性的另一个POCO(普通旧C#对象)类型,并尝试使用该模型对其进行序列化。

有关此问题的详情,请参阅http://blogs.msdn.com/b/sowmy/archive/2006/02/22/536747.aspxhttp://blogs.msdn.com/b/sowmy/archive/2006/05/14/why-prevent-datacontract-ixmlserializable.aspx

上的博文

所以,这里的解决方案是两件事之一: - 从DataContract类型中删除DataContract等,并开始使用[Serializable],IXmlSerializable,ISerializable,POCO或其他一些可用于XmlFormatter或XmlSerializer的序列化机制

  • 删除XmlSerializer用法并改为使用DataContractSerializer。