Службы WCF REST-общая обработка исключений

у меня много устаревшего кода, который теперь является бэкэндом для службы WCF REST-раньше это был обычный бэкэнд службы WCF, если это имеет значение. Я хочу реализовать механизм, который поймает любое исключение в любом методе и проанализирует его. Если это окажется известной ошибкой, она будет обработана и превращена в дружественную ошибку.

Я знаю, что могу бросить FaultException или WebProtocolException вместо "обычных" исключений, но есть много мест, где создаются исключения по всему коду, и искать их все довольно болезненный вариант.

Я попытался добавить расширение поведения конечной точки, которое создает новое поведение, которое переопределяет standard WebHttpBehavior.AddServerErrorHandlers метод и добавляет мои обработчики ошибок (IErrorHandler реализации) в коллекцию обработчиков ошибок диспетчера конечных точек. Внутри обработчиков ошибок я анализирую исключение и создаю (или не создаю) желаемую ошибку на основе этого исключения.

Я ожидал, что этот механизм вернет custom данные для любого известного исключения, но я ошибался. Старый добрый Microsoft реализовал замечательный неизбежный WebHttpBehavior2, что, безусловно, добавляет внутренний Microsoft.ServiceModel.Web.WebErrorHandler в конец коллекции обработчиков ошибок диспетчера конечных точек. Этот обработчик игнорирует все ранее выполненные обработчики и распознает только небольшой набор исключений, в то время как большинство интерпретируется как "внутренняя ошибка сервера", и ничего больше.

вопрос в том, нахожусь ли я на правильном пути, и есть способ отключить этот обработчик в механизме WCF REST или вводит его с новым исключением (например, когда любое исключение поймано, оно сначала обрабатывается моими обработчиками, и если они бросают/возвращают, например, FaultException, то это новое исключение предоставляется Microsoft.ServiceModel.Web.WebErrorHandler вместо оригинального). Если все мои эксперименты с IErrorHandler и расширения поведения бесполезны, что такое альтернатива? Опять же, я действительно не хочу изменять логику метания исключений, я хочу, чтобы одно место ловило исключения и обрабатывать их.

Спасибо большое!

2 ответов


когда вы изменяете службы WCF SOAP на REST, изменяется весь настрой отчетов об ошибках и обработки.

в SOAP ошибки являются частью вашего контракта. В REST они просто становятся кодами, которые вы выводите в коде ответа HTTP и описании.

вот фрагмент catch:

catch (Exception e)
{
    Trace.WriteLine(e.ToString());

    OutgoingWebResponseContext response = WebOperationContext.Current.OutgoingResponse;
    response.StatusCode = System.Net.HttpStatusCode.UnsupportedMediaType; // or anything you want
    response.StatusDescription = e.Message;
    return null; // I was returning a class
}

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


Это то, что я делал в прошлом

    public class MyServerBehavior : IServiceBehavior {

        public void AddBindingParameters(ServiceDescription serviceDescription,
             ServiceHostBase serviceHostBase, 
             Collection<ServiceEndpoint> endpoints, 
             BindingParameterCollection bindingParameters) {

        }

        public void ApplyDispatchBehavior(ServiceDescription serviceDescription,
                                          ServiceHostBase serviceHostBase) {

            foreach (ChannelDispatcher chDisp in serviceHostBase.ChannelDispatchers) {
                chDisp.IncludeExceptionDetailInFaults = true;
                if (chDisp.ErrorHandlers.Count > 0) {
                    // Remove the System.ServiceModel.Web errorHandler
                    chDisp.ErrorHandlers.Remove(chDisp.ErrorHandlers[0]);  
                }
                // Add new custom error handler
                chDisp.ErrorHandlers.Add(new MyErrorHandler());

            }

        }

        public void Validate(ServiceDescription serviceDescription, 
                             ServiceHostBase serviceHostBase) {
        }

    }

MyErrorHandler был моим классом, который реализовал IErrorHandler.