【问题标题】:How can we pass the class object as XML to WCF REST post METHOD?我们如何将类对象作为 XML 传递给 WCF REST post METHOD?
【发布时间】:2014-06-24 22:01:08
【问题描述】:

我有一个场景,我需要将类对象作为输入发送到 WCF REST 方法,如下所示。

[OperationContract]
        [WebInvoke(Method = "POST", UriTemplate = "/InsertContact", ResponseFormat = WebMessageFormat.Xml,
          RequestFormat = WebMessageFormat.Xml, BodyStyle = WebMessageBodyStyle.Wrapped)]
        int InsertContact(ContactType objContactType);

在 Fiddler 中得到以下错误

<Fault xmlns="http://schemas.microsoft.com/ws/2005/05/envelope/none"><Code><Value>Receiver</Value><Subcode><Value xmlns:a="http://schemas.microsoft.com/net/2005/12/windowscommunicationfoundation/dispatcher">a:InternalServiceFault</Value></Subcode></Code><Reason><Text xml:lang="en-US">Error in deserializing body of request message for operation 'InsertContact'. OperationFormatter encountered an invalid Message body. Expected to find node type 'Element' with name 'InsertContact' and namespace 'http://tempuri.org/'. Found node type 'Element' with name 'ContactType' and namespace ''</Text></Reason><Detail><ExceptionDetail xmlns="http://schemas.datacontract.org/2004/07/System.ServiceModel" xmlns:i="http://www.w3.org/2001/XMLSchema-instance"><HelpLink i:nil="true"/><InnerException><HelpLink i:nil="true"/><InnerException i:nil="true"/><Message>OperationFormatter encountered an invalid Message body. Expected to find node type 'Element' with name 'InsertContact' and namespace 'http://tempuri.org/'. Found node type 'Element' with name 'ContactType' and namespace ''</Message><StackTrace>   at System.ServiceModel.Dispatcher.DataContractSerializerOperationFormatter.DeserializeBody(XmlDictionaryReader reader, MessageVersion version, String action, MessageDescription messageDescription, Object[] parameters, Boolean isRequest)&#xD;
   at System.ServiceModel.Dispatcher.OperationFormatter.DeserializeBodyContents(Message message, Object[] parameters, Boolean isRequest)&#xD;
   at System.ServiceModel.Dispatcher.OperationFormatter.DeserializeRequest(Message message, Object[] parameters)</StackTrace><Type>System.Runtime.Serialization.SerializationException</Type></InnerException><Message>Error in deserializing body of request message for operation 'InsertContact'. OperationFormatter encountered an invalid Message body. Expected to find node type 'Element' with name 'InsertContact' and namespace 'http://tempuri.org/'. Found node type 'Element' with name 'ContactType' and namespace ''</Message><StackTrace>   at System.ServiceModel.Dispatcher.OperationFormatter.DeserializeRequest(Message message, Object[] parameters)&#xD;
   at System.ServiceModel.Dispatcher.DemultiplexingDispatchMessageFormatter.DeserializeRequest(Message message, Object[] parameters)&#xD;
   at System.ServiceModel.Dispatcher.UriTemplateDispatchFormatter.DeserializeRequest(Message message, Object[] parameters)&#xD;
   at System.ServiceModel.Dispatcher.CompositeDispatchFormatter.DeserializeRequest(Message message, Object[] parameters)&#xD;
   at System.ServiceModel.Dispatcher.DispatchOperationRuntime.DeserializeInputs(MessageRpc&amp; rpc)&#xD;
   at System.ServiceModel.Dispatcher.DispatchOperationRuntime.InvokeBegin(MessageRpc&amp; rpc)&#xD;
   at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage5(MessageRpc&amp; rpc)&#xD;
   at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage41(MessageRpc&amp; rpc)&#xD;
   at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage4(MessageRpc&amp; rpc)&#xD;
   at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage31(MessageRpc&amp; rpc)&#xD;
   at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage3(MessageRpc&amp; rpc)&#xD;
   at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage2(MessageRpc&amp; rpc)&#xD;
   at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage11(MessageRpc&amp; rpc)&#xD;
   at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage1(MessageRpc&amp; rpc)&#xD;
   at System.ServiceModel.Dispatcher.MessageRpc.Process(Boolean isOperationContextSet)</StackTrace><Type>System.ServiceModel.CommunicationException</Type></ExceptionDetail></Detail></Fault>

我想让我的 REST API 接受 JSON 或 XML 请求,具体取决于客户端。我需要在 WebInvoke 属性或 web.config 中设置此属性吗?

传递下面的 XML

<ContactType>
    <ContactTypeID>3</ContactTypeID>
    <Name>Assistant Sales Representative</Name>
    <ModifiedDate>2002-06-01T00:00:00</ModifiedDate>
 </ContactType>

谁能帮我解决这个问题?

【问题讨论】:

  • 您是否使用命名空间进行验证?如果没有,那么也许只需将其删除 - 然后重试。
  • @AnthonyHorne 传递此 XML 3销售助理代表2002-06-01T00:00:00
  • 我最近编写的服务允许用户发送 txt、XMLElement(或 Document)或实际对象。接口只是分别定义了它们。我需要将 System.Linq 更改为 System.XML(否则不起作用),就我而言,要求我删除 NS(因为供应商放入了无效的)
  • Fiddler 允许您指定 xml 响应版本。在我的 .NET 5.6 中,它要求我在 Composer 中选择 HTTP/1.1,否则会出现错误。 >1.1 给出错误。
  • @AnthonyHorne 我尝试了 1.1 版本并选择了更高版本。得到同样的错误。

标签: wcf rest wcf-rest


【解决方案1】:

错误指出了你遇到的问题:

预计会找到名称为“InsertContact”和命名空间“http://tempuri.org/”的节点类型“元素”。找到名称为“ContactType”和命名空间“”的节点类型“元素”

当您将WebInvokeBodyStyle 声明为Wrapped 时,这意味着您必须包装带有操作名称(和适当的XML 命名空间)的请求正文。

下面的代码显示了一种将值传递给操作的方法。

public class StackOverflow_23526051
{
    [ServiceContract]
    public interface ITest
    {
        [WebInvoke(Method = "POST", UriTemplate = "/InsertContact", ResponseFormat = WebMessageFormat.Xml,
          RequestFormat = WebMessageFormat.Xml, BodyStyle = WebMessageBodyStyle.Wrapped)]
        int InsertContact(ContactType objContactType);
    }
    public class Service : ITest
    {
        public int InsertContact(ContactType objContactType)
        {
            Console.WriteLine("objContactType: {0}", objContactType);
            return 0;
        }
    }

    [DataContract(Name = "ContactType", Namespace = "")]
    public class ContactType
    {
        [DataMember(Order = 1)]
        public int ContactTypeID { get; set; }

        [DataMember(Order = 2)]
        public string Name { get; set; }

        [DataMember(Order = 3)]
        public string ModifiedDate { get; set; }

        public override string ToString()
        {
            return string.Format("ContactType[Id={0},Name={1},ModifiedDate={2}]", ContactTypeID, Name, ModifiedDate);
        }
    }

    public static void Test()
    {
        string baseAddress = "http://" + Environment.MachineName + ":8000/Service";
        WebServiceHost host = new WebServiceHost(typeof(Service), new Uri(baseAddress));
        host.Open();
        Console.WriteLine("Host opened");

        WebClient c = new WebClient();
        c.Headers.Add(HttpRequestHeader.ContentType, "text/xml");
        var xml = @"<t:objContactType>
            <ContactTypeID>3</ContactTypeID>
            <Name>Assistant Sales Representative</Name>
            <ModifiedDate>2002-06-01T00:00:00</ModifiedDate>
         </t:objContactType>";

        xml = "<t:InsertContact xmlns:t=\"http://tempuri.org/\">" + xml + "</t:InsertContact>";

        Console.WriteLine(c.UploadString(baseAddress + "/InsertContact", xml));
        Console.WriteLine();

        // To find out the request format: use the following 5 lines, look at Fiddler
        var factory = new WebChannelFactory<ITest>(new Uri(baseAddress));
        var proxy = factory.CreateChannel();
        proxy.InsertContact(new ContactType { ContactTypeID = 123, ModifiedDate = "the date", Name = "John Doe" });
        ((IClientChannel)proxy).Close();
        factory.Close();

        Console.Write("Press ENTER to close the host");
        Console.ReadLine();
        host.Close();
    }
}

【讨论】:

  • carlosfigueira 感谢您的帮助。我对 Wrap 有几个问题。 1. 这会影响 XML 对象吗? 2.我必须将类ContactType对象转换成XML。 xml 字符串会有所不同吗? 3.我已经按照给定的方式实现了,但是没有返回请求ContactTypeId。
  • 正文样式影响需要作为请求正文传递的 XML 正文的格式(模式)。只要 XML 遵循指定的模式,它就可以工作。尝试使用 WCF 客户端 发送请求(正如我在代码的最后部分中展示的那样),并查看使用 Fiddler 等工具发送的内容。这将准确地告诉您请求需要发送的格式。
  • 我将 xml 字符串发送为 "tempuri.org\">3助理销售代表2002-06-01T00:00:00" 。在服务中验证如果contacttype 对象不为null 返回ContactTypeId。我总是将contactId设为零而不是三。
  • 如果没有看到服务/类的完整实现,就不可能知道格式应该是什么。如果您针对您的问题发布 small, self-contained, complete example(就像我在回答中所说的那样),那么我们将能够提供更多帮助。
猜你喜欢
  • 2014-06-23
  • 2014-01-06
  • 2015-04-10
  • 1970-01-01
  • 1970-01-01
  • 2019-10-21
  • 2016-08-13
  • 2012-03-30
  • 1970-01-01
相关资源
最近更新 更多