views:

31

answers:

3

I'm hosting some SOAP services with WCF. How can I turn off these services via config for the purposes of maintenance, etc., and provide a friendly message to the service consumer with something like "The service you've requested is down for maintenance."?

+2  A: 

You would have to have a second service, that offered the same interface, same methods etc., that would all return that friendly message instead of a real result.

That might get a bit trickier when those service methods don't just return a string but a complex data object - where do you put that "friendly" message??

In reality I think this cannot really be done - since your services typically aren't "seen" by actual people, you cannot just put up an app_offline.htm file or anything like that.

Try to have as little downtime as possible, by e.g. setting up your new version of the service on a new port and testing it there, until you're confident enough to switch over.

With WCF, it's mostly an exercise of updating / copying around the appropriate config, so your service should never really be unavailable for any extended period of time (hopefully!).

If you really must, what you could do, is just have a replacement service that will always throw a FaultContract<ServiceDownForMaintenance> - but then all the clients calling your service would have to know about this and they would have to handle this case and present an error or information message. Your service can't really provide that...

marc_s
You edited your answer to add Fault Contracts, so I'm deleting mine, but I'd like to add a comment: although I agree that having a public service go "down for maintenance" isn't something that should be done, there may be a valid reason to do so; banks, for example, frequently go down for extended periods to "post transactions" and so forth.
Randolpho
@Shafique: In general you should avoid having your service provide "friendly service is down" messages, *unless* you are in such a situation. If you *are* in such a situation, make sure the fact that the service can go down is part of the contract, and that consumers of your service *know* about it and can handle it!
Randolpho
And to be fair, I only used the "down for maintenance" as an example. We will need to pull our service offline for business reasons and provide a friendly message that the service is down, but not necessarily for maintenance. Thanks for the input!
Shafique
@Randolpho: yes, absolutely - you might need to do this - but typically you don't get any special "nice error message" - the service just isn't there and your calls just aren't going to succeed.
marc_s
@marc_s: Well... I don't think TCP timeouts are the best option here. If the service has to be down, the consumer should know relatively quickly. Faults, as you mentioned, are the best alternative.
Randolpho
@Shafique: sounds like you're in the situation I described. As marc_s has mentioned, a custom fault is your best bet. But make sure your consumers are *very* clear on the contract and what that fault means.
Randolpho
A: 

How about this: create a custom ServiceBehavior to intercept my incoming requests to the service. Then, have the custom behavior check a user-defined flag in my config file, something like <add key="IsMyServiceUp" value="true" /> and if that value returns as false then throw a ServiceException with my friendly message and HTTP code of 503 - Service Unavailable.

Does that sound reasonable? Then all I have to do is change the flag in my config file to specify where the service is up or down.

Shafique
Yes, something like that would work. But again: I would throw an interoperable `FaultException<T>` - consumer of your service might not be using .NET and thus couldn't really handle a `ServiceException` properly
marc_s
yes, thanks for that heads up. In reality, I have a .NET REST-ful service facade that is consuming the SOAP service which throws the ServiceException. The REST-ful service facade layer in turn will catch the ServiceException, unpackage the useful information I need, and I throw a new WebFaultException, which inherits from FaultException<T>. Hopefully this would get around the issue that you've suggested above with interoperability for non-.NET REST service consumers.
Shafique
A: 

Okay, so I've created a new Custom Behavior that implements IOperationBehavior. In the Validate method, I've got

public void Validate(OperationDescription operationDescription)
    {
        bool isServiceUp = Boolean.Parse(ConfigurationManager.AppSettings["IsOrderServiceUp"].ToString());
        if (!isServiceUp)
        {
            throw new ServiceException(ServiceErrorCode.Generic_Server_Exception,
            ServiceErrors.Generic_Server_Exception,
            SoapFaultCode.Server);
        }
    }

The other implemented methods ApplyClientBehavior, ApplyDispatchBehavior and AddBindingParameters are all empty.

I have decorated one of my service operations with [ServiceStatusValidation] which is the class name of my custom behavior.

When I start the service and navigate to the operation with this decoration, I do NOT get the exception I've thrown. SOAP UI shows nothing as returned in the response pane, and my consuming REST facade gives a generic 400 error with The exception message is 'The server did not provide a meaningful reply; this might be caused by a contract mismatch, a premature session shutdown or an internal server error.'.

Any ideas? Should I be doing this logic in one of the other methods that I didn't implement instead of the Validate method?

Shafique