BizTalk Orchestration: ответьте нетипизированной ошибкой SOAP

У меня есть оркестровка BizTalk 2009 с типом порта запрос-ответ, который публикуется как веб-служба WCF Basic-HTTP. У порта есть одна операция, и у этой операции есть сообщения запроса и ответа с соответствующими схемами. После получения запроса через этот порт в некоторых случаях клиенту следует вернуть сообщение об ошибке вместо стандартного ответного сообщения. Мне трудно вернуть клиенту правильное сообщение о неисправности. Я хотел бы иметь возможность устанавливать элементы faultcode и faultstring сообщения об ошибке SOAP. Вот что я пробовал:

Добавление сообщения об ошибке типа String: я попытался добавить к операции сообщение об ошибке со строкой типа сообщения. В рамках оркестровки я создал строковое сообщение и отправил его в качестве ответа. Неисправность, возвращенная клиенту, выглядела так:

<?xml version="1.0" encoding="utf-8"?>
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
   <s:Body>
      <s:Fault>
         <faultcode xmlns:a="http://schemas.microsoft.com/net/2005/12/windowscommunicationfoundation/dispatcher">a:InternalServiceFault</faultcode>
         <faultstring xml:lang="en-US">&lt;?xml version="1.0" encoding="utf-8"?>
&lt;string>This is the error message.&lt;/string></faultstring>
         <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 i:nil="true"/>
               <Message>&lt;?xml version="1.0" encoding="utf-8"?>
&lt;string>This is the error message.&lt;/string></Message>
               <StackTrace>at Microsoft.BizTalk.Adapter.Wcf.Runtime.BizTalkAsyncResult.End() ...</StackTrace>
               <Type>Microsoft.BizTalk.Adapter.Wcf.Runtime.BizTalkNackException</Type>
            </ExceptionDetail>
         </detail>
      </s:Fault>
   </s:Body>
</s:Envelope>

Это почти работает, за исключением того, что элемент faultstring содержит сериализованную версию моей строки xml вместо самой строки. Я также не могу установить элемент faultcode.

Добавление сообщения об ошибке типа http://schemas.xmlsoap.org/soap/envelope/#Fault. Я подумал, что смогу убедить BizTalk вернуть сообщение об ошибке в соответствии со строками, которые я ожидал бы, если бы создал элемент Fault и отправил его. Поэтому я добавил сообщение об ошибке типа http://schemas.xmlsoap.org/soap/envelope/#Fault, создал соответствующее сообщение и отправил его в качестве ответа. Результат был таким же, как и выше, за исключением того, что вместо строки элемент faultstring содержал раздел CDATA со всем xml-сообщением, которое я создал внутри.

Так что я сейчас застрял; Я чувствую, что это должно быть простой задачей в BizTalk. Опубликована документация по MSDN, Как выбросить исключения сбоя из оркестровок как WCF Services, ничего не говорит вам о том, «как» генерировать исключения сбоя, за исключением того, что они могут быть выброшены и что вам нужно установить includeExceptionDetailInFaults в конфигурации (что я уже сделал).

Есть ли у кого-нибудь предложения о том, как это можно сделать в BizTalk 2009?


person Michael Petito    schedule 14.10.2010    source источник
comment
С BizTalk нет ничего простого :)   -  person Nix    schedule 15.10.2010
comment
@Nix: Согласен! Я не сказал, что это просто, просто так должно быть.   -  person Michael Petito    schedule 15.10.2010


Ответы (2)


Я решил эту точную проблему, добавив настраиваемый WCF IDispatchMessageInspector, в котором я прочитал текст причины из сериализованного сообщения, а затем вернул новое сообщение System.ServiceModel.FaultException, используя десериализованный текст причины.

В оркестровке BizTalk я использую System.String в качестве типа сообщения об ошибке PortType.

public class HandleUntypedSoapFault : IDispatchMessageInspector
{

    public void BeforeSendReply(ref System.ServiceModel.Channels.Message reply, object correlationState)
    {

        if (reply.IsFault)
        {

            MessageBuffer buffer = reply.CreateBufferedCopy(int.MaxValue);
            MessageFault messageFault = MessageFault.CreateFault(buffer.CreateMessage(), int.MaxValue);

            if (!messageFault.HasDetail)
            {
                reply = buffer.CreateMessage();
                return;
            }

            using (XmlReader reader = XmlReader.Create(new StringReader(messageFault.Reason.ToString())))
            {
               reader.MoveToContent();
               string _faultText =  reader.ReadElementContentAsString();
            }

            reply = Message.CreateMessage(
                reply.Version, 
                new FaultException(
                    _faultText, 
                    new FaultCode("client")).CreateMessageFault(),
                null);
        }
    }
}

Теперь SoapFault будет выглядеть примерно так:

<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
   <s:Body>
      <s:Fault>
         <faultcode>s:Client</faultcode>
         <faultstring xml:lang="en-US">An untyped SoapFault from my BizTalk orchestration. This text was set in the orchestration.</faultstring>
      </s:Fault>
   </s:Body>
</s:Envelope>
person magnus    schedule 09.09.2013
comment
Хотя я больше не могу протестировать этот подход, судя по вашим результатам, это должен быть правильный ответ. Спасибо! - person Michael Petito; 09.09.2013

Напомнил об этой длинной беседе, в которой я участвовал некоторое время назад: http://social.msdn.microsoft.com/forums/en-US/biztalkr2adapters/thread/f69ec7af-a490-4229-81d4-3d1b41bf9c48/

Они ссылаются на образец SDK, который может вам помочь, но это типизированное (а не нетипизированное, как вы просили) исключение сбоя.

person NealWalters    schedule 20.01.2011
comment
К сожалению, мне так и не удалось выяснить, как отреагировать на нетипизированную ошибку, и я совершенно убежден, что в BizTalk 2009 это просто невозможно. В итоге я вернул сериализованную строку и потребовал от клиентов десериализации сообщения. - person Michael Petito; 17.11.2011