Как предотвратить, чтобы исключение канала переставало работать службе WCF? - PullRequest
1 голос
/ 25 декабря 2009

Я создал одноэлементную службу WCF с помощью netNamedPipeBinding. Когда возникает исключение канала, он покидает канал в неисправном состоянии, и все последующие операции выдают исключения. Как я могу предотвратить это? Я хочу, чтобы исключение TimeoutException или любое другое распространенное исключение приводило к сбою только одной операции, а не к отключению службы.

Ответы [ 2 ]

8 голосов
/ 25 декабря 2009

Вам нужно поместить исключения на стороне сервера в FaultException. Если вы контролируете оба конца провода, и оба конца являются .NET, вы можете просто обернуть исключение .NET в FaultException<T> и отправить его обратно клиенту. Таким образом, канал остается пригодным для использования.

См. Определение и обработка ошибок в контрактах и ​​услугах на MSDN для получения дополнительной информации, а также ознакомьтесь с этой статьей о CodeProject и этой записью в блоге Зачем использовать WCF FaultException на ту же тему.

Кроме того, чтобы упростить свою жизнь, воспользуйтесь интерфейсом IErrorHandler , который вы можете реализовать на стороне сервера для глобального обнаружения исключений и их преобразования в ошибки. Также смотрите множество постов в блоге на эту тему, например IErrorHandler: универсальный конвертер ошибок или многие другие (Bing или Google для получения дополнительной информации).

Чтобы сделать вашу жизнь еще проще , вы можете реализовать IErrorHandler как поведение, которое вы можете включить или отключить в своей службе - либо в конфигурации службы, либо путем установки атрибута в своем классе службы , В интернете довольно много реализаций, одна мне нравится здесь: Полезное поведение WCF: IErrorHandler .

2 голосов
/ 04 января 2010

Есть другой способ. Вы можете создать клиентский прокси для каждого запроса, вместо того чтобы использовать один экземпляр для более чем одного запроса. Таким образом, если канал переходит в неисправное состояние, он все равно удаляется.

Это немного сложно, потому что вы не должны располагать каналом, кроме того, что он может быть IDisposable.

Это не сработает:

using(var channel = channelFactory.CreateChannel())
{
    return channel.ServiceMethod(parameter);
}

Вместо этого вы должны:

public static class Service<T>
{
    public static ChannelFactory<T> _channelFactory = new ChannelFactory<T>("");

    public static TResult Use<TResult>(Func<T, TResult> func)
    {
        TResult output;
        var channel = (IClientChannel)_channelFactory.CreateChannel();
        bool success = false;
        try
        {
            output = func((T)proxy);
            channel.Close();
            success = true;
        }
        finally
        {
            if (!success)
            {
                proxy.Abort();
            }
        }
        return output;
    }
}

return Service<IService>.Use(channel =>
{
    return channel.ServiceMethod(parameter);
});
...