Should I bind directly to objects returned from a webservice or should I have client-side objects that I bind to my gridcontrols? For instance if I have a service that returns object Car should I have a client side Car object that I populate with values from the webservice Car object? What is considered best-practice? In C# do I need to mark my classes as serializable or do something special to them?
This really depends on what you are getting from the web service. If they are simple data transfer objects and you are only displaying data, then yes, you can bind. If you plan to edit the objects, it may not be usefull as you will need to track changes.
Do your objects and/or collections on the client track changes? If so you can use them.
If you have no change tracking, then you will need to track changes yourself, so you may need to translate the objects or wrap them in something to track changes.
Again, it really depends on what you are getting, what they support, what you are doing with them, as well as what response the server wants back for changes.
One thing you can do is to create client classes corresponding to the web service data contracts with any additional functionality that you want and set the web service reference to reuse existing types. Then there is no reason to create an additional wrapper class to bind to.
If you bind directly to the Web service types, you're introducing a coupling. Should the Web service change in future, this may have undesired side-effects that mean lots of code changes.
For example, what if you're using .asmx Web services today, then shift to WCF tomorrow? That might mean quite a few changes through your code if you've used types that WCF won't serialize.
It's often better in the long run to create specific client-side objects and then translate to and from Web service data contract types. It may seem a lot of work, but this is often repaid greatly when it's time to refactor, as your changes are localised in one place.
This is a good question, which follows the sames lines as two questions I have asked myself:
- Large, Complex Objects as a Web Service Result.
- ASP.NET Web Service Results, Proxy Classes and Type Conversion.
Both of these may be a worthwhile read for you.
Heres my two bits:
- Try to keep the return types of your Web Services to primitives where possible. This not only helps reduce the size of the messages, but also reduces complexity at the receiving end.
- If you do need to return complex objects, return them as a raw xml string (I'll explain below).
What I then do is create a seperate class which represents the object and handles it's xml. I ensure the class can be instantiated from and serialized to xml easily. Then both projects (the web service and the client) can reference the DLL with the concrete object in, but there is none of the annoying coupling with the proxy class. This coupling causes issues if you have shared code.
For example (using your Car
class):
- Web Service (
CarFactory
) methodBuyCar(string make, string model)
is a factory method that returns a car. - You also write a
Mechanic
class that works onCar
objects to repair them, this is developed without knowledge of the Web Service. - You then right a
Garage
class for your application. You add a web reference to theCarFactory
service to get your cars, and then add someMechanic
's to your garage and then crack your knuckles and get ready to get some cars from the factory to get them working on. - Then it all falls over, when you get the result of
CarFactory.BuyCar("Audi", "R8")
and then tell yourMechanic.Inspect(myAudi)
the compiler moans, because theCar
is actually of typeCarFactory.Car
not the originalCar
type, yes?
So, using the method I suggested:
- Create your
Car
class in its own DLL. Add methods to instantiate it and serialize it from/to XML respectively. - Create your
CarFactory
web service, add a reference to the DLL, build your cars as before, but instead of returning the object, return the XML. - Create your
Garage
adding a reference to theMechanic
,Car
DLL and theCarFactory
web service. Call yourBuyCar
method and now it returns a string, you then pass this string to theCar
class, which re-builds its object model. TheMechanic
's can happily work on theseCar's
too because everything is singing from the same hymn sheet (or DLL?) :) - One major benefit is that if the object changes in its design, all you need to do is update the DLL and the web service and client apps are completely decoupled from the process.
Note: Often it can be useful to then create a Facade layer two work with the web services and auto-generate objects from the XML results.
I hope that makes sense, if not, then please shout and I will clarify .
If you are the owner of both the web service and the client.
And you need the parameters of the web service calls to be complex classes which contain not only data but also behavior (actual coded logic) then you are in a bit of a pickle when developing these web services using web service frame works.
As suggested in the answer by Rob Cooper you can use pure xml as web service parameters and xml serialization, but there is a cleaner solution.
If you are using Visual Studio 2005 (probably applies the same for 2008), You can customize the way VS creates you proxy as described in this article:
Customizing generated Web Service proxies in Visual Studio 2005
This way you can tell VS to use your own classes instead of generating a proxy class.
Well when I think of it, it's pretty much same solution as proposed by Rob Cooper, with the little twist, that you wont be writing a Facade layer your self but will be using VS itself as this layer.