2010-12-16 4 views
8

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

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

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

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

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

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

ответ

7

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

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

Вот улов сниппет:

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 
} 

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

+0

Такой улов должен быть добавлен к каждому методу обслуживания, не так ли? Или есть способ написать его где-то один раз, чтобы справиться со всеми исключениями? Мне понравился подход, основанный на поведении, потому что он определил общий обработчик для всех исключений, и мне не пришлось беспокоиться о обработке и обработке исключений для каждого отдельного метода. Лучше всего, что я определил один процессор для всех сервисов в конечной точке. Я не могу добиться этого, используя ваш подход, не так ли? – 2010-12-17 08:30:07

+0

Настройка `StatusDescription` не влияет! Ответ всегда имеет общее описание состояния. Есть все равно, чтобы исправить это? – Hemant 2011-01-13 07:19:30

2

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

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.

Смежные вопросы