IErrorHandler interface is confusing me - wcf

I have created a class that implements IErrorHandler and IServiceBehavior. I add the behavior to my ServiceHost and run it.
The reason I got around to trying to learn about IErrorHandler is because the frustration I was having in having to wrap all of my service code that interfaces with callback channels in try catch statements, and wondered if there was a global way to catch the exceptions.
Well from what I read here on StackOverflow, I saw that it is indeed the thing I want.
In execution however, it's confusing me greatly. If I have a contract method that does the following...
Dictionary<IChatCallback, string> userChannels = new Dictionary<IChatCallback, string>();
public void SendMessage(string message)
{
IChatCallback callback = OperationContext.Current.GetCallbackChannel<IChatCallback>();
string senderName = userChannels[callback];
SendMessageToAllUsers(message, senderName);
}
public void SendMessageToAllUsers(string message, string sender)
{
foreach (var userChannel in userChannels.Keys)
{
userChannel.ReceiveMessage(new ChatMessage(message, sender));
}
}
If a client is on my server and he drops off the face of the earth and the channel faults, it seems to take a while before my server realizes that the channel is faulted. Even if am subscribed to the events of the ICommunicationObject, it seems to take a while before the server realizes the channel is faulted. For example, if someone is sending messages and someone disconnects, and a message is being propagated at the same time.
Now, I have another method that essentially pings clients at a regular interval to figure out if they're still there or not, so I can remove them from the userChannel dictionary.
How exactly is IErrorHandler supposed to help me here? It seems that it's not exactly helping my service from crashing even if it catches the error. Because my service cannot ping my clients at a super rapid pace, sometimes a message seems to come in immediately(I was testing this) after a previous message that threw an exception. It seemed to have handled the first one, but the second one threw another exception that wasn't caught, and my service crashed, because the server was trying to communicate with a faulted channel. Now, my service DOES clean up those faulted channels, but it does so periodically.
I was hoping that by implementing IErrorHandler I could avoid having to wrap all of my methods in try{}catch{} blocks... but it seems like I still have to, to check if I'm communicating with a faulted channel?
Or maybe I'm just going about using IErrorHandler improperly and thinking it should be doing things it's not supposed to do. Should I maybe have my service implement it, and inject itself into the Servicehost as the IServiceBehavior? And then in my HandleError() method remove the channel from my list of clients? That seems kind of messy, because I'm putting that WCF plumbing stuff in my service class, but that would be the only way I can think of to have the exception code itself remove the channel from the list of callbacks.
I'm trying to do a lot of reading because I'm new to it, but it seems like the world of Error Handling in WCF is daunting.
Even if I try to remove the channel so it's not called on services via subscribing to the Faulted event, it doesn't work fast enough and still throws exception that the server cannot seem to recover from even with IErrorHandler.
For example, when the user first connects, I subscribe to the event.
IChatCallback callback = OperationContext.Current.GetCallbackChannel<IChatCallback>();
ICommunicationObject callbackComm = (ICommunicationObject) callback;
callbackComm.Faulted += (sender, e) =>
{
lock (lockObject)
{
string name = userChannels[callback];
userChannels.Remove(callback);
NotifyOfUserDisconnect(name);
}
};
Do I just need to go into all my methods and check if the channel is closed or faulted, and wrapping everything in a try/catch block to remove the reference and notify clients?

Related

How to hide a WCF Faulted state message box on an expected exception?

I have an application that supports multiple types of devices. One of the devices supported requires a WCF service to connect to it.
I have a thread that continuously checks for the service, and if it is found then it can proceed in calling necessary code to try to connect to the device... this all works fine if the service is running.
However, for the case where the service is not running, or not available (a user may not even use that device), a EndpointNotFoundException is getting thrown. I expect this exception to happen and I am catching it in a try/catch. However, I still get an error message pop up that says "The communication object, System.ServiceModel.Channels.ServiceChannel, cannot be used for communication because it is in the Faulted state". How can I hide/disable this error box?
protected override void OnTimerCallback(object state)
{
ServiceClient proxy = new ServiceClient("NetNamedPipeBinding_IService");
try
{
proxy.Open();
// do some stuff here...
proxy.Close();
}
catch (EndpointNotFoundException)
{
// just ignore, expected if service isn't running
}
catch (CommunicationObjectFaultedException)
{
// just ignore, expected if service isn't running
}
}
I'm using .NET 3.5 by the way.
Have you googled this or searched SO?
I don't think a client channel in a faulted state will throw CommunicationObjectFaultedException when you try to use the proxy. You would need to check if the client is in the faulted state.
Check the accepted answer here

NHibernate + WCF + Windows Service and WcfOperationSessionContext class

I have a Windows Service Application
in which i create WCF services in it.
One of the services is data
services: add, delete,
read , updatte data via
WCF.
WCF use NHibernate for data manipulation
So my guestions are:
Any advice (best practice) for session management for Hibernate using with WCF?
Anybody knows anything about
WcfOperationSessionContext (hibernate 3.0) class?
how to use it with WCF?
Well to make it concrete :
Suppose that i have WCF Service called DataServices
class WCFDataService .....
{
void SaveMyEntity(MyEntity entity)
{
.....................?? // How to do? Best Way
// Should i take one session and use it all times
// Should i take session and dipsose when operation finished then get
//new session for new operations?
// If many clients call my WCF service function at the same time?
// what may go wrong?
// etc....
}
}
And I need a NHibernateServiceProvider class
class NHibernateServiceProvider ....
{
// How to get Session ?? Best way
ISession GetCurrentSession(){.... }
DisposeSession(){ ....}
}
Best Wishes
PS: I have read similiar entries here and other web pages. But can not see "concrete" answers.
The WcfOperationSessionContext, similar to ThreadStaticSessionContext and WebRequestSessionContext is an implementation for a session context. The session context is used to bind (associate) a ISession instance to a particular context.
The session in the current context can be retrieved by calling ISessionFactory.GetCurrentSession().
You can find more information about session context here.
The WcfOperationSessionContext represents a context that spans for the entire duration of a WCF operation. You still need to handle the binding of the session in the begining of the operation and the unbinding/commiting/disposal of the session at the end of the operation.
To get access to the begin/end actions in the wcf pipeline you need to implement a IDispatchMessageInspector. You can see a sample here.
Also regarding WCF integration: if you use ThreadStatic session context it will appear to work on development, but you will hit the wall in production when various components (ex: authorization, authentication ) from the wcf pipeline are executed on different threads.
As for best practices you almost nailed it: Use WcfOperationSessionContext to store the current session and the IDispatchMessageInspector to begin/complete your unit of work.
EDIT - to address the details you added:
If you configured WcfOperationSessionContext and do the binding/unbinding as i explained above, all you have to do to is inject the ISessionFactory into your service and just use factory.GetCurrentSession(). I'll post a sample prj if time permits.
Here is the sample project
The model we use for managing NHibernate sessions with WCF is as follows:
1) We have our own ServiceHost class that inherits from System.ServiceModel.ServiceHost which also implements ICallContextInitializer. We add the service host instance to each of the operations in our service as follows:
protected override void InitializeRuntime()
{
base.InitializeRuntime();
foreach (ChannelDispatcher cd in this.ChannelDispatchers)
{
foreach (EndpointDispatcher ed in cd.Endpoints)
{
foreach (DispatchOperation op in ed.DispatchRuntime.Operations)
{
op.CallContextInitializers.Add(this);
}
}
}
}
public void AfterInvoke(object correlationState)
{
// We don't do anything after the invoke
}
public object BeforeInvoke(InstanceContext instanceContext, IClientChannel channel, Message message)
{
OperationContext.Current.Extensions.Add(new SessionOperationContext());
return null;
}
The BeforeInvoke simply makes sure that the OperationContext for each WCF call has it's own session. We have found problems with IDispatchMessageInspector where the session is not available during response serialisation - a problem if you use lazy loading.
2) Our SessionOperationContext will then be called to attach itself and we use the OperationCompleted event to remove ourselves. This way we can be sure the session will be available for response serialisation.
public class SessionOperationContext : IExtension<OperationContext>
{
public ISession Session { get; private set; }
public static SessionOperationContext Current
{
get
{
OperationContext oc = OperationContext.Current;
if (oc == null) throw new InvalidOperationException("Must be in an operation context.");
return oc.Extensions.Find<SessionOperationContext>();
}
}
public void Attach(OperationContext owner)
{
// Create the session and do anything else you required
this.Session = ... // Whatever instantiation method you use
// Hook into the OperationCompleted event which will be raised
// after the operation has completed and the response serialised.
owner.OperationCompleted += new EventHandler(OperationCompleted);
}
void OperationCompleted(object sender, EventArgs e)
{
// Tell WCF this extension is done
((OperationContext)sender).Extensions.Remove(this);
}
public void Detach(OperationContext owner)
{
// Close our session, do any cleanup, even auto commit
// transactions if required.
this.Session.Dispose();
this.Session = null;
}
}
We've used the above pattern successfully in high-load applications and it seems to work well.
In summary this is similar to what the new WcfOperationSessionContext does (it wasn't around when we figured out the pattern above;-)) but also overcomes issues surrounding lazy loading.
Regarding the additional questions asked: If you use the model outlined above you would simply do the following:
void SaveMyEntity(MyEntity entity)
{
SessionOperationContext.Current.Session.Save(entity);
}
You are guaranteed that the session is always there and that it will be disposed once the WCF operation is completed. You can use transactions if required in the normal way.
Here is a post describing, in detail, all the steps for registering and using the WcfOperationSessionContext. It also includes instructions for using it with the agatha-rrsl project.
Ok, after few days of reading internet posts etc. all approaches shown in the internets seems to be wrong. When we are using UnitOfWork pattern with NH 3^ with nhibernate transaction this all aprochaes are producing exceptions. To test it and proof that we need to create test enviroment with MSMQ transaction queue, special interface with OneWay operation contract with transaction required set on it. This approach should works like this:
1. We put transactionally message in queue.
2. Service is getting transactionally messege from queue.
3. Everything works queue is empty.
In some cases not so obious with internet approaches this does not work properly. So here are expamples which we tested that are wrong and why:
Fabio Maulo approach: Use ICallContextInitializer - open NH session/transaction on BeforeCall, after that WCF is executing service method, on AfterCall in context initializer we call session.Flush + transaction.commit. Automaticly session will be saved when transaction scope will commit operation. In situation when on calling transaction.Complete exception will be thrown WCF service will shutdown! Question can be ok, so take transaction.Complete in try/catch clausule - great! - NO wrong! Then transaction scope will commit transaction and message will be taken from queue but data will not be saved !
Another approach is to use IDispatchMessageInspector - yesterday I thought this is best approach. Here we need to open session/transaction in method AfterReceiveRequest, after WCF invoke service operation on message dispatcher inspector BeforeSendReply is called. In this method we have info about [reply] which in OneWay operation is null, but filled with fault information if it occured on invoking service method. Great I thought - this is this ! but NOT! Problem is that at this point in WCF processing pipe we have no transaction ! So if transaction.Complete throw error or session.Flush will throw it we will have not data saved in database and message will not come back to queue what is wrong.
What is the solution?
IOperationInvoker and only this!
You need to implement this interface as a decorator pattern on default invoker. In method Invoke before call we are openning session/transaction open then we call invoke default invoker and after that call transaction.complete in finally clausule we call session.flush. What types of problem this solves:
1. We have transaction scope on this level so when complete throws exception message will go back to queue and WCF will not shutdown.
2. When invocation will throw exception transaction.complete will not be called what will not change database state
I hope this will clear everyones missinformation.
In some free time I will try to write some example.

Calling Abort on faulted WCF channel causes server side error to be logged

When a FaultException is returned from my WCF service, I need to Abort the channel instead of Closing it. Both my client and service work fine with this approach but after implementing IErrorHandler on the service and logging any exception, I can see that calling Abort on the client causes the service to log:
System.ServiceModel.CommunicationException: The socket connection was aborted...
I do not want to pollute my service logs with this information and only want to log service related errors. I know I can obviously stop logging any CommunicationExceptions but my service is also a WCF client for other services and CommunicationExceptions raised by these services should be logged.
How can I stop it doing this?
As nobody else has answered the question (Tomas's answer was not relevant), I asked a few experts in the field. Unfortunately, there is no nice way of stopping this and the best that they could come up with was to add logic in IErrorHandler to not log CommunicationExcepions with a message starting with 'The socket connection was aborted'. Not very elegant, but it does work.
The problem is that you get an exception that covers your underlying exception if you get an exception when calling dispose wich is possible. I wrote a wrapper to deal with scenarios like this, you can read about it on my blog: http://blog.tomasjansson.com/2010/12/disposible-wcf-client-wrapper/
The idea is that you have a wrapper around your channel that deals with the scenario if the dispose method throws an exception.
A small example of how you should use my wrapper:
public class ClientWrapperUsage : IYourInternalInterface
{
public IList<SomeEntity> GetEntitiesForUser(int userId)
{
using(var clientWrapper = new ServiceClientWrapper<ServiceType>())
{
var response = clientWrapper.Channel.GetEntitiesForUser();
var entities = response.YourListOfEntities.TranslateToInternal();
return entities;
}
}
}
Here I have assumed that it existing an extension method for a list that contains the entity that is returned by the service, then you use that method to translate it to internal entities. This is 100 % testable, at least I think :). Just moch the interface IYourInternalInterface everywhere you wan't to fake the service.

Best Practice for WCF proxy lifetime - or how often to close a WCF proxy?

I've been working on a WPF application that uses WCF to access the server side logic & database.
I started with a single WCF client proxy object that I was using repeatedly to call methods on the server. After using the proxy for a while, the server would eventually throw an exception:
System.ServiceModel.EndpointNotFoundException: There was no endpoint listening at http://.../Service/BillingService.svc that could accept the message. This is often caused by an incorrect address or SOAP action. See InnerException, if present, for more details. ---> System.Net.WebException: Unable to connect to the remote server ---> System.Net.Sockets.SocketException: An operation on a socket could not be performed because the system lacked sufficient buffer space or because a queue was full.
I think this is because every service call was opening a new socket from the proxy to the server and never closing them. Eventually the server was flooded and began refusing requests.
After a brief bit of searching, I determined that I need to Close() the proxy periodically. The samples I found are degenerately small. This one provided some helpful hints, but doesn't really answer the question. I've also seen recommendations to avoid the using() pattern (and apply try/catch/finally instead) because the proxy's Dispose method may throw an exception (yuck).
It seems like the recommended pattern is shaping up like this:
[TestClass]
public class WCFClientUnitTest
{
BillingServiceClient _service;
[TestMethod]
public void TestGetAddressModel()
{
List<CustomerModel> customers = null;
try
{
_service = new BillingServiceClient();
customers = _service.GetCustomers().ToList();
}
catch
{
_service.Abort();
_service = null;
throw;
}
finally
{
if ((_service != null) &&
(_service.State == System.ServiceModel.CommunicationState.Opened))
_service.Close();
_service = null;
}
if (customers != null)
foreach (CustomerModel customer in customers)
{
try
{
_service = new BillingServiceClient();
AddressModel address = (AddressModel)_service.GetAddressModel(customer.CustomerID);
Assert.IsNotNull(address, "GetAddressModel returned null");
}
catch
{
_service.Abort();
_service = null;
throw;
}
finally
{
if ((_service != null) &&
(_service.State == System.ServiceModel.CommunicationState.Opened))
_service.Close();
_service = null;
}
}
}
So my question still revolves around how long should I keep a client proxy alive? Should I open/close it for every service request? That seems excessive to me. Won't I incur a significant performance hit?
What I really want to do is create & open a channel and make brief burst of repeated, short, sequential service calls across the channel. Then nicely close the channel.
As a side note, while I haven't implemented it yet, I will soon be adding a security model to the service (both SSL & ACL) to restrict who can call the service methods. One of the answers to this post mentions that renegotiating the authentication & security context makes reopening the channel for every service call wasteful, but simply recommends to avoid constructing a security context.
EDIT 11/3/2010: This seems important, so I am adding it to the question...
In response to Andrew Shepherd's comment/suggestion, I re-ran my unit test with my TrendMicro AntiVirus shutdown while monitoring the output of netstat -b. Netstat was able to record a significant growth of open ports that were owned by WebDev.WebServer40.exe. The vast majority of the ports were in TIME_WAIT state. Microsoft says that ports may linger in NET_WAIT after the client closes the connection...
NOTE: It is normal to have a socket in
the TIME_WAIT state for a long period
of time. The time is specified in
RFC793 as twice the Maximum Segment
Lifetime (MSL). MSL is specified to be
2 minutes. So, a socket could be in a
TIME_WAIT state for as long as 4
minutes. Some systems implement
different values (less than 2 minutes)
for the MSL.
This leads me to believe that if every service call opens a new socket on the server, and because I am calling the service in a tight loop, I could easily flood the server, causing it to run out of available sockets and in turn generate the exception I noted above.
Therefore, I need to pursue one of two paths:
1) attempt to batch service calls so that they reuse the server side socket
2) change my service contract so that I can return larger chunks of data with fewer calls.
The first choice seems better to me, and I am going to continue to pursue it. I'll post back what I discover and welcome further comments, questions and answers.
(Posting a completely different second answer)
If we are talking about "best practice", the real best practice with WCF is to have "coarse-grained methods". If a client is calling a method numerous times in a loop, then the entire business logic should be moved to the service itself.
For example.
[DataContract]
class CustomerAndAddress
{
[DataMember]
CustomerModel Customer;
[DataMember]
AddressModel Address;
}
[ServiceContract]
class BillingService
{
[OperationContract]
CustomerAndAddress[] GetAllCustomersAndAddresses();
}
or, more likely in the real world:
[ServiceContract]
class BillingService
{
[OperationContract]
CustomerReportData FetchCustomerReportInfo(CustomerReportParameters parameterSet);
}
Having said that, I'm still interested to see if you can pull off what you are trying.
It seems like there are several things at play here.
First the unit test I ran and monitored with netstat –b pointed out that Cassini (WebDev.WebServer40.exe) was the owner of the ports that were accumulating in the TIME_WAIT state. As the referenced MSFT kb article notes, it is normal for ports to linger after the FIN handshake while the application waits for any slow packets on the network to be delivered and the message queue to drain. The default configuration of 2 minutes explains why I saw the ports malingering after my unit test completed. While it is possible to change the MSL via registry setting, it isn’t recommended.
But, the important point that I almost overlooked is that the service was running under Cassini. When I switch my server endpoint to run under IIS7, I don’t experience any port growth at all! I can’t explain whether that means the client is reusing the ports or whether IIS7 is just better than Cassini at cleaning up the ports after they are finished.
Now, that doesn’t totally answer my question regarding how often should I close the WCF proxy. It just means I don’t have to close the proxy frequently.
I can see there still being a resource tradeoff to keeping the proxy open for long periods of time.
If you have many (i.e. thousands) of clients accessing your WCF service, it may make sense to release the server resources in between calls, or small batches of calls. In which case, be sure to use the try/catch/finally mechanism and not using() because even though the service proxy implements IDisposable, the close() method can throw an exception if the service is in a faulted state.
On the other hand (as in my particular case), if you only expect to have a few clients accessing your WCF service, you don’t need the added complexity of frequently and explicitly opening and closing the service proxy. Therefore, I intend to open the proxy once when my application launches, and leave it open until the application completes. I intend to implement a service invoke helper method (similar to: Renewing a WCF client when SCT has expired? ) that will recycle the connection, just in case it ever goes into a faulted state. Then, I don’t have to worry about managing the proxy lifetime.
Please let me know if think I am misreading my test results, or if you have a better solution.
I wrote (well, found and modified) a wrapper to help with properly disposing the service. Sorry about the VB. It has some extra things in it, like a MessageViewerInspector so I can intercept the XML that flies in and out of the service. Just ignore it for now.
EDIT: I know this doesn't really answer your question of how to maintain bursts of requests, but it would certainly make using the service a little cleaner, code-wise.
Imports System.ServiceModel
Namespace WCF
''' <summary>
''' This helper fixes an issue with WCF services where an exception gets thrown
''' during the Dispose() call of the client, so it doesn't actually get disposed.
''' </summary>
''' <typeparam name="TProxy"></typeparam>
''' <typeparam name="TChannel"></typeparam>
''' <remarks></remarks>
Public Class ServiceProxyHelper(Of TProxy As {ClientBase(Of TChannel), New}, TChannel As Class)
Implements IDisposable
Private _proxy As TProxy
Private _inspector As MessageViewerInspector
Public ReadOnly Property ServiceProxy() As TProxy
Get
If Not _proxy Is Nothing Then
Return _proxy
Else
Throw New ObjectDisposedException("ServiceProxyHelper")
End If
End Get
End Property
Public ReadOnly Property Inspector() As MessageViewerInspector
Get
If _inspector Is Nothing Then
_inspector = New MessageViewerInspector()
End If
Return _inspector
End Get
End Property
Public Sub New()
_proxy = New TProxy()
_proxy.Endpoint.Behaviors.Add(Me.Inspector)
End Sub
Public Sub New(ByVal endpointAddress As String)
Me.New()
If Not Me._proxy Is Nothing AndAlso Not String.IsNullOrEmpty(endpointAddress) Then
Me._proxy.Endpoint.Address = New EndpointAddress(endpointAddress)
End If
End Sub
Public Sub Dispose() Implements IDisposable.Dispose
Try
If Not _proxy Is Nothing Then
If _proxy.State <> CommunicationState.Faulted Then
_proxy.Close()
Else
_proxy.Abort()
End If
End If
Catch ex As CommunicationException
_proxy.Abort()
Catch ex As TimeoutException
_proxy.Abort()
Catch ex As Exception
_proxy.Abort()
Throw
Finally
_proxy = Nothing
End Try
End Sub
End Class
End Namespace
Then you can use it like this:
Using myService As New ServiceProxyHelper(Of MyService.MyServiceClient, MyService.IMyService)
Try
' Do work
myService.ServiceProxy.DoWork()
Catch ex As FaultException(Of MyService.MyServiceException)
' Log exception
End Try
End Using
You have put your own answer in the question.
"What I really want to do is create & open a channel and make brief burst of repeated, short, sequential service calls across the channel. Then nicely close the channel"
That's correct.
Applying this to the example you have given, you can simplify it as:
try
{
_service = new BillingServiceClient();
customers = _service.GetCustomers().ToList();
if (customers != null)
foreach (CustomerModel customer in customers)
{
AddressModel address = (AddressModel)_service.GetAddressModel(customer.CustomerID);
Assert.IsNotNull(address, "GetAddressModel returned null");
}
}
catch
{
_service.Abort();
_service = null;
throw;
}
finally
{
if ((_service != null) &&
(_service.State == System.ServiceModel.CommunicationState.Opened))
_service.Close();
_service = null;
}
Later Edit: Oh, hang on, I just reread your question. You've said that it would fail after multiple repeated calls. I guess the above code actually causes the failure?

WCF - Faults / Exceptions versus Messages

We're currently having a debate whether it's better to throw faults over a WCF channel, versus passing a message indicating the status or the response from a service.
Faults come with built-in support from WCF where by you can use the built-in error handlers and react accordingly. This, however, carries overhead as throwing exceptions in .NET can be quite costly.
Messages can contain the necessary information to determine what happened with your service call without the overhead of throwing an exception. It does however need several lines of repetitive code to analyze the message and determine actions following its contents.
We took a stab at creating a generic message object we could utilize in our services, and this is what we came up with:
public class ReturnItemDTO<T>
{
[DataMember]
public bool Success { get; set; }
[DataMember]
public string ErrorMessage { get; set; }
[DataMember]
public T Item { get; set; }
}
If all my service calls return this item, I can consistently check the "Success" property to determine if all went well. I then have an error message string in the event indicating something went wrong, and a generic item containing a Dto if needed.
The exception information will have to be logged away to a central logging service and not passed back from the service.
Thoughts? Comments? Ideas? Suggestions?
Some further clarification on my question
An issue I'm having with fault contracts is communicating business rules.
Like, if someone logs in, and their account is locked, how do I communicate that? Their login obviously fails, but it fails due to the reason "Account Locked".
So do I:
A) use a boolean, throw Fault with message account locked
B) return AuthenticatedDTO with relevant information
This however carries overhead as throwing exceptions in .NET can be quite costly.
You're serializing and de-serializing objects to XML and sending them over a slow network.. the overhead from throwing an exception is negligable compared to that.
I usually stick to throwing exceptions, since they clearly communicate something went wrong and all webservice toolkits have a good way of handling them.
In your sample I would throw an UnauthorizedAccessException with the message "Account Locked".
Clarification: The .NET wcf services translate exceptions to FaultContracts by default, but you can change this behaviour. MSDN:Specifying and Handling Faults in Contracts and Services
If you think about calling the service like calling any other method, it may help put things into perspective. Imagine if every method you called returned a status, and you it was up to you to check whether it was true or false. It would get quite tedious.
result = CallMethod();
if (!result.Success) handleError();
result = CallAnotherMethod();
if (!result.Success) handleError();
result = NotAgain();
if (!result.Success) handleError();
This is one of the strong points of a structured error handling system, is that you can separate your actual logic from your error handling. You don't have to keep checking, you know it was a success if no exception was thrown.
try
{
CallMethod();
CallAnotherMethod();
NotAgain();
}
catch (Exception e)
{
handleError();
}
At the same time, by returning a result you're putting more responsibility on the client. You may well know to check for errors in the result object, but John Doe comes in and just starts calling away to your service, oblivious that anything is wrong because an exception is not thrown. This is another great strength of exceptions is that they give us a good slap in the face when something is wrong and needs to be taken care of.
I would seriously consider using the FaultContract and FaultException objects to get around this. This will allow you to pass meaningful error messages back to the client, but only when a fault condition occurs.
Unfortunately, I'm in a training course at the moment, so can't write up a full answer, but as luck would have it I'm learning about exception management in WCF applications. I'll post back tonight with more information. (Sorry it's a feeble answer)