This is exactly, in my opinion, what you should do. I've blogged about this several times (www.lhotka.net/weblog) and I discuss it somewhat in Chapter 11.
Regarding considerations for building your web services, there are four key points in my view.
First, make sure you are message-based, as that's the core of SOA. Don't pass simple/primitive types to/from services - make sure to always pass messages.
Second, treat each method as a use case. They must be atomic and stateless anyway, so they are pefect textbook candidates for use case driven OOD: clear entry point, defined inputs and outputs and a defined purpose/task.
Third, remember that services are autonomous and paranoid. They stand alone and trust no one. This means that they must validate and calculate and manipulate anything themselves. Even if a client application might have already done these things, the client application can't be trusted. SOA succeeds because services are paranoid, and fails if they are too trusting.
Fourth, don't try to "reuse" code between applications. The whole point of SOA is to get reuse at the service level and avoid coupling between applicaitons. Any reuse of code between applications is a form of coupling. Yes, this leads to a fair amount of duplicate code at times, because your client application will implement things like validation logic to give the user a decent experience, but your services won't trust the client application and will re-validate. But that's the cost you pay to get the loose coupling of SOA and still have a decent user experience.
It is best to make each object as "dumb" as possible - especially in terms of what the object knows about other objects.
In other words, the best approach is to have each object (parent, child, etc) put its own data into the DTO. Otherwise the parent must know all the details about all the properties of all its children, which would badly break encapsulation and reduce maintainability.
Copyright (c) Marimer LLC