Answered by:
Catching a Thrown Exception on the Server

Question
-
User1663286328 posted
Hi all,
Now that I've sorted out my issue with respect to throwing my exception
when (and only when) it needs to be thrown, I now have the issue of
catching the exception where I want it to be caught.
The exception is thrown on the server, but being caught on the client.
(On top of that, it's coming back as a CommunicationException, and
not my custom exception handler, but that probably wouldn't happen if
I could catch the exception on the server to begin with.)
Can anyone clue me in on how to catch the exception on the server-side?
... or perhaps I should ask how to throw it so that the server will
catch it?
Thanks!class Server_Program { public static void Main() { ServiceHost serviceHost = new ServiceHost(typeof(VS_Service)); try { serviceHost.Open(); foreach (Uri baseAddress in serviceHost.BaseAddresses) VSM_Log.mssg.Info (" *** Service started at {0}", baseAddress); VSM_Log.mssg.Info (""); VSM_Log.mssg.Info ("Press <ENTER> to terminate the service"); VSM_Log.mssg.Info (""); Console.ReadLine(); serviceHost.Close(); } catch (not_implemented_exception NI_xcpt) { NI_xcpt.add_name ("MAIN <1> (local service)"); NI_xcpt.log_error_messages (NI_xcpt); } catch (CommunicationException e) { VSM_Log.mssg.Info (e.Message); } catch (TimeoutException e) { VSM_Log.mssg.Info (e.Message); } if (serviceHost.State != CommunicationState.Closed) { VSM_Log.mssg.Info ("Aborting the service..."); serviceHost.Abort(); } } }
Tuesday, March 19, 2013 11:36 PM
Answers
-
User1663286328 posted
Hi sukumarraju,
I'm sorry that you put in the time and effort to write that response,
as it does nothing to address my issue. In the example that you've given,
the exception is caught on the client - not on the server - as I'm in the
process of doing. I've got plenty of examples for catching exceptions
on the client, but scarce few for catching them on the server - before
they are sent on to the client. This is a bit of a surprise, as there could be
a lot of sensitive information that could make it to the general public
(or, even worse, a hacker who deliberately trips an exception to get back
information that could lead to bad things happening).
In debugging, the more information that a developer/administrator has
in dealing with an issue, the easier it will be to fit it. The common-sense
thing to do in that regard is to catch detailed exceptions on the server,
then send a less-detailed message on to the client.
The good news is that I seem to have found the key elements in getting
what I want: the ability to catch exceptions on the server. I found a post
that has given me the clue that I need to get around the cast exception
issue that I had before. It seems that, in accessing the collection returned
in the call to serviceHostBase.ChannelDispatchers, I need to use, as the
return type, ChannelDispatcherBase (instead of ChannelDispatcher),
then use an "as" cast to convert it to ChannelDispatcher, then it's
onward to using it to access the exception handler (unless the cast
evaluates to null, then it's onward to the next element within the list).
public sealed class ErrorHandlingBehaviorAttribute : Attribute, IServiceBehavior { public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase) { foreach (ChannelDispatcherBase chanDispBase in serviceHostBase.ChannelDispatchers) { ChannelDispatcher channelDispatcher = chanDispBase as ChannelDispatcher; if (channelDispatcher == null) continue; channelDispatcher.ErrorHandlers.Add(new ErrorHandler(...)); } } //Other interface methods omitted for brevity } //http://www.codeproject.com/Articles/26320/WCF-Error-Handling-and-Fault-Conversion
It looks like I've found the solution to my problem, but if anyone else has
a better idea, I'd appreciate the input.
Thanks sukumarraju for the effort, and to everyone else who has been reading- Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
Thursday, March 21, 2013 2:35 PM
All replies
-
User-629220960 posted
Hi ,
If you have made application in three tier architecture you can handle the exception without rendering on client . Handel the exception in the Model and Controller phaes or in datalayer and BusinessLayer .and create a error log with the help of System.IO namespace.
Wednesday, March 20, 2013 12:06 AM -
User1663286328 posted
Hi Vivek,
There are only two tiers: client and server.
I want to throw and catch certain exception(s) on the server,
and not have it sent to the client.
BTW: This is self-hosted - no IIS.Thanks for the response!
Wednesday, March 20, 2013 10:36 AM -
User220959680 posted
Exceptions are called WCF faults, here is the list of best practices.
http://blogs.msdn.com/b/pedram/archive/2008/01/25/wcf-error-handling-and-some-best-practices.aspx
Wednesday, March 20, 2013 10:52 AM -
User1663286328 posted
Hi sukumarraju,
I've been looking through the referenced Blog:
---------------------------------------------------------
An interesting and useful WCF extensibility point for error handling:
WCF is a very extensible framework. You can explicitly control the
behaviour of your application when an exception is thrown.
You can
- Decide to send a fault to the client or not,
- Replace an exception with a fault,
- Replace a fault with another fault,
- Perform logging,
- Perform other custom activities
---------------------------------------------------------
"Decide to send a fault to the client or not"... or not.
I'm still trying to figure out how to do that.
I've come across a post that mentions the IServiceBehavior interface:
---------------------------------------------------------
http://stackoverflow.com/questions/3308794/wcf-server-side-error-handling-best-practice
---------------------------------------------------------
Have a look at IErrorHandler interface
It allows an implementer to control the fault message returned
to the caller and optionally perform custom error processing
such as logging
You can implement your service behavior (see IServiceBehavior
interface) and add your handler to ChannelDispatcher error
handlers.
See WCF Exception Handling with IErrorHandler for more details.
---------------------------------------------------------
---------------------------------------------------------
I tried this, and, when I attempted to iterate through the
"ChannelDispatcherCollection", an invalid cast exception was thrown.
try { serviceHost.Open(); dispatcher_info (serviceHost); //[ EXE1: dispatcher_info <1>] . . . private static void dispatcher_info (ServiceHost p_serviceHost) { IChannelListener icl = p_serviceHost.ChannelDispatchers[0].Listener; ChannelDispatcher dispatcher = new ChannelDispatcher(icl); VSM_Log.mssg.Info ("servicehost has {0} ChannelDispatchers", p_serviceHost.ChannelDispatchers.Count); ChannelDispatcherCollection dispatchers = p_serviceHost.ChannelDispatchers; foreach (ChannelDispatcher disp in dispatchers) { VSM_Log.mssg.Info ("Binding name: " + disp.BindingName); } }
System.InvalidCastException was unhandled Message=Unable to cast object of type 'System.ServiceModel.Discovery.OfflineAnnouncementChannelDispatcher' to type 'System.ServiceModel.Dispatcher.ChannelDispatcher'. Source=service StackTrace: ...
The client is using discovery to find the endpoint.
Perhaps that has something to do with it?THANKS for the response!
Wednesday, March 20, 2013 1:28 PM -
User220959680 posted
https://msevents.microsoft.com/CUI/EventDetail.aspx?culture=en-US&EventID=1032344323
Just register at above to download/view a detailed video tutorial, all can download all wcf videos .
Wednesday, March 20, 2013 2:45 PM -
User1663286328 posted
Hi sukumarraju,I watched the webcast and it was very informative about sending faults
to the client - but that is not what I want to know.It was only at the end of the webcast that IErrorHandler was mentioned,
and the means by which to attach it to the service is to be revealed in the
next webcast - on extensibility.I've downloaded the code, and I can see that I'd be spending several hours
going through it, which is something that I'd rather not do at the present.
(A lot of it incorporates things that are not relevant to my current situation,
which is a very simple self-hosted client-server model with duplex operations.)All I want to know is how to go about grabbing on to the service thread being
executed on a ServiceHost, and catching whatever exceptions that might be
thrown on it before it goes back to the client. Perhaps it's a product of my own
naivete that it isn't as simple as I thought it should be.I'll keep searching for a suitable answer, but I'm still hoping that someone will
shine a ray of sunshine upon me that will enlighten me to a viable solution ...THANKS for the response and the clue on the webcast.
Wednesday, March 20, 2013 4:57 PM -
User220959680 posted
Exceptions can not cross the service boundary.
WCF automaticaly translates unhandled exceptions into SOAP faults. For security reasons, only a generic message is returned to client.In order to include the exception details in faults
- Enable with ServiceBehavior (shown below) or the ServiceDebug behavior, this is useful for debugging purpose, not recommended in production.
<configuration> <system.serviceModel> <behaviors> <behavior name="Default"> <serviceDebug includeExceptionDetailInFaults="true"/> <behaviors> </system.serviceModel>
The FaultException class represents an explicity soap fault.
- Thorw in service operation to return a soap fault.
- WCF clients can catch FaultException to handle the error
- It is feasible to throw/catch typed faults.
Service//Service operation public void GetProduct(int id) { try{ /// } catch(Exception ex) { throw new FaultException("<Fault reason here>") } }
Client side
Client needs to be prepared for two main exception types.- Communication excepiton - these are various runtime communication exceptions and FaultExceptions thrown by the operations (methods above).
- TimeoutException:- send timeout limit exceeded or thrown by underlying transprot channel.
//Client handling exception //create an instance service proxy productServiceClient client = new productServiceClient(); //Invoke service method try { client.GetProduct(2); client.Close(); } //Catch FaultException Catch(FaultException fe) { Console.WriteLine("{0}",fe.GetType()); Client.Abort(); } //Communication exception catch(CommunicationException ce) { Console.WriteLine("{0}",ce.GetType()); Client.Abort(); } //Timeout exception catch(TimeoutException te) { Console.WriteLine("{0}",te.GetType()); Client.Abort(); } }
Please refer http://msdn.microsoft.com/en-us/library/ms576199.aspx
Wednesday, March 20, 2013 7:36 PM -
User1663286328 posted
Hi sukumarraju,
I'm sorry that you put in the time and effort to write that response,
as it does nothing to address my issue. In the example that you've given,
the exception is caught on the client - not on the server - as I'm in the
process of doing. I've got plenty of examples for catching exceptions
on the client, but scarce few for catching them on the server - before
they are sent on to the client. This is a bit of a surprise, as there could be
a lot of sensitive information that could make it to the general public
(or, even worse, a hacker who deliberately trips an exception to get back
information that could lead to bad things happening).
In debugging, the more information that a developer/administrator has
in dealing with an issue, the easier it will be to fit it. The common-sense
thing to do in that regard is to catch detailed exceptions on the server,
then send a less-detailed message on to the client.
The good news is that I seem to have found the key elements in getting
what I want: the ability to catch exceptions on the server. I found a post
that has given me the clue that I need to get around the cast exception
issue that I had before. It seems that, in accessing the collection returned
in the call to serviceHostBase.ChannelDispatchers, I need to use, as the
return type, ChannelDispatcherBase (instead of ChannelDispatcher),
then use an "as" cast to convert it to ChannelDispatcher, then it's
onward to using it to access the exception handler (unless the cast
evaluates to null, then it's onward to the next element within the list).
public sealed class ErrorHandlingBehaviorAttribute : Attribute, IServiceBehavior { public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase) { foreach (ChannelDispatcherBase chanDispBase in serviceHostBase.ChannelDispatchers) { ChannelDispatcher channelDispatcher = chanDispBase as ChannelDispatcher; if (channelDispatcher == null) continue; channelDispatcher.ErrorHandlers.Add(new ErrorHandler(...)); } } //Other interface methods omitted for brevity } //http://www.codeproject.com/Articles/26320/WCF-Error-Handling-and-Fault-Conversion
It looks like I've found the solution to my problem, but if anyone else has
a better idea, I'd appreciate the input.
Thanks sukumarraju for the effort, and to everyone else who has been reading- Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
Thursday, March 21, 2013 2:35 PM -
User220959680 posted
In the example that you've given,
the exception is caught on the client - not on the server -In my previous response exception is caught in Service layer and you are suggested to comment the config behavior in production. Refer the below.
<div>Service</div>
//Service operation
public void GetProduct(int id)
{
try{
///
}
catch(Exception ex)
{
throw new FaultException("<Fault reason here>")
}
}Enable with ServiceBehavior (shown below) or the ServiceDebug behavior, this is useful for debugging purpose, not recommended in production.
Friday, March 22, 2013 8:00 AM -
User1663286328 posted
Hi Sukumarraju,
What you're suggesting is that I should put the code in every service method
inside try/catch blocks. I thought of doing that myself, but it I'm not sure that
it would catch all exceptions thrown.
Perhaps someone else can comment on this.
I don't see how this is a better approach than attaching an error handler
to the channelDispatcher - and this is the approach recommended by
Bustamante (who has a nice example of it in the extensibility part of her
example code).
I've also come accross another approach that you might be interested in.
It involves the Exception Handling Application Block (a part of Enterprise Library):
http://msdn.microsoft.com/en-us/library/ff664698%28v=pandp.50%29.aspx
ltimately, this might be the best way to go, but for now, I'll stick with the
channelDispatcher error handler.
Thanks for the responses.Saturday, March 23, 2013 12:29 AM -
User220959680 posted
wASP
channelDispatcherThanks for sharing ChannelDispatcher.ErrorHandlers property.
Note that ErrorHandler class, which is called in ErrorHandlingBehaviorAttribute class is implementing FaultException()as shown below.
//ExceptionFault in ErrorHandler class if (faultDetail != null) { Type faultExceptionType = typeof(FaultException<>).MakeGenericType(faultDetail.GetType()); FaultException faultException = (FaultException)Activator.CreateInstance( faultExceptionType, faultDetail, error.Message); MessageFault faultMessage = faultException.CreateMessageFault(); fault = Message.CreateMessage(version, faultMessage, faultException.Action); } //creating new instance of ErrorHandler in ErrorHandlingBehaviorAttribute class if (channelDispatcher == null) continue; channelDispatcher.ErrorHandlers.Add(new ErrorHandler(...));
what ever the exceptions that are caught using FaultException in the example I provided earlier also does the same in the article/example utilising ChannelDispatcher, the only difference is rather than repeating FaultException in each service method ChannelDispatcher.ErrorHandlers implementation i.e., behavior can be added as Attribute to the service class as below.
[ErrorHandlingBehavior] class MyService : IMyService
wASP
I've also come accross another approach that you might be interested in.
It involves the Exception Handling Application Block (a part of Enterprise Library):Enterprise Lib Exception Handling app block provides consistent error handling across the application using Exception policy. It is required to specify what type of exceptions i.e., FileNotFoundException etc. in the policy and call the policy name in exception handling (Catch) block. It is feasible to specify number of policies and utilise as required. Utilising Application block is simple and all it required is 'using simple configuration tool (more in my articles below).
Service related exceptions can be wrapped in a Exception policy and utilised in service layer. Client side exceptions can be wrapped in a policy and reused across the application.
Refer below referred two articles from my blog.
wASP
Perhaps someone else can comment on this.Please keep this thread as un-resolved by marking your response as Not an Answer, such a way community member can provide further help.
Sunday, March 24, 2013 7:36 PM