Recommended Web Method Output for Unknown Custom Object?

D

David Palau

I'm looking for some guidance on what data type would work best as the
result output of a web service function method. This web method will
return an object that implements a class that is generated from the
xsd.exe tool built off a xml schema. I don't know at invocation time
what the exact class will be returned from the call.

Even though this is an internal web service to our company, this web
service will be used by a bevy of clients, not all .Net applications.

Initially this web method was just returning a string that was created
from using XmlSerializer to serialize the object using a XmlWriter
into a MemoryStream and then just using a StreamReader to get to the
actual string.

But I'm wondering if there is a better way to go about this?

I created a version of this web method that return a XmlDocument that
is created from the same MemoryStream object (e.g.
document.Load(stream)). That seems to work as well and seems more
intuitive.

Is there another alternative? XmlNode or XmlDataDocument?

Any gottchas on using one type or the other?

Thanks in advance for any help.

-David
 
J

John Saunders [MVP]

David Palau said:
I'm looking for some guidance on what data type would work best as the
result output of a web service function method. This web method will
return an object that implements a class that is generated from the
xsd.exe tool built off a xml schema. I don't know at invocation time
what the exact class will be returned from the call.

Even though this is an internal web service to our company, this web
service will be used by a bevy of clients, not all .Net applications.

Initially this web method was just returning a string that was created
from using XmlSerializer to serialize the object using a XmlWriter
into a MemoryStream and then just using a StreamReader to get to the
actual string.

But I'm wondering if there is a better way to go about this?

I created a version of this web method that return a XmlDocument that
is created from the same MemoryStream object (e.g.
document.Load(stream)). That seems to work as well and seems more
intuitive.

Is there another alternative? XmlNode or XmlDataDocument?

Any gottchas on using one type or the other?

Thanks in advance for any help.

This sounds like an interesting web service. Can you provide more detail
about it? In particular, why does it not know what kind of object it will
return? Does the client know what kind of object it will return? If not, how
does the client process what was returned to it?

The answers to those questions will help determine the best return type and
format. For instance, if the client was simply going to write the return
value to a file, I'd say you should return XmlNode, as it would just be a
block of XML - the client wouldn't have to look inside of the block.

It's different if the clients need to know more.
 
D

David Palau

The web service returns a representation of a configurable 'item' that
is defined by an XML schema. Instead of having a dozen different
methods that return a particular item (based off an ID parameter) of a
certain type we just have one method where you pass in the type of
product you want (as well as particular ID of it).

For example, a representation of two of our classes that get returned:

Class Foo
ID As Integer
FieldA As String
FieldB As String

Class Bar
ID As Integer
FieldC As String
FieldD As String

So our web method definition looks like:

Function GetItem(ByVal type As String, ByVal ID As Integer) As
String /* This function result is what I'm asking about */

The parameter type is just an identifier so we know what particular
class to create behind the web service (by use of an abstract
factory). For this conversation, it could just be the name of the
class: "Foo" or "Bar":

WebService.GetItem("Foo", 123)
WebService.GetItem("Bar", 456)

With the number of different types of items we have, coupled with the
fact that we have a dozen different methods you can perform on a
particular item (e.g. Delete, Update), we decided to make the type of
the item a parameter as well instead of something like:

Function GetFooItem(ByVal ID As Integer)
Function GetBarItem(ByVal ID As Integer)

There also exists the situation where we truly don't know the class of
the object returning - I won't bore you with the details of why.

So the client has to interrogate the result of the web service method
to either A) deserialize back into the right .Net class (for a .Net
app) and access it's variables that way or B) perform some other
function on it (usually just displaying certain fields) using whatever
XML 'reader' they have available to them (they also know what our
schema is).


In our current method we just return a string so the start of the XML
coming back looks like

<?xml version="1.0" encoding="utf-8" ?>
<string xmlns="...

Using an XmlDocument the start of the XML looks like:

<?xml version="1.0" encoding="utf-8" ?>
- <Foo xmlns="...

I was thinking that using an XmlDocument seemed more correct as the
object represenation is XML straight from the service instead of
wrapped up in a string. But is XmlNode a better option? Does using
XmlDocument or XmlNode limit what sort of clients can interrogate the
web service? From what I understand, no, but I wanted to be sure (I
haven't actually turned this over to the client teams that will be
using this).

I didn't mention this above, but this is an ASP.Net 2.0 web service,
not sure if that matters or not.

Thanks for replying and any insight you may have.
 
J

John Saunders [MVP]

David Palau said:
The web service returns a representation of a configurable 'item' that
is defined by an XML schema. Instead of having a dozen different
methods that return a particular item (based off an ID parameter) of a
certain type we just have one method where you pass in the type of
product you want (as well as particular ID of it).

I think you may not have the best object model for your needs. I also think
you didn't give much detail on _how_ the clients use objects returned to
them when they don't know ahead of time what kind of object it will be. For
instance, to they interrogate the returned object and then process it in a
switch statement? If so, then perhaps an object hierarchy and the use of
polymorphism would help. I know that XML serialization handles that, though
I haven't yet tried this with a web service.

FYI, I have worked with a web service that handles highly-configurable
types. It is salesforce.com. Not only are users able to customize existing
types, but it is possible to create entirely new types, complete with
relationships between the new and old types. It is also possible to create
subtypes of existing types easily.

In other words, the schema can change from one minute to the next! The way
they handle that is by requiring that the customer downloads the WSDL file
whenever they care about the change in configuration. That gives you the
updated WSDL, complete with customizations, and yet allows the client to
work with strong types.
 
D

David Palau

We certainly may not have the right object model. I have glossed over
the details of how the clients of the web service handle the data just
to try to keep things simple, but perhaps a better explanation is in
order. 99% of the time the clients will know what type of item they
are requesting.

Our clients really come in two flavors:

1. Read-only, informational clients that wants to reference the fields
of the 'object' (this object is read as an XML document or
deserialized into the .Net class for .Net applications) in some
manner, either to the end-user in either a form or browser based
application, or as part of some calculation based on data gathered
from other sources (and then displayed on something or store somewhere
else). These clients know where to get the schema definition of the
objects that we are returning through our web service. Like I said
they know they are requesting a 'Foo' object and will get one. The
types of these applications range from our ERP product (SAP) to
applications that run on our manufacturing floor to reporting-based
applications.

2. We have a form based client that handles creating and configuring
these objects (just think of a standard configurator-type of
application - its is a little more complicated than that). We
actually don't manipulate the object coming back from the web service
- that object is just a DTO object (http://en.wikipedia.org/wiki/
Data_Transfer_Object) that is just used to for data transversal
between our domain and client tiers. We use this DTO to construct a
traditional complex domain object with state that is used by this
client. When we are ready to save this business object it gets
translated back into the DTO to be passed back to the web service
(which leads to a similiar question of what type of parameter this DTO
object should be in - currently it is just a .Net string again). The
complex object has the capability to generate a DTO of itself or
initialize from a DTO (with the help of an 'assembler/mapper' class).

Like I mentioned above, the web service has a dozen or so different
methods that operate on a business object (we have about a dozen
different types of items). Instead of having 144 different methods on
our web service, we only have 12. Albeit these web methods are just a
very thin layer on top of our buinsess facade before getting to the
domain business logic.

You raise a good point about exploring inheritance based schemas -
currently the schema that eventually translates into a DTO are all
individual even though the complex business objects that use them are
coming from a OOP heirarchy (the schemas just duplicate common
properties). Would then the web methods deal in the 'base' schema/
class? Then I assume the return types of that method would be of the
base DTO class. But would this be okay for non-.Net clients?

But given my current project realities, would returning the
representation of this DTO be best serverd by sticking the XML into a
string type or a different one?
 
J

John Saunders [MVP]

David Palau said:
We certainly may not have the right object model. I have glossed over
the details of how the clients of the web service handle the data just
to try to keep things simple, but perhaps a better explanation is in
order. 99% of the time the clients will know what type of item they
are requesting.

Our clients really come in two flavors:

1. Read-only, informational clients that wants to reference the fields
of the 'object' (this object is read as an XML document or
deserialized into the .Net class for .Net applications) in some
manner, either to the end-user in either a form or browser based
application, or as part of some calculation based on data gathered
from other sources (and then displayed on something or store somewhere
else). These clients know where to get the schema definition of the
objects that we are returning through our web service. Like I said
they know they are requesting a 'Foo' object and will get one. The
types of these applications range from our ERP product (SAP) to
applications that run on our manufacturing floor to reporting-based
applications.

2. We have a form based client that handles creating and configuring
these objects (just think of a standard configurator-type of
application - its is a little more complicated than that). We
actually don't manipulate the object coming back from the web service
- that object is just a DTO object (http://en.wikipedia.org/wiki/
Data_Transfer_Object) that is just used to for data transversal
between our domain and client tiers. We use this DTO to construct a
traditional complex domain object with state that is used by this
client. When we are ready to save this business object it gets
translated back into the DTO to be passed back to the web service
(which leads to a similiar question of what type of parameter this DTO
object should be in - currently it is just a .Net string again). The
complex object has the capability to generate a DTO of itself or
initialize from a DTO (with the help of an 'assembler/mapper' class).

Like I mentioned above, the web service has a dozen or so different
methods that operate on a business object (we have about a dozen
different types of items). Instead of having 144 different methods on
our web service, we only have 12. Albeit these web methods are just a
very thin layer on top of our buinsess facade before getting to the
domain business logic.

You raise a good point about exploring inheritance based schemas -
currently the schema that eventually translates into a DTO are all
individual even though the complex business objects that use them are
coming from a OOP heirarchy (the schemas just duplicate common
properties). Would then the web methods deal in the 'base' schema/
class? Then I assume the return types of that method would be of the
base DTO class. But would this be okay for non-.Net clients?

But given my current project realities, would returning the
representation of this DTO be best serverd by sticking the XML into a
string type or a different one?

David,

The salesforce.com web services are similar to yours. They have a small
number of generic methods which operate on types in a type hierarchy. As I
said earlier, these types are extremely configurable. I have been able to
consume their web service from a .NET project since version 1.1, simply by
using Add Web Reference. .NET creates proxy classes that use inheritance to
define the sub-classes, even though the base class (which I think is called
"object", or "sobject") has very little in it, and all the other classes
derive from "sobject" - none of them derive from other classes.

As to the type for these objects, or for the DTO, you can certainly use
XmlElement. See the MSDN article "The Power of XmlElement Parameters in
ASP.NET Web Methods"
(http://msdn2.microsoft.com/en-us/library/aa480498.aspx). That's what I use
most of the time, simply because I design my WSDL by hand, and because I
prefer keeping the entire service written in terms of XML.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,994
Messages
2,570,223
Members
46,810
Latest member
Kassie0918

Latest Threads

Top