marcelo-ferraz
marcelo-ferraz

Reputation: 3257

Wcf service exception good practices

I am developing a distributed application. In it, there are roles and sets of permissions that I must validate.
Is a good pratice to throw an exception, in per example, unauthorized access?
Or should I send some message back to the client?

Upvotes: 36

Views: 37037

Answers (3)

khaled4vokalz
khaled4vokalz

Reputation: 958

Throwing general Dot Net Exceptions would make the service client proxies and the server channel to go in faulted state if you are not using basicHTTPBinding ...To avoid that you should always throw FaultException from the service... from you catch block just use:

throw new FaultException("Your message to the clients");

Upvotes: 4

Traxxus
Traxxus

Reputation: 871

On your service operation, you can specify a FaultContract that will serve both purposes like so:

[OperationContract]
[FaultContract(typeof(MyServiceFault))]
void MyServiceOperation();

Note that MyServiceFault must be marked with DataContract and DataMember attributes, in the same way you would a complex type:

[DataContract]
public class MyServiceFault
{
    private string _message;

    public MyServiceFault(string message)
    {
        _message = message;
    }

    [DataMember]
    public string Message { get { return _message; } set { _message = value; } }
}

On the service-side, you are then able to:

throw new FaultException<MyServiceFault>(new MyServiceFault("Unauthorized Access"));

And on the client-side:

try
{
    ...
}
catch (FaultException<MyServiceFault> fault)
{
    // fault.Detail.Message contains "Unauthorized Access"
}

Upvotes: 61

Daniel Persson
Daniel Persson

Reputation: 2233

Well, you can catch all exceptions in the WCF service implementations methods and rethrow them as FaultExceptions. By doing it this way, the exception will be rethrown on the client with a message of your choosing:

[OperationContract]
public List<Customer> GetAllCustomers()
{
    try
    {
        ... code to retrieve customers from datastore
    }
    catch (Exception ex)
    {
        // Log the exception including stacktrace
        _log.Error(ex.ToString());

        // No stacktrace to client, just message...
        throw new FaultException(ex.Message);
    }
}

To avoid having unexpected errors relayed back to the client, it's also a good practice to never throw Exception instances in code on the server-side. Instead create one or more of your own exception types and throw them. By doing so, you can distinguish between unexpected server processing errors and errors that are thrown due to invalid requests etc:

public List<Customer> GetAllCustomers()
{
    try
    {
        ... code to retrieve customers from datastore
    }
    catch (MyBaseException ex)
    {
         // This is an error thrown in code, don't bother logging it but relay
         // the message to the client.
         throw new FaultException(ex.Message);
    }
    catch (Exception ex)
    {
        // This is an unexpected error, we need log details for debugging
        _log.Error(ex.ToString());

        // and we don't want to reveal any details to the client
        throw new FaultException("Server processing error!");
    }
}

Upvotes: 15

Related Questions