Descripción general: esta sección describe principalmente las excepciones y las excepciones simuladas que pueden ocurrir en las llamadas de servicio, y analiza cuándo y qué excepciones se pueden detectar, y cómo pasar excepciones de servicio al cliente de la manera correcta.
Al final del artículo, se proporciona la secuencia de captura para detectar correctamente las excepciones. Esta captura de excepciones es solo una introducción y algunas de ellas son funciones de la aplicación, por lo que el código y la escritura son relativamente simples. También presenta algunas técnicas para el manejo de excepciones en el lado del servidor.
1. Primero, creamos un servidor y un cliente de calculadora simples, de la siguiente manera:
Haga clic para expandir el código
//Servidor[ServiceContract]interfaz pública ICalc{[OperationContract][FaultContract(typeof(GreentingError))]string Div(int x, int y);}clase pública Calc: ServiceBase, ICalc {cadena pública Div(int x, int y ) ) {resultado de cadena = string.Empty; prueba {resultado = string.Format("resultado: {0}", x / y); catch (DivideByZeroException ex) {throw ex }devolver resultado; [ServiceContract] interfaz pública ICalc { [OperationContract] [FaultContract(typeof(GreentingError))] cadena Div(int x, int y } clase pública CalcClient: ClientBase<ICalc>, ICalc{ cadena pública Div(int x, int y) ) ) {return base.Channel.Div(x, y }});
Vale, admito que el código es bastante sencillo, pero me gustan las cosas sencillas.
2. Las cosas simples son buenas, y llamarlas es mucho más sencillo; llamémoslas.
intente { CalcClientcalcclient = new CalcClient(); resultado de cadena =calcclient.Div(10, 0); Console.WriteLine(resultado); Console.ReadKey() } catch (TimeoutExceptionex) {throw ex } catch (FaultException<GreentingError>; ex) {lanzar ex} capturar (FaultExceptionex) {lanzar ex; capturar (System.ServiceModel.CommunicationException ex) {lanzar ex} capturar (Exceptionex) {lanzar ex}
3. Cuando llamamos al método Div(int x, int y) del servicio y pasamos el valor 0 al logaritmo y, el servidor generará una excepción DivideByZeroException, como se esperaba. En este momento,
Esta excepción se detecta en la sección FaultException del cliente.
4. No hay problema, lanzaremos manualmente FaultException en el código del servidor.
catch (DivideByZeroException ex){FaultException excepción = nueva FaultException (ex.Message); lanzar excepción;}
En este momento, descubrí que FaultException detectó esta excepción.
5. Haz otra prueba.
Agregue este código al servicio: System.Threading.Thread.Sleep(70000) para hacer que el servicio expire.
Esta vez, TimeOutException finalmente detectó la excepción del servidor, por lo que tenemos que preguntarnos: ¿cuándo detectará FaultException<GreentingError> la excepción? La respuesta es que cuando el servidor arroja FaultException<GreentingError>, cite un pasaje en MSDN (parte verde):
Si el oyente recibe un error SOAP que no se espera ni se especifica en el contrato de operación, se generará un objeto FaultException. Se pueden enviar dos tipos de errores SOAP: declarados y no declarados. Un error SOAP declarado es aquel en el que una operación tiene el atributo System.ServiceModel.FaultContractAttribute que especifica un tipo de error SOAP personalizado. Los errores SOAP no declarados son errores que no están especificados en el contrato de la operación. El "error SOAP inesperado o no especificado" aquí se refiere a un tipo de error personalizado que no está incluido con FaultContractAttribute en la operación del servicio.
6. Entonces, ¿cuándo se detectará CommincationException?
MSDN dice: La aplicación maneja objetos CommunicationException que pueden generarse durante la comunicación
Bueno, para plantear esta excepción, hacemos lo siguiente. Primero cierre el objeto del canal actual en el servidor.
OperationContext.Current.Channel.Close();
Desafortunadamente, el cliente no detectó CommunicationException, ¡pero sí TimeOutException! Debido a que no se produjo ninguna excepción después de que se cerró el canal de servicio, no se devolvió ningún mensaje al cliente. Después de esperar un cierto período de tiempo, el cliente agotó el tiempo y salió.
Entonces especificamos un TimeSpan al cerrar el canal. Esto permite que la llamada regrese inmediatamente. Por supuesto, la devolución de la llamada también se puede completar a través de Channel.Abort.
OperationContext.Current.Channel.Close(nuevo TimeSpan(5000));
Al llamar al método Close de IContextChannel, especifique el tiempo que debe completarse la operación de envío antes del tiempo de espera, de modo que el mensaje pueda devolverse inmediatamente dentro del tiempo especificado sin tener que esperar a que se agote el tiempo de espera de la llamada de servicio; de lo contrario, el cliente definitivamente arrojará una excepción TimeOutException en lugar de una excepción CommunicationException.
7. Remedios
Al mismo tiempo, para tomar algunas medidas correctivas cuando ocurre una excepción en el servicio, creamos una nueva clase abstracta ServiceBase e hicimos que la clase de implementación del servicio Calc herede de ella, de modo que podamos obtener control sobre las diversas transiciones de estado de el servicio. La clase ServiceBase es la siguiente:
clase parcial abstracta pública ServiceBase {canal IContextChannel privado = nulo ServiceBase protegido() { canal = OperationContext.Current.Channel.Opening += new EventHandler(delegate(remitente del objeto, EventArgs e) {/* PARA HACER*/ }) ; canal.Abierto += new EventHandler(delegate(remitente del objeto, EventArgs e) {/* PARA HACER*/ }); }); canal.Cerrado += new EventHandler(delegate(remitente del objeto, EventArgs e) { Abortar(); }); canal.Faulted += new EventHandler(delegate(remitente del objeto, EventArgs e) { Abortar(); }) ; } void Open() {/* PARA HACER*/ } void Close() { /* PARA HACER*/} void Abort() { canal.Abort();
Como se puede ver en el código anterior, después de cerrar el canal de servicio, detenemos inmediatamente el servicio y dejamos que el mensaje regrese inmediatamente. En este momento, incluso si el servicio se cierra durante la operación sin especificar el tiempo de espera, la llamada. Todavía puedo regresar inmediatamente.
Esta vez el cliente finalmente detectó la CommunicationException, como se muestra en la siguiente figura:
¿Por qué sucede esto?
8. Echemos un vistazo a la jerarquía de herencia de CommunicationException, de la que podemos inspirarnos.
8.1. La primera es la jerarquía de herencia de FaultException<TDetail>.
8.2, nuevamente la jerarquía de herencia de TimeOutException.
9. Como se puede ver en la figura anterior, TimeOutException y CommunicationException heredan de la clase SystemException, mientras que FaultException hereda de CommunicationException y, finalmente, FaultException <TDetail> hereda de la clase FaultException.
10. Finalmente, llegamos a la conclusión de que el orden correcto para detectar excepciones en el cliente debería ser:
TimeOutException> FaultException<TDetail> > FaultException > CommunicationException > Excepción. Se recomienda encarecidamente que los desarrolladores lancen y detecten excepciones de tipo FaultException<TDetail>.
Autor: Lao Mi Fuente: http://www.cnblogs.com/viter/
Los derechos de autor de este artículo pertenecen al autor y Blog Park es bienvenido. Sin embargo, esta declaración debe conservarse sin el consentimiento del autor y se debe proporcionar un enlace al texto original en una posición obvia en la página del artículo. se reserva el derecho de exigir responsabilidad legal.