return non-dataset XML to vb.net client?

  • Thread starter Thread starter Tom Leylan
  • Start date Start date
T

Tom Leylan

(I posted this in languages.vb also... I can't figure out where things go if
you use a little of a lot of things)

Hi all... I'm looking for an example (or a pointer to one) related to the
following. I have a WebService (it works) that fetches data, turns it into
XML and returns it to a vb.net client. The "data" though represents
property values for an object which the vb.net client has created and now
has to load.

Just about every example I have found demonstrates how "tables, rows,
columns" and such can be fetched, updated, etc. but I have it working so
that nothing on the client side knows a thing about where the data comes
from or if it is even fetched from a table at all. It is all objects (and
collections of objects) on the client side.

So the XML string that has to be created on the server is a mix of things.
It includes data from one or more tables but also the result of some other
"knowledge" that it has (the date and time on the server for instance). The
XML returned will be a composite of the properties that make up the object.

I'm looking for a way to cleanly create this composite XML string on the
server side and an equally elegant way to break it down again on the client
so the values can be assigned to the newly created object. Any ideas?

I have it all working with VB6, DCOM and property bags but I'd like to get
it all converted to .NET before the decade is out :-) A website, an
article, a book, I'll take what I can get.

Thanks,
Tom
 
ick
Tom,

I don't really get why you are sending XML ?
If you are just going to create objects on the client side, why not send
objects?

Eg, make a webservice that returns a custom type , and return that type.

Then on the client side, the response is an instance of that type.

In other words, the .NET runtime takes care of serialization and
de-serialization of the object graph into (and from) XML. XML is used on
the wire but you don't need to interact with XML or the DOM within your
applicaiton logic.

You do this:
server side:
create object graph
send it as a response
client side:
get response object
do work on it. .. . .


Does this work??

------

On the other hand if you send and receive XML, then in effect you would be
doing this within your application:
server side:
create your object graph
serialize it to XML
send that string to client
client side:
get xml string
de-serialize it (manually??!) into an object graph
do work on it...

This seems like you are doing more work that you need to...

If you really insist on doing the serialization yourself, then you could do
this (sorry, not VB):

server side:

[WebMethod]
public string GetRawXml()
{
System.Xml.XmlDocument doc = new System.Xml.XmlDocument();
MyCustomType instance= new MyCustomType ();
// fill MyCustomType here.... (fill in the object graph)

System.IO.StringWriter sw = new System.IO.StringWriter();
System.Xml.Serialization.XmlSerializer s1 = new
System.Xml.Serialization.XmlSerializer(typeof(MyCustomType));
s1.Serialize(sw, instance);
return sw.ToString();
}

client side:

string s= MyWebService.GetRawXml();
System.Xml.XmlDocument doc= new System.Xml.XmlDocument();
doc.LoadXml(s);
// here, you would manually construct the object graph from the given
XmlDocument
// then, do some work on the object graph
 
Dino Chiesa said:
I don't really get why you are sending XML ?
If you are just going to create objects on the client side, why not send
objects?

Hi Dino... Can I be your friend :-) I started using XML because I thought
that was the way to do it. It currently works (in VB6) with a byte stream
and I'm happy with that but I'll always listen to a better idea.
Eg, make a webservice that returns a custom type , and return that type.
Then on the client side, the response is an instance of that type.

In other words, the .NET runtime takes care of serialization and
de-serialization of the object graph into (and from) XML. XML is used on
the wire but you don't need to interact with XML or the DOM within your
applicaiton logic.

You do this:
server side:
create object graph
send it as a response
client side:
get response object
do work on it. .. . .

Does this work??

It works for me! My current implementation converted to strings to make the
transmission faster but if that is what .NET is going to do anyway I'd love
to let .NET handle the details.

(I always look this stuff in the interim but...) is there any way you can
point me to an example of what my class has to do in order to give it this
ability to self-serialize? I learn fast but I seem to "search" rather slow.
Maybe the problem is when I get 1,900,000 hits :-)

Thanks,
Tom
 
Dino... I found some articles on serialization and formatters. I have to
read more about this now as it looks exactly like what I was intending to
do.

Also do you have any opinions on whether it's (generally speaking)
worthwhile to put it in a soap wrapper at this point? I'm not going to
offer the data through the Internet or to the general public but it might
make for an interesting demo to a client and if there isn't much downside it
might be a good thing.

Thanks,
Tom
 
Hi again Dino, well this has been interesting. I just read about the
ISerializable interface and I believe I'll add the extra code to go that
route.

It seems to me to offer a little more control and... one of the things
(unless I'm mistaken) I will have to set up is a separate "data-aware"
class. This MgrClass would have a method for returning the class I want,
and a method that accepts a serialized version of my class (passed back) for
storage. As I see it, if I don't do it this way then any ADO (along with
any other data-related "SQL" for instance) references need to be compiled
into the client side.

Those methods for fetching and saving data make no sense in the client-side
version of the object since it can't access the database (that's all done on
the server.) And the client-side versions make no sense in the server
version.

Does this make sense or have I over-complicated it again? BTW, the samples
I've found so far use "cloning" an object as the example. The requirements
for creating a local copy are different than when sending one across a wire
to another machine. In those cases (as I've mentioned) they can't be
_exact_ duplicates unless all the capabilities are compiled into both the
server and the client and that's not a great idea.

Thanks for your comment,
Tom




..
 
Hey Tom, you've been busy!

1. re: ISerializable
Can we start with something simple? I am not sure of your requirements, so
maybe we can start with the simpler cases and work up to the more complex
ones (like using ISerializable).

You can get implicit serialization with .NET and web services.
ISerializable gives you more control but are you sure you want and need it?
You may be able to get by with the implicit xml-serialization support in
..NET.

Here's source code for an example service, and client, and makefile. This
example exhibits both manual serialization (sending response as a string),
and auto-magic serialization (Sending the actual object, which gets
automatically serialized as xml), of complex types.
http://cheeso.europe.webmatrixhosting.net/srcview.aspx?dir=Leylan&file=Service.asmx

Here's the URL for the (working) service:
http://cheeso.europe.webmatrixhosting.net/Leylan/Service.asmx

You can try it out via the test form.

Here's a great intro article on XML and serialization in .NET:
http://www.agiledeveloper.com/articles/XMLSerialization.pdf

2. re: SOAP Wrapper
YES, use web services. If your load and performance requirements allows you
to use XML as the on-the-wire protocol, then by all means use web services
and expose the service via SOAP. Even if you don't expose it over the
internet publicly, this is the way to do it. Why? Because web services
allows maximum interop - clients regardless of platform or technology will
be able to consume your service. It's the most flexible method, and the
tools support is great. Also this is where the strategic development is
happening within Microsoft and within the broader industry.


-Dino
 
Dino Chiesa said:
Hey Tom, you've been busy!

As apparently have you :-)
Can we start with something simple? I am not sure of your requirements, so
maybe we can start with the simpler cases and work up to the more complex
ones (like using ISerializable).

2. re: SOAP Wrapper

That's pretty much what I was thinking also. Requirements never "shrink"
and they always expand outside of what is defined as 'the most we'll ever
need" typically before we're done programming it.

I'm going to incorporate all of this now that I am certain it will work.
And thanks again very much for your lucid explanations. It shows us that
newsgroups don't have to be just a series of people posting "you're a dope"
(or worse) at each other.

Tom
 
Dino... aw shucks there is a problem. I tried all sorts of combinations but
nothing works. Your example creates a class defined in the web service and
uses it in the web service but it doesn't create an object on a client
elsewhere.

When I debug my web service project I see the code execute and it serializes
my object and it creates the XML just fine. When I then go to my client (in
this case a .DLL) it says it can't create an object from the class on the
server.

My biggest problem is deciding where and how to define the class itself. I
sort of alluded to the problem in an earlier message but I probably didn't
state it clearly. In fact I know I goofed up on the description a bit.

On the client-side there is a .DLL which contains business objects (let's
call it MYDATA.DLL. A client app would access MYDATA.DLL of course. Let's
call one of the classes "Customer." I've declared it to be serializable.
The web service obviously needs to be able to instantiate an object of type
Customer also in order to fill it with data and to send it MYDATA.DLL on the
client side. My first thought was to give the MYSERVICE.ASPX project a
reference to MYDATA.DLL so they are using a common Customer class.
MYSERVICE.ASPX has a GetCustomer service available which will return a
serialized Customer object. As I mentioned this works when testing
MYSERVICE.

When I then try to access the class (in the debugger) using MYDATA.DLL by
calling a Test() function which instantiates a Customer object and then
requests the object from MYSERVICE it won't compile or run complaining that
the two versions of Customer are incompatible.

The error doesn't exactly indicate it but I thought the problem might be
that both my test and the web service want the same copy of the .DLL since
I'm testing on a localserver. This wouldn't be the case if I put a copy out
on the Internet of course but that makes testing more difficult.

One thought I had was to create a .DLL with the business classes separate
from the one that fetches the data. That way the business class .DLL would
be part of the web service project but the data fetching .DLL wouldn't. If
there is a conflict created by the one shared .DLL doing all the work this
should stop that. But I don't know if it would make a difference.

Any idea? Do you need a better description?

I think the bottom line question is how do web services and clients get
access to a common class definition?

Thanks,
Tom
 
Dino Chiesa said:
Hey Tom, you've been busy!

And I've been busy again, too. I have more information. I'm probably going
to have to implement remoting. I just read an article on the MS site that
outlined the differences (and ties) between web services and remoting. It
defined a number of issues with the return of some classes when a web
service returns it's idea of what the properties of a class are. Computed
properties aren't returned for instance and the client won't even know they
were supposed to exist.

It also looks fairly straightforward to set up a customized server (in place
of using IIS) if one wanted to direct the exchange to another port or wanted
to set up some special features. It cleared up my confusion about where the
..DLL goes also. In the case of web services on the server, in the case of
remoting both on the server and the client.

Well I have something to keep me occupied through Friday now!

Tom
 
Computed
properties aren't returned for instance and the client won't even know they
were supposed to exist.

Yep, so one way web services people deal with it is to use a "Value Object"
or "Data Transfer Object", which is in effect a structure, a type without
methods. It's just for the convenience of shipping data around.
It also looks fairly straightforward to set up a customized server (in place
of using IIS) if one wanted to direct the exchange to another port or wanted
to set up some special features. It cleared up my confusion about where the
.DLL goes also. In the case of web services on the server, in the case of
remoting both on the server and the client.

Check that - in the case of web services it is possible to have shared types
across client and server (See my previous post).

Cheers!
 
Dino Chiesa said:
Check that - in the case of web services it is possible to have shared types
across client and server (See my previous post).

I think I have it all straight now. I got the web service working by
explicitly defining the local object as a type of the "remote" class rather
than having it created from the local business dll. It worked so I'm on
track again.

I believe I'm going in the direction of remoting now. I found a book on it
and things should move along briskly.

I know where to find you if I get stuck :-)
Tom
 
Back
Top