2010-12-16 12 views
8

Tengo un gran número de código heredado que ahora es un backend para un servicio WCF REST, que solía ser un backend WCF habitual antes, si eso fuera importante. Quiero implementar un mecanismo que atrape cualquier excepción en cualquier método y lo analice. Si resulta ser un error conocido, se procesará y se convertirá en un error de aspecto amistoso.Servicios de WCF REST: gestión de excepciones genéricas

Sé que puedo lanzar FaultException o WebProtocolException en lugar de las excepciones 'habituales', pero hay muchos lugares donde se lanzan excepciones en todo el código, y buscar todos ellos es una opción bastante dolorosa.

Intenté agregar una extensión de comportamiento de punto final que crea un nuevo comportamiento que anula el método WebHttpBehavior.AddServerErrorHandlers estándar y agrega mis controladores de errores (implementaciones IErrorHandler) a la colección de controladores de error del asignador de extremo. Dentro de los manejadores de errores analizo la excepción y creo (o no creo) un fallo basado en esta excepción.

Esperaba que este mecanismo devolviera datos personalizados para cualquier excepción conocida, pero estaba equivocado. El bueno de Microsoft ha implementado un maravilloso e inevitable WebHttpBehavior2, que agrega incondicionalmente un Microsoft.ServiceModel.Web.WebErrorHandler interno al final de la colección de manejadores de errores del asignador de punto final. Este manejador ignora todos los manejadores previamente ejecutados y reconoce solo un pequeño conjunto de excepciones, mientras que la mayoría se interpreta como "Error interno del servidor", y nada más.

La pregunta es si estoy en el camino correcto y hay una forma de deshabilitar este controlador en el mecanismo WCF REST, o introducirlo con una nueva excepción (por ejemplo, cuando se detecta cualquier excepción, primero es procesada por mi controladores y si lanzan/devuelven, por ejemplo, FaultException, esta nueva excepción se suministra al Microsoft.ServiceModel.Web.WebErrorHandler en lugar del original). Si todos mis experimentos con IErrorHandler y las extensiones de comportamiento no tienen valor, ¿cuál es una alternativa? De nuevo, realmente no quiero modificar la lógica de arrojar excepciones, quiero que un lugar capte las excepciones y las procese.

¡Muchas gracias!

Respuesta

7

Cuando cambia los servicios WCF SOAP a REST, cambia todo el modo de pensar de los informes y el manejo de errores.

En SOAP, las fallas son parte de su contrato. En REST, simplemente se convierten en códigos que se muestran en el código y la descripción de respuesta HTTP.

Aquí hay un fragmento de captura:

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 
} 

así que yo sugeriría a crear un código auxiliar que genera códigos de error relevantes para usted y poner en la respuesta.

+0

Tal captura debería agregarse a cada método de servicio, ¿verdad? ¿O hay una manera de escribirlo en alguna parte una sola vez para manejar todas las excepciones? Me gustó el enfoque basado en el comportamiento porque definía un controlador común para todas las excepciones, y no tenía que preocuparme por manejar y procesar excepciones para cada método. Lo mejor es que definí un procesador para todos los servicios en el punto final. No puedo lograr esto usando su enfoque, ¿verdad? –

+0

Establecer el 'StatusDescription' no tiene ningún efecto! La respuesta siempre tiene una descripción de estado genérica. ¿Hay alguna manera de arreglarlo? – Hemant

+0

Tiene.Puede verificarlo en el mensaje saliente del servidor que usa el violín, .... Pero lo que tiende a encontrar es que varios navegadores o implementaciones diferentes pueden ignorar la descripción y simplemente usar el código para mapear a un mensaje predefinido. Tuve ese problema con una aplicación de Android que estaba creando y terminé configurando la descripción y cambiando la firma del método para poder devolver una cadena. ¡Ay! ** Es por eso que nunca volvería a utilizar WCF REST. ** – Aliostad

2

Esto lo que hice en el pasado

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 fue mi clase que implementa IErrorHandler.

+0

Esto se ve muy similar a lo que hice. ¿Funcionó para el servicio REST, o solo para SOAP? Si funcionó para el servicio REST, ¿cómo configuró el servicio? Si solo para SOAP, entonces gracias, pero REST es una historia completamente diferente, hasta donde yo lo veo ahora. –

+1

@Michael Lo hice para los servicios REST. Estuve alojado por mí mismo y en realidad creé mi propio host de servicio derivado que configuró el comportamiento. Está todo basado en código, sin XML. –

+0

Alojado por mí mismo, ya veo ... Eso es lo que estaba pensando, pero lo consideraba demasiado complicado. ¡Gracias! –

Cuestiones relacionadas