I had designed a web service which, upon each method call, would return a structure of some type T if the request were successfully conducted, or otherwise throw a FaultException to the client to signal some error. One of the client applications was an ASP.NET application with a bunch of ObjectDataSource objects directly tied to the methods of the service. Those objects would take care of things such as GridView paging or DropDown populating for themselves.
Unfortunately, I was just now ordered to remove all FaultException from the service and wrap the types I was returning into a generic ServiceResponse<T> structure which wraps the original return structure of type T and adds some more fields to transmit exception information. Having no other choice, I did this right away and replaced all the old service proxy calls with a call to a generic ExecuteMethod<TChannel, TReturn> method which takes care for itself of unwrapping the value if the request was successful or throw some exception otherwise. The problem now is that, since this new method is generic, I can’t tie an ObjectDataSource to it, and GridView automatic paging is gone.
Since ObjectDataSource doesn’t support generic methods, nor it supports generic classes without a lot of mangling with assembly-qualified types names which I would like to avoid, I am left with the options of either page the GridView manually, which I would like to avoid as well, or writing a proxy to wrap every necessary service call and return the desired value, which then is “wrapping a wrapper”. Can you please help me decide which one will not be the worst? Do I have any other options in this case?
I prefer the “wrapping a wrapper” approach as you call it. Architecturally it’s entirely valid since each has a single responsibility.
It will be a pain to maintain if the service contract is not stable but it’s probably more maintainable than the assembly qualified name approach will be in the same circumstances.
(RANT: As an aside I trust the person who “ordered” you to remove the Faults from the service understands the impacts this will have on interoperability of the service. Also, the approach allows the service implementors and consumers to get themselves into difficulty if they fail to properly implement your new proprietary protocol. It seems like it doesn’t actually achieve anything anyway since all you’re changing is the mechanism by which a Fault gets converted to an Exception at the client.)