Как создать исключение WCF с помощью настраиваемого заголовка и тела Soap

  1. Я знаю, как использовать [FaultException] и бросать Customized [DataContract] в WCF
  2. Я знаю, как вернуть мыльное сообщение с настраиваемыми заголовками и тегами тела, используя [MessageContract]

Однако я собираюсь спросить: как создать [FaultException] в WCF с настроенными заголовками и телом? Потому что, когда я использую [FaultException] для создания [MessageContract], он всегда заключает мои заголовки и теги тела в тег тела.

Это не то, чего я хочу. Большинство клиентов SOAP не понимают WCF [FaultException].

<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
  <s:Header />
  <s:Body>
    <s:Fault>
      <faultcode>s:Client</faultcode>
      <faultstring xml:lang="en-CH" />
      <detail>
        <CustomizedError xmlns="http://schemas.datacontract.org/2004/07/PlayWcfFault" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
          <BodyTag1>Hello BodyTag1</BodyTag1>
          <HeaderTag1>Hello HeaderTag1</HeaderTag1>
        </CustomizedError>
      </detail>
    </s:Fault>
  </s:Body>
</s:Envelope>

    [MessageContract]
    public class CustomizedError
    {
        [MessageHeader] public string HeaderTag1;
        [MessageBodyMember] public string BodyTag1;
    }

    [ServiceContract]
    public interface IService1
    {

        [OperationContract]
        [FaultContract(typeof(CustomizedError))]
        CustomizedError GetData();
    }

    public class Service1 : IService1
    {
        public CustomizedError GetData()
        {
            CustomizedError fault = new CustomizedError
            {
                HeaderTag1 = "Hello HeaderTag1",
                BodyTag1 = "Hello BodyTag1",
            };
            throw new FaultException<CustomizedError>(fault, "");
            // return fault;
        }

    }

Мыльное сообщение, которое я хочу, это


<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
  <s:Header />
          <HeaderTag1>Hello HeaderTag1</HeaderTag1>
</s:Header >
  <s:Body>
    <s:Fault>
          <BodyTag1>Hello BodyTag1</BodyTag1>
      </detail>
    </s:Fault>
  </s:Body>
</s:Envelope>


person Vincent    schedule 15.09.2019    source источник


Ответы (1)


Я смущен тем, почему вы определяете структуру мыльных сообщений в этом формате. Но, насколько мне известно, интерфейс IErrorHandler может настроить сообщение об ошибке при захвате ошибки связи. Вот пример, используемый для фиксации ошибок во время связи.

Конечная точка ошибки Hadler в моем хосте - WCF - поведение

Мы можем добавить собственный заголовок сообщения в метод ProvideFault. Пожалуйста, рассмотрите приведенный ниже код.

public void ProvideFault(Exception error, MessageVersion version, ref Message fault)
        {
            FaultException faultException = new FaultException(error.Message);
            MessageFault messageFault = faultException.CreateMessageFault();
            fault = Message.CreateMessage(version, messageFault, error.Message);
            MessageHeader mh = MessageHeader.CreateHeader("itemname", "apptest", "34");
            fault.Headers.Add(mh);
        }

Результат.
введите здесь описание изображения

Не стесняйтесь, дайте мне знать, если я могу чем-то помочь.
Обновлено.

class Program
    {
        static void Main(string[] args)
        {
            Uri uri = new Uri("http://localhost:4386");
            WSHttpBinding binding = new WSHttpBinding();
            binding.Security.Mode = SecurityMode.None;

            using (ServiceHost sh = new ServiceHost(typeof(TestService), uri))
            {
                sh.AddServiceEndpoint(typeof(ITestService), binding, "");
                ServiceMetadataBehavior smb;
                smb = sh.Description.Behaviors.Find<ServiceMetadataBehavior>();
                if (smb == null)
                {
                    smb = new ServiceMetadataBehavior()
                    {
                        HttpGetEnabled = true
                    };

                    sh.Description.Behaviors.Add(smb);

                }
                Binding mexbinding = MetadataExchangeBindings.CreateMexHttpBinding();
                sh.AddServiceEndpoint(typeof(IMetadataExchange), mexbinding, "mex");


                sh.Opened += delegate
                {
                    Console.WriteLine("service is ready");
                };
                sh.Closed += delegate
                {
                    Console.WriteLine("service is closed");
                };
                sh.Open();

                Console.ReadLine();

                sh.Close();
            }
        }
    }
    [ServiceContract]
    public interface ITestService
    {
        [OperationContract]
        int Div(int x, int y);
    }

    [ServiceBehavior]
    public class TestService : ITestService
    {
        public int Div(int x, int y)
        {
            if (y == 0)
            {
                FaultReason reason = new FaultReason("The divisor cannot be Zero");
                FaultCode code = new FaultCode("NotZero", "mynamespace",new FaultCode("mysubcode"));
                throw new FaultException(reason,code);
            }
            return x / y;
        }
}

Чтобы создать поле ActivityID, мы должны включить трассировку и ведение журнала сообщений на стороне сервера.

  <system.diagnostics>
    <sources>
      <source name="System.ServiceModel" propagateActivity="true" switchValue="Information, ActivityTracing">
        <listeners>
          <add type="System.Diagnostics.XmlWriterTraceListener" name="xmlLog" initializeData="myLogs.svclog"/>
        </listeners>
      </source>
    </sources>
  </system.diagnostics>
  <system.serviceModel>
    <diagnostics>
      <messageLogging logEntireMessage="true" logMessagesAtServiceLevel="true" logMessagesAtTransportLevel="false"/>
    </diagnostics>
  </system.serviceModel>

Ссылка.
О поле ActivityID
Настройка трассировки и ведения журнала сообщений
Когда вызов на стороне клиента передает параметр 0. Мы фиксируем HTTP-запрос с помощью fiddler.
введите здесь описание изображения

person Abraham Qian    schedule 16.09.2019
comment
Спасибо, Авраам Кьян. Это очень близко к требованию! Мне нужно приложение WCF, способное выдавать мыло такого формата: docs.microsoft.com/en-us/openspecs/windows_protocols/ms-wstep/ - person Vincent; 19.09.2019
comment
Этого можно добиться с помощью службы WCF, созданной с помощью wshttpbinding. Затем мы выбрасываем пользовательское исключение Faultexception. Пожалуйста, обратитесь к моему обновленному ответу. - person Abraham Qian; 20.09.2019