all groups > dotnet web services > february 2008 >
You're in the

dotnet web services

group:

How to return a user-defined data type object from a webservice?


How to return a user-defined data type object from a webservice? nano2k
2/29/2008 12:57:59 PM
dotnet web services:
Hi

In my solution I have 3 projects:

1. A class library. Let's name it CL (let's also name the namespace as
"CL").
This class library defines a type like this:

[SerializableAttribute()]
public class Person {
//default constructor
private string m_firstName;
private string m_lastName;

public string FirstName {
get { return m_firstName; }
set {m_firstName = value; }
}

public string LastName {
get { return m_lastName; }
set {m_lastName = value; }
}
}

2. A webservice that references CL (described above).
The webservice defines and implements a web method like:

[WebMethod]
public CL.Person GetPerson() {
CL.Person person = new Person();
//read person from database
return person;
}

3. A client winforms application that references the class library
decribed above, instantiates a proxy to the webservice and calls the
web method GetPerson like this:

private void FetchPerson() {
//proxy gets created
CL.Person person = proxy.GetPerson();
}

The compiler will generate a compiler error like this:
Cannot implicitly convert type 'WinFormClientApp.MyWebService.Person'
to 'CL.Person'

Where do I go wrong? How to "transport" more complex objects between
client and the webserver.
I understand how serialization works and I think the serialization
should implicitly work when returning such complex types. Maybe I
missed something.
Should I explicitly use soap serialization and deserialization? Hope
not.

Please help.
Re: How to return a user-defined data type object from a webservice? nano2k
2/29/2008 1:04:20 PM
[quoted text, click to view]

Re: How to return a user-defined data type object from a webservice? John Saunders [MVP]
3/1/2008 8:07:42 PM
[quoted text, click to view]

You went wrong in not understanding web services. Web Services don't
"transport" complex types. They transport XML. In order to keep you from
having to deal with XML, .NET allows the service to "return" a complex type,
CL.Person. .NET then takes care of serializing that complex type into XML.
On the client side, in order to keep the client from having to deal with
XML, .NET creates proxy classes. In particular, it creates a
WebReferenceName.Person class. That is whtat the proxy GetPerson method
returns, not CL.Person.

So, long story short, your client should never reference the class library
"CL".
--
--------------------------------------------------------------------------------
John Saunders | MVP - Windows Server System - Connected System Developer

Re: How to return a user-defined data type object from a webservice? nano2k
3/1/2008 10:44:42 PM
Thanks, John.


On 2 Mar, 03:07, "John Saunders [MVP]" <john.saunders at trizetto.com>
[quoted text, click to view]
Re: How to return a user-defined data type object from a webservice? nano2k
3/1/2008 11:40:44 PM
Anyway,

Passing DataSet or XmlNode objects works by itself.
How can I enable my Person class to act like the above ones?

Thanks.


[quoted text, click to view]
Re: How to return a user-defined data type object from a webservice? John Saunders [MVP]
3/3/2008 7:34:09 AM
[quoted text, click to view]
Anyway,

Passing DataSet or XmlNode objects works by itself.
How can I enable my Person class to act like the above ones?

=========
You don't want to. Really.
--
--------------------------------------------------------------------------------
John Saunders | MVP - Windows Server System - Connected System Developer

Re: How to return a user-defined data type object from a webservice? nano2k
3/4/2008 11:09:16 AM

On 3 Mar, 14:34, "John Saunders [MVP]" <john.saunders at trizetto.com>
[quoted text, click to view]

Sorry, but why?
Re: How to return a user-defined data type object from a webservice? John Saunders [MVP]
3/4/2008 5:46:31 PM
[quoted text, click to view]

On 3 Mar, 14:34, "John Saunders [MVP]" <john.saunders at trizetto.com>
[quoted text, click to view]

Sorry, but why?
Just for the record.
=
I pretty much told you why before. It's just not how Web Services works.

The paradigm of Web Services is all about interoperability between client
and server by using industry-standard protocols (HTTP) and data formats
(XML). You are asking how you can use the above to pass data specific to a
particular platform (Microsoft .NET). There is no provision for that in the
Web Services standards. If you read those standards, you'll find mention of
the use of standards (XML Schema) to describe the structure of the data to
be exchanged. Nowhere in any of those standards is there an ability for you
to specify a particular data type from a particular platform.

This is in contrast to .NET Remoting, which is platform-specific, and which
actually transmits the full typename and assembly name of the types of the
data being transferred. This permits the client to receive instances of the
precise type sent by the server. There is no provision for anything like
this in Web Services.

Now, I'm only just recently getting up to speed on WCF, but it looks like
when you create a Service Reference (the WCF equivalent of a Web Reference),
you have the ability to tell WCF to try to reuse datatypes if the types are
declared in particular assemblies. This may give you what you're looking
for, as long as you are in a controlled environment where you can be certain
that the type that WCF will choose for you is compatible with the type being
sent by the server. An example of such an environment is when the server and
all of its clients are in the same .NET solution. Tihs may be acceptable for
"internal" web services, which are only ever meant to be used by well-known
clients. It cannot work in the general case.
--
--------------------------------------------------------------------------------
John Saunders | MVP - Windows Server System - Connected System Developer

Re: How to return a user-defined data type object from a webservice? nano2k
3/5/2008 7:19:31 AM
On 5 Mar, 00:46, "John Saunders [MVP]" <john.saunders at trizetto.com>
[quoted text, click to view]

Thanks John.
I understand and aggree entirely.
But my app is ment to work ONLY on .NET platforms. It is not a public
web site or smtg like that.
It's an "internal" application for a company that will use the app
inside its own VPN.
More than that, I'm being asked to secure the entire system so that
the webservice will only work with the designated client (also
developed by me).

So I find myself in this particular case, not in the general case. I
assure you I understand how interoperatibility works and its demands.

Anyway, your input was very good for me, but what do you say about my
particular situation? Creating standard XML schemas for each type I
want to "transport" would be a waiste of time, as I am 100% SURE my
webservice will only be accessible from a .NET client.

Re: How to return a user-defined data type object from a webservice? Bradley Plett
3/5/2008 3:46:05 PM
What John is saying is all true, but it's a bit of an ivory tower
approach. Sometimes we developers have to bend the rules because it's
the easiest way to get the job done!

Anyway, I'm guessing that you have shared code between your server and
your client (probably using the same class code, shared in VSS). If
that's the case, what you're up against is simply the fact that the
object coming from the server via the web service is in a different
namespace from the object you want to use in your client. There are a
variety of ways of getting around this problem. For example, you can
use reflection and generics to change the namespace of the object in
question. Here's a code sample that will simply copy everything from
one object to another, assuming all their public properties are
identical:

// the idea for this came from
http://www.eggheadcafe.com/tutorials/aspnet/a4264125-fcb0-4757-9d78-ff541dfbcb56/net-reflection--copy-cl.aspx
private static T SetProperties<T, U>(U fromRecord, T toRecord)
{
foreach (PropertyInfo fromField in
fromRecord.GetType().GetProperties())
{
if (fromField.Name != "Id")
{
foreach (PropertyInfo toField in
toRecord.GetType().GetProperties())
{
if (fromField.Name == toField.Name)
{
toField.SetValue(toRecord, fromField.GetValue(fromRecord,
null), null);
break;
}
}
}
}
return toRecord;
}

Hope that helps!
Brad.

On Wed, 5 Mar 2008 07:19:31 -0800 (PST), nano2k
[quoted text, click to view]
Re: How to return a user-defined data type object from a webservice? John Saunders [MVP]
3/5/2008 4:29:11 PM
[quoted text, click to view]
Thanks John.
I understand and aggree entirely.
But my app is ment to work ONLY on .NET platforms. It is not a public
web site or smtg like that.
It's an "internal" application for a company that will use the app
inside its own VPN.
More than that, I'm being asked to secure the entire system so that
the webservice will only work with the designated client (also
developed by me).

So I find myself in this particular case, not in the general case. I
assure you I understand how interoperatibility works and its demands.

Anyway, your input was very good for me, but what do you say about my
particular situation? Creating standard XML schemas for each type I
want to "transport" would be a waiste of time, as I am 100% SURE my
webservice will only be accessible from a .NET client.

PS: I should have been more specific on this on my first post, my bad.
==========

If you're doing .NET to .NET, then you shouldn't be using Web Services - you
should be using .NET Remoting, or WCF with the NetDataContractSerializer.
These cover the case I mentioned, where it's important to be using the
correct version of the correct type. They both communicate the actual .NET
type name across the channel.

If, for some political reason you feel you must stick to ASMX web services,
then you can do something like have a translation layer than receives the
proxy type, then uses it to fill in an instance of the "real" type.
--
--------------------------------------------------------------------------------
John Saunders | MVP - Windows Server System - Connected System Developer

Re: How to return a user-defined data type object from a webservice? John Saunders [MVP]
3/5/2008 10:11:52 PM
[quoted text, click to view]

Sorry, Bradley, you're wrong. It's not that the classes are in different
namespaces. They're different classes that happen to have a lot of names in
common. Try returning a custom type that has a non-default constructor, or
methods, or indexers. None of them will show up in the proxy classes because
none of them are described by XML Schema or WSDL.

Remember: they're _proxy_ classes. They are stand-ins for the real classes,
which never leave the server to travel over the wire. They only exist in
order to stand as proxy for the real classes, handling serialization and
deserialization.
--
--------------------------------------------------------------------------------
John Saunders | MVP - Windows Server System - Connected System Developer

Re: How to return a user-defined data type object from a webservice? Bradley Plett
3/6/2008 12:17:58 AM
Yes, I understand that they're different classes and different
objects. That is, after all, the implication of different namespaces.
I also understand that there can be issues around the constructor and
any hidden data, but pragmatically the solution I suggested will
handle the majority of the situations common programmers deal with
between server-side and client-side objects. :-)

Sure, remoting might be a preferable solution to maintain the full,
true object, but sometimes remoting is overkill and I think sometimes
we tend to over-think/over-analyze and ignore simple solutions which
may be less elegant and less pure, but do the job.

Brad.

On Wed, 5 Mar 2008 22:11:52 -0500, "John Saunders [MVP]"
[quoted text, click to view]
Re: How to return a user-defined data type object from a webservice? Bradley Plett
3/6/2008 9:40:40 AM
Good point - it is worth understanding, that's for sure!

The sample I gave was not intended to modify the proxy class. I never
do that either, since regeneration, for me, is a fairly common task.
The sample I gave was intended either in an inherited class or as a
utility function.

Brad.

On Thu, 6 Mar 2008 10:49:36 -0500, "John Saunders [MVP]"
[quoted text, click to view]
Re: How to return a user-defined data type object from a webservice? John Saunders [MVP]
3/6/2008 10:49:36 AM
[quoted text, click to view]

Brad, in answering newsgroup and forum posts on this topic, I have found
many people who do expect the code they wrote in their server-side classes
to appear on the client side. In my opinion, that's because .NET makes it so
easy to call a "web method". After all, it's a _method_, isn't it?

The problem is that this totally obscures what's actually happening, so many
people never even learn that there is something different happening at all.
I recommend naming web references with the word "Proxy" in the name, so
that, maybe, some new developer will at least wonder "proxy for what"? It
would also make it easier for me, when they ask "where's my indexer", to
answer, "remember, it's only a proxy class". They could then say, "oh, so
_that's_ why it's called Proxy".

;-)

Also, Brad, if you're going to suggest that people modify the proxy class,
you should remind them that the class will be overwritten whenever "Update
Web Reference" is used. For that reason, I _never_ suggest modifying
generated code.
--
--------------------------------------------------------------------------------
John Saunders | MVP - Windows Server System - Connected System Developer

Re: How to return a user-defined data type object from a webservice? nano2k
3/7/2008 6:36:49 AM
Thanks John and Brad

John,
Never dealed with .NET Remoting or WCF.
Any good and easy to digest resources on these?
Thanks.


On 5 Mar, 23:29, "John Saunders [MVP]" <john.saunders at trizetto.com>
[quoted text, click to view]
Re: How to return a user-defined data type object from a webservice? John Saunders [MVP]
3/7/2008 10:00:41 AM
[quoted text, click to view]
Thanks John and Brad

John,
Never dealed with .NET Remoting or WCF.
Any good and easy to digest resources on these?
Thanks.
=============
I have been working seriously with WCF only for the past few weeks.
Nonetheless, I'm willing to make a suggestion.

Try the Web Services Software Factory: Modeling Edition at
http://www.codeplex.com/servicefactory. This is what I've been reviewing for
the past week or so, and have mostly decided that I'll recommend it as the
way for my company to go forward with web services.

As it relates to your situation, I think it will be helpful. WCF makes a
strong distinction between the types sent out on the wire, and the types
used in the Business Logic Layer, and the Data Access Layer below that.
WSSF:ME goes further by requiring you to design your wire formats in an
abstract way, and then by helping you create translation methods for
translating between the layers. At the same time, it permits the client and
server both to work with these "data contract" types in useful ways. You can
specify, for instance, that the server will treat a particular collection as
an array, but the client will treat it as a List<T>, or a Dictionary<string,
T>.

Give it a look.
--
--------------------------------------------------------------------------------
John Saunders | MVP - Windows Server System - Connected System Developer

Re: How to return a user-defined data type object from a webservice? Relaxin
3/9/2008 6:05:10 AM

[quoted text, click to view]

That was said beautifully!!
AddThis Social Bookmark Button