Как остановить службу собственного размещения WCF при необработанных ошибках? - PullRequest
1 голос
/ 26 мая 2011

У меня есть собственная служба WCF, которая работает как служба Windows. Для тестов я запускаю его как консольное приложение.

Я бы хотел перехватить все необработанные исключения, возникающие в службе, и завершить работу хоста. Я хотел бы перехватить все исключения, не связанные с FaultException, которые возникают при создании ответа, а также все исключения, возникающие в «режиме ожидания», т. Е. Генерируемые из некоторых рабочих потоков.

К сожалению, я не могу обработать исключения ни IErrorHandler (не вызывается), ни AppDomain.CurrentDomain.UnhandledException (не вызывается).

Есть какие-нибудь подсказки?

App.config:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <system.serviceModel>
    <behaviors>
      <serviceBehaviors>
        <behavior name="TestServiceBahavior">
          <serviceMetadata httpGetEnabled="true" />
        </behavior>
      </serviceBehaviors>
    </behaviors>
    <services>
      <service behaviorConfiguration="TestServiceBahavior" name="WcfErrorHandling.TestService">
        <host>
          <baseAddresses>
            <add baseAddress="http://localhost:8001/TestService" />
          </baseAddresses>
        </host>
        <endpoint address="" binding="basicHttpBinding"
          bindingConfiguration="" contract="WcfErrorHandling.ITestService" />
        <endpoint address="mex" binding="mexHttpBinding"
          contract="IMetadataExchange" />
      </service>
    </services>
  </system.serviceModel>
</configuration>

код:

using System;
using System.Linq;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Dispatcher;

namespace WcfErrorHandling
{
    [ServiceContract]
    interface ITestService
    {
        [OperationContract]
        string SayHello(string param);
    }

    public class TestService : ITestService
    {
        public string SayHello(string param)
        {
            if (param == "ae")
                throw new ArgumentException("argument exception");
            if (param == "fe")
                throw new FaultException("fault exception");
            return "hello";
        }
    }

    public class TestHost : ServiceHost, IErrorHandler
    {
        public TestHost()
            : base(typeof(TestService))
        {
        }

        public void Start()
        {
            AppDomain.CurrentDomain.UnhandledException += 
                (sender, ea) => UnhandledExceptionHandler(ea.ExceptionObject as Exception);

            Open();
            foreach (var channelDispatcher in ChannelDispatchers.OfType<ChannelDispatcher>())
                channelDispatcher.ErrorHandlers.Add(this);
        }

        public void ProvideFault(Exception error, MessageVersion version, ref Message fault)
        {
            // do nothing
        }

        public bool HandleError(Exception error)
        {
            if (!(error is FaultException))
                UnhandledExceptionHandler(error);
            return true;
        }

        private void UnhandledExceptionHandler(Exception ex)
        {
            Close();
            Environment.Exit(1);
        }
    }

    public class Program
    {
        public static void Main(string[] args)
        {
            var testHost = new TestHost();
            testHost.Start();
            Console.Out.WriteLine("Press any key to exit...");
            Console.ReadKey();
            testHost.Close();
        }
    }
}

1 Ответ

0 голосов
/ 09 июня 2011

Была такая же проблема, это решило ее для меня:

Заставьте ваш сервис реализовать этот интерфейс:

public class MyService : System.ServiceModel.Description.IServiceBehavior

Реализуйте это так:

    public void AddBindingParameters(System.ServiceModel.Description.ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, System.Collections.ObjectModel.Collection<System.ServiceModel.Description.ServiceEndpoint> endpoints, System.ServiceModel.Channels.BindingParameterCollection bindingParameters)
    {
        return;
    }

    public void ApplyDispatchBehavior(System.ServiceModel.Description.ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
    {
        foreach (ChannelDispatcher channel in serviceHostBase.ChannelDispatchers) { channel.ErrorHandlers.Add(new ErrorHandler()); }
    }

    public void Validate(System.ServiceModel.Description.ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
    {
        return;
    }

И добавить этот класс:

public class ErrorHandler : IErrorHandler
{
   bool IErrorHandler.HandleError(Exception error)
    { return true; }
   void IErrorHandler.ProvideFault(Exception error, System.ServiceModel.Channels.MessageVersion version, ref System.ServiceModel.Channels.Message fault)
    { return;  }
}

Теперь установите точку останова на HandleError .. она покажет вам исключение

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...