Несоответствие AddressFilter при использовании адаптера BizTalk REST - почему?
Я испытываю функциональность BizTalk 2013 REST с помощью адаптера WCF-WebHttp.
Я пытаюсь смоделировать поведение общедоступного REST API - API Nordnet nExt. В частности, я пытаюсь смоделировать поведение функции входа в систему: пустой запрос POST для /[version]/login? Service=[service]&auth=[blob] должен вернуть тело ответа с кучей параметров в нем включая токен сеанса (ответ на данный момент не важен, так как я его пока не реализую)
Я выполнил следующие шаги:
- настроить порт приема со связанным местоположением приема
- установите тип адаптера получающего местоположения в WCF-WebHttp
- установите адрес конечной точки равным /1/login/Service1.svc (на данный момент я откладываю любую перезапись URL и просто ссылаюсь на файл обязательного определения службы WCF в URL)
- установите метод 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 предполагают, что сообщение должно содержать поле "To" WS-Addressing. Однако это REST, а не SOAP, поэтому это свойство не имеет значения. В отличие от большинства других вопросов, относящихся к этому сообщению об ошибке, у меня нет контроля над определением службы, так как экземпляр службы создается BizTalk через настраиваемую фабрику хостов (именно так все и происходит, как и во всех адаптерах BizTalk WCF).)
Как я могу заставить службу WCF с поддержкой BizTalk распознать, что пустое тело 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, которое уже было там, чтобы заставить это приложение работать RESTful, и я обнаружил, что:
- WebHttpBehaviour, кажется, красная сельдь
- Удаление параметров запроса и замена их на простые / route / сегменты, кажется, работает как ожидалось - теперь я получаю сообщения об ошибках службы и приостановленные сообщения, которые указывают, что сообщение проходит через конечную точку WCF.
Тогда возникает вопрос: правильно ли адаптер WCF-WebHttp поддерживает параметры запроса или эта функция не работает?
1 ответ
Я вижу две проблемы здесь. Во-первых, вы настроили GET на принимающем порту и попробуйте POST. Если тело запроса должно быть пустым, вам, вероятно, следует использовать GET. Если вы хотите использовать POST, измените POST в конфигурации.
Во-вторых, когда BizTalk получает запрос, тело запроса вставляется в тело сообщения. Если тело сообщения пустое, BizTalk завершается ошибкой. Вы должны создать пользовательский конвейер на принимающем порту, который создает тело сообщения на основе схемы, ожидаемой оркестровкой. Если продвигаемые переменные основаны на сообщениях, их необходимо вставить в сообщение.
Когда тело сообщения на месте, оно должно работать как положено.