WCF OperationFormatter 遇到无效的消息正文
Posted
技术标签:
【中文标题】WCF OperationFormatter 遇到无效的消息正文【英文标题】:WCF OperationFormatter encountered an invalid Message body 【发布时间】:2019-05-13 11:42:21 【问题描述】:我的任务是将一个 wcf 项目合并到一个 web api 项目中。我已将 .svc 文件和 svc.cs 文件以及 web.config 的一部分复制到 web api 项目中,更新了服务名称,以便它们引用 web api 项目中的 svc 文件和端点以引用 a普通项目。
正在构建 Web api 项目,我通过输入其中一项服务的路径来测试 WCF 服务是否正常工作: http://localhost/WebAPI_Interface/Test.svc 这会提供一个网页,通知我我已经创建了一个服务(所以没有配置错误)。
我想测试一个服务操作 getavailablelibraries。运营合同如下:
[OperationContract(Action = "getavailablelibraries")]
[WebInvoke(Method = "POST", UriTemplate = "getavailablelibraries", RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.Wrapped)]
Libraries getavailablelibraries(SystemAuthentication auth);
在提琴手中,我设置了一个 POST 请求: http://localhost/WebAPI_Interface/Test.svc/getavailablelibraries
带有标题:内容类型:应用程序/json 和消息正文:
"auth":
"username" : "Test",
"password" : "Test",
"systemname" : "Test"
执行此请求会返回 504 错误。我打开了 WCF 跟踪,发现在处理消息时抛出了以下异常:
OperationFormatter 遇到无效的消息正文。预计会找到名称为“root”和命名空间“”的节点类型“元素”。找到名称为“”和命名空间“”的节点类型“无”
在提琴手中,当我在旧的 WCF 服务上尝试相同的请求时,它以 200 成功。
如果我重试相同的请求但这次没有消息正文,这一次我发现它在 getavailablelibraries 的调试器中中断,并且 auth 变量设置为 null。因此,将 json 反序列化到 SystemAuthentication 类中似乎是一个问题,但是,相同的 json 在原始 WCF 项目上工作,所以我不知所措。
有什么想法吗?
编辑: 我尝试将 Namespace 和 Name 属性添加到 ServiceContract 和 DataContract,但仍然出现相同的错误。 我切换了 BodyStyle = WebMessageBodyStyle.Bare,这导致了不同的错误:
无法使用 DataContractSerializer 反序列化具有根名称“”和根命名空间“”的 XML 正文(用于操作“getavailablelibraries”和合同(“ProcessExport”,“http://www.myurl.com/services”))。确保将 XML 对应的类型添加到服务的已知类型集合中。
当我将 BodyStyle 更改为 Bare 时,原来的 wcf 服务也停止工作: 无法反序列化数据协定类型“Services.SystemAuthentication”,因为找不到所需的数据成员“密码、系统名称、用户名”。
更多信息,错误堆栈跟踪:
在 System.ServiceModel.Dispatcher.DataContractJsonSerializerOperationFormatter.ValidateTypeObjectAttribute(XmlDictionaryReader 阅读器,布尔 isRequest)在 System.ServiceModel.Dispatcher.DataContractJsonSerializerOperationFormatter.DeserializeBody(XmlDictionaryReader 阅读器、MessageVersion 版本、字符串操作、MessageDescription messageDescription,Object[] 参数,布尔 isRequest) 在 System.ServiceModel.Dispatcher.OperationFormatter.DeserializeBodyContents(消息 消息,Object[] 参数,布尔 isRequest)在 System.ServiceModel.Dispatcher.OperationFormatter.DeserializeRequest(消息 消息,对象 [] 参数)在 System.ServiceModel.Dispatcher.DemultiplexingDispatchMessageFormatter.DeserializeRequest(消息 消息,对象 [] 参数)在 System.ServiceModel.Dispatcher.UriTemplateDispatchFormatter.DeserializeRequest(消息 消息,对象 [] 参数)在 System.ServiceModel.Dispatcher.CompositeDispatchFormatter.DeserializeRequest(消息 消息,对象 [] 参数)在 System.ServiceModel.Dispatcher.DispatchOperationRuntime.DeserializeInputs(MessageRpc& RPC)在 System.ServiceModel.Dispatcher.DispatchOperationRuntime.InvokeBegin(MessageRpc& RPC)在 System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage5(MessageRpc& RPC)在 System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage41(MessageRpc& RPC)在 System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage4(MessageRpc& RPC)在 System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage31(MessageRpc& RPC)在 System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage3(MessageRpc& RPC)在 System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage2(MessageRpc& RPC)在 System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage11(MessageRpc& RPC)在 System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage1(MessageRpc& rpc) 在 System.ServiceModel.Dispatcher.MessageRpc.Process(Boolean isOperationContextSet) 在 System.ServiceModel.Dispatcher.ChannelHandler.DispatchAndReleasePump(RequestContext 请求,布尔型 cleanThread,OperationContext 当前操作上下文)在 System.ServiceModel.Dispatcher.ChannelHandler.HandleRequest(RequestContext 请求,OperationContext currentOperationContext)在 System.ServiceModel.Dispatcher.ChannelHandler.AsyncMessagePump(IAsyncResult 结果)在 System.ServiceModel.Dispatcher.ChannelHandler.OnAsyncReceiveComplete(IAsyncResult 结果)在 System.Runtime.Fx.AsyncThunk.UnhandledExceptionFrame(IAsyncResult 结果)在 System.ServiceModel.Diagnostics.TraceUtility.c__DisplayClass14_0.
b__0(AsyncCallback 回调,IAsyncResult 结果)在 System.Runtime.AsyncResult.Complete(布尔完成同步)在 System.Runtime.InputQueue 1.AsyncQueueReader.Set(Item item) at System.Runtime.InputQueue
1.EnqueueAndDispatch(Item item, Boolean canDispatchOnThisThread) 在 System.Runtime.InputQueue1.EnqueueAndDispatch(T item, Action dequeuedCallback, Boolean canDispatchOnThisThread) at System.ServiceModel.Channels.SingletonChannelAcceptor
3.Enqueue(QueueItemType 项目,动作 dequeuedCallback,布尔值 canDispatchOnThisThread) 在 System.ServiceModel.Channels.HttpPipeline.EnqueueMessageAsyncResult.CompleteParseAndEnqueue(IAsyncResult 结果)在 System.ServiceModel.Channels.HttpPipeline.EnqueueMessageAsyncResult.HandleParseIncomingMessage(IAsyncResult 结果)在 System.Runtime.AsyncResult.SyncContinue(IAsyncResult 结果)在 System.ServiceModel.Channels.HttpPipeline.EnqueueMessageAsyncResult..ctor(ReplyChannelAcceptor 接受器,Action dequeuedCallback,HttpPipeline 管道, AsyncCallback 回调,对象状态)在 System.ServiceModel.Channels.HttpPipeline.EmptyHttpPipeline.BeginProcessInboundRequest(ReplyChannelAcceptor replyChannelAcceptor,Action dequeuedCallback,AsyncCallback 回调, 对象状态)在 System.ServiceModel.Channels.HttpChannelListener1.HttpContextReceivedAsyncResult
1.ProcessHttpContextAsync() 在 System.ServiceModel.Channels.HttpChannelListener`1.BeginHttpContextReceived(HttpRequestContext 上下文,Action acceptorCallback,AsyncCallback 回调,对象 州)在 System.ServiceModel.Activation.HostedHttpTransportManager.HttpContextReceived(HostedHttpRequestAsyncResult 结果)在 System.ServiceModel.Activation.HostedHttpRequestAsyncResult.HandleRequest() 在 System.ServiceModel.Activation.HostedHttpRequestAsyncResult.BeginRequest() 在 System.ServiceModel.Activation.HostedHttpRequestAsyncResult.OnBeginRequest(对象 州)在 System.ServiceModel.AspNetPartialTrustHelpers.PartialTrustInvoke(ContextCallback 回调,对象状态)在 System.ServiceModel.Activation.HostedHttpRequestAsyncResult.OnBeginRequestWithFlow(对象 州)在 System.Runtime.IOThreadScheduler.ScheduledOverlapped.IOCallback(UInt32 errorCode,UInt32 numBytes,NativeOverlapped* nativeOverlapped) 在 System.Runtime.Fx.IOCompletionThunk.UnhandledExceptionFrame(UInt32 错误,UInt32 bytesRead,NativeOverlapped* nativeOverlapped) 在 System.Threading._IOCompletionCallback.PerformIOCompletionCallback(UInt32 errorCode, UInt32 numBytes, NativeOverlapped* pOVERLAP)
【问题讨论】:
也许可以尝试使用 SoapUI 并添加为新的 REST 项目,以查看它如何格式化您的请求(它会自动生成测试请求)。另外,也许可以尝试将 body style 设置为 bare:BodyStyle = WebMessageBodyStyle.Bare
尝试将命名空间和名称属性添加到ServiceContract和DataContract。
【参考方案1】:
问题原来是由于消息处理程序可能引发了异常。 在 web api 项目的 Startup.Config 中,我们有一行: config.MessageHandlers.Add(new MessageLoggingHandler(ref globalLogger));
此 MessageLoggingHandler 类继承自 Microsoft 类 DelegatingHandler,并覆盖 SendAsync 函数以在进行 Web api 调用时进行一些日志记录。如果请求 Uri 包含“.svc/”,我们会检查并调用基类定义,并且它开始工作,因此可能是日志记录代码特定于 Web api 请求。
【讨论】:
以上是关于WCF OperationFormatter 遇到无效的消息正文的主要内容,如果未能解决你的问题,请参考以下文章
一步一步搭建客服系统 客户列表 - JS($.ajax)调用WCF 遇到的各种坑
WCF 错误:期待状态“元素”。遇到名称为“文本”、名称空间“”的 XML 格式的 post call