我正在尝试使用 WCF-WebHttp 适配器的 BizTalk 2013 REST 功能。
我正在尝试模拟公开可用的 REST API 的行为 - Nordnet nExt API。特别是,我试图模拟登录功能的行为:对 /[version]/login?service=[service]&auth=[blob] 的空 POST 请求应该返回一个包含一堆参数的响应正文包括一个会话令牌(此时响应并不重要,因为我还没有实现它)
我已经执行了以下步骤:
- 设置具有相关接收位置的接收端口
- 将接收位置的适配器类型设置为 WCF-WebHttp
- 将端点地址设置为 /1/login/Service1.svc (目前我推迟进行任何 URL 重写并仅在 URL 中引用强制性 WCF 服务定义文件)
- 将 HTTP 方法和 URL 映射部分设置为:
<BtsHttpUrlMapping> <Operation Name="Login" Method="POST" Url="?service={SERVICE}&auth={AUTH}"/> <Operation Name="Logout" Method="DELETE" Url="/{SESSION_KEY}"/> </BtsHttpUrlMapping>
- 将 URL 参数映射到一些相关的上下文属性
- 使用 BizTalk WCF 配置向导在 IIS 中创建与上述参数匹配的应用程序
使用本地机器上的PostMan将空 POST 提交到 http:// localhost
/1/login/Service1.svc?service=foo&auth=bar 会产生以下错误消息:
<Fault
xmlns="http://schemas.microsoft.com/ws/2005/05/envelope/none">
<Code>
<Value>Sender</Value>
<Subcode>
<Value
xmlns:a="http://schemas.microsoft.com/ws/2005/05/addressing/none">a:DestinationUnreachable
</Value>
</Subcode>
</Code>
<Reason>
<Text xml:lang="en-US">The message with To 'http://localhost/1/login/Service1.svc?service=foo&auth=bar' cannot be processed at the receiver, due to an AddressFilter mismatch at the EndpointDispatcher. Check that the sender and receiver's EndpointAddresses agree.</Text>
</Reason>
</Fault>
为什么?
我的预感是它与空的 POST 正文有关,因为有关来自普通 WCF 服务的类似消息的其他一些问题表明该消息应包含 WS-Addressing 'To' 字段。但是,这是 REST,而不是 SOAP,因此此属性不相关。与引用此错误消息的大多数其他问题不同,我无法控制服务定义,因为服务实例是由 BizTalk 通过自定义主机工厂创建的(这就是它做事的方式,与所有 BizTalk WCF 适配器相同) )
如何让 BizTalk-surfaced WCF 服务识别空 POST 正文是正确的并将其路由到正确的端点?
编辑#1:
一些进展。将 WebHttpBehaviour 应用到接收位置会阻止此错误消息出现,但会出现新的错误消息。现在对 POST 请求的响应是:
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html
xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Service</title>
<style>BODY { color: #000000; background-color: white; font-family: Verdana; margin-left: 0px; margin-top: 0px; } #content { margin-left: 30px; font-size: .70em; padding-bottom: 2em; } A:link { color: #336699; font-weight: bold; text-decoration: underline; } A:visited { color: #6699cc; font-weight: bold; text-decoration: underline; } A:active { color: #336699; font-weight: bold; text-decoration: underline; } .heading1 { background-color: #003366; border-bottom: #336699 6px solid; color: #ffffff; font-family: Tahoma; font-size: 26px; font-weight: normal;margin: 0em 0em 10px -20px; padding-bottom: 8px; padding-left: 30px;padding-top: 16px;} pre { font-size:small; background-color: #e5e5cc; padding: 5px; font-family: Courier New; margin-top: 0px; border: 1px #f0f0e0 solid; white-space: pre-wrap; white-space: -pre-wrap; word-wrap: break-word; } table { border-collapse: collapse; border-spacing: 0px; font-family: Verdana;} table th { border-right: 2px white solid; border-bottom: 2px white solid; font-weight: bold; background-color: #cecf9c;} table td { border-right: 2px white solid; border-bottom: 2px white solid; background-color: #e5e5cc;}</style>
</head>
<body>
<div id="content">
<p class="heading1">Service</p>
<p>Endpoint not found.</p>
</div>
</body>
</html>
...这本身几乎完全没用。
深入WCF跟踪日志,实际问题其实是:
<TraceRecord Severity="Warning" Channel="Analytic" xmlns="http://schemas.microsoft.com/2004/10/E2ETraceEvent/TraceRecord">
<TraceIdentifier>http://msdn.microsoft.com/en-US/library/System.ServiceModel.Diagnostics.TraceHandledException.aspx</TraceIdentifier>
<Description>Handling an exception. Exception details: System.InvalidOperationException: The incoming HTTP request's URI 'http://localhost/1/login/Service1.svc?service=foo&auth=bar' does not match any service operation.</Description>
<AppDomain>/LM/W3SVC/1/ROOT/1/login-2-130560354135646221</AppDomain>
<Exception>
<ExceptionType>System.InvalidOperationException, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</ExceptionType>
<Message>The incoming HTTP request's URI 'http://localhost/1/login/Service1.svc?service=foo&auth=bar' does not match any service operation.</Message>
<StackTrace>
at System.Runtime.Diagnostics.EtwDiagnosticTrace.WriteExceptionToTraceString(XmlTextWriter xml, Exception exception, Int32 remainingLength, Int32 remainingAllowedRecursionDepth)
at System.Runtime.Diagnostics.EtwDiagnosticTrace.ExceptionToTraceString(Exception exception, Int32 maxTraceStringLength)
at System.Runtime.Diagnostics.EtwDiagnosticTrace.GetSerializedPayload(Object source, TraceRecord traceRecord, Exception exception, Boolean getServiceReference)
at System.Runtime.TraceCore.HandledExceptionWarning(EtwDiagnosticTrace trace, String param0, Exception exception)
at System.ServiceModel.Dispatcher.HttpUnhandledOperationInvoker.Invoke(Object instance, Object[] inputs, Object[]& outputs)
at System.ServiceModel.Dispatcher.DispatchOperationRuntime.InvokeBegin(MessageRpc& rpc)
at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage5(MessageRpc& rpc)
at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage31(MessageRpc& rpc)
at System.ServiceModel.Dispatcher.MessageRpc.Process(Boolean isOperationContextSet)
at System.ServiceModel.Dispatcher.ChannelHandler.DispatchAndReleasePump(RequestContext request, Boolean cleanThread, OperationContext currentOperationContext)
at System.ServiceModel.Dispatcher.ChannelHandler.HandleRequest(RequestContext request, OperationContext currentOperationContext)
at System.ServiceModel.Dispatcher.ChannelHandler.AsyncMessagePump(IAsyncResult result)
at System.Runtime.ActionItem.DefaultActionItem.TraceAndInvoke()
at System.Runtime.ActionItem.CallbackHelper.InvokeWithoutContext(Object state)
at System.Runtime.IOThreadScheduler.ScheduledOverlapped.IOCallback(UInt32 errorCode, UInt32 numBytes, NativeOverlapped* nativeOverlapped)
at System.Runtime.Fx.IOCompletionThunk.UnhandledExceptionFrame(UInt32 error, UInt32 bytesRead, NativeOverlapped* nativeOverlapped)
at System.Threading._IOCompletionCallback.PerformIOCompletionCallback(UInt32 errorCode, UInt32 numBytes, NativeOverlapped* pOVERLAP)
</StackTrace>
<ExceptionString>System.InvalidOperationException: The incoming HTTP request's URI 'http://localhost/1/login/Service1.svc?service=foo&auth=bar' does not match any service operation.</ExceptionString>
</Exception>
</TraceRecord>
所以问题仍然存在:为什么?
编辑#2:
我下载并安装了WCF-WebHttpAdapter 示例代码,看看有什么不同 - 令人失望的是它没有包含 WebHttp 接收位置,但它确实促使我尝试更多的东西。我试图复制已经存在的 WSHttp 接收位置,以使该应用程序以 REST 方式工作,我发现:
- WebHttpBehaviour 似乎是一条红鲱鱼
- 删除查询参数并用简单的 /route/segments 替换它们似乎按预期工作 - 我现在收到服务故障和暂停消息,这表明消息正在通过 WCF 端点。
那么现在的问题是:WCF-WebHttp 适配器是否正确支持查询参数,或者此功能是否损坏?