Returning a custom class.....

M

Manni

Hi!

I have a component (MyComp) with a class TheElement.

I write a Webservice (MyService) with tow methods - one returning a DataSet,
the other returning TheElement.

Next I write a client (WinApp) and add a web reference to MyService.

The two methodes are there, one return (as expected) a class
System.Data.DataSet.
BUT the other returns MyService.TheElement instead of MyComp.TheElement.

The public elements are there and so on, but it is a different class!!!

I tried a lot of things
1.) DataSet is derivied from MarshalByRefObject
When I add this to my class, it does not work --
Marsh....implements an interface -- as error from the service.
2.) DataSet implement ISerializeable
I can't implement this since the class should also work with
Windows.CE - no ISerializeable there!!!
3.) I write a method in my class (TheElement) wich takes
MyService.TheElement...
This does not work since this class is generated by the Proxy
and therefore not available on the server.

Even if there could be a way with conditionals or so - my intention is to
get a proxy from the WebService - automaticly!!
Of course I can change the Proxy - but the WebService is complex and under
development - it will grow.
So I would always (at a change of the WebService) have to "recode" the
proxy, instead of simply say "refresh".

It is possible (since it works with DataSet), but how can it be done???

Thanks a lot

Manfred
 
M

MSFT

Hi Manfred,

I think you have to implement the ISerializable Interface in your custom
class (DataSet also implements this interface). When pass a object from web
service, it first will be Serialized by calling GetObjectData method in
ISerializable Interface. If you can't implement the ISerializable
Interface, you may consider converting your object to a dataset first and
then pass it from web service. For example, save its all property to a
datatable and recreate this object based on values in this datatable.

Luke
Microsoft Online Support

Get Secure! www.microsoft.com/security
(This posting is provided "AS IS", with no warranties, and confers no
rights.)
 
M

Manni

Thanks for your fast response Luke!

As I mentioned - I use this things in mobile Apps - so the "inbetween" of
using a dataset is
not wanted.
To do things like this - I could write some methods converting
"ServiceNS.MyType" to CompoNS.MyType.

But that is not what I asked!!!

Another MS guy gave me a hint to

With the XMLNamespace for the Component classes - now I got it work!
This means, that the Components class is serialized with the right NS,
so that the conversion from MySvc.Class to MyCompo.Class works.

I only to edit the Proxy (using my Components namespace and delete the
returnclass defined),
but it works now.

So I have a much better solution than my first one.

BUT still there is no explanation how how the Framework does the thing with
DS.
There the proxy is automaticly defined right!!!!

Since my project uses about 30 Classes within that WebService - it's a
little hard to edit the proxy
all the times (it changes frequently because of development on the
webservice).

But it works!

I repeat:
MS can do the "automatic fitting proxy generation" with DS (and other
classes)!!!
What is the mystery behind this???
Can we ("normal" developers) do this also??
Or is there a hack in WSDL that it "knows" the framework classes???

Manfred
 
S

Scott Mason

Hello.
In response to your questions regarding the automatic (on the fly)
generation of the proxy for the DataSet.
The DataSet does not actually change any proxy settings anywhere. If you
have a DS object getting passed back as a return value on a method call,
the client will expect a DataSet object until you go in and manually change
it.
I think that you're refering to the fact that a DataSet object can
obviously return different data in the form of DataTables, Rows, etc. Each
DataSet can be completely different and yet all the client has to do is
expect a single DataSet and it works. Is this what you're talking about?
If so, then let's talk a bit about the inner workings of a DataSet. The DS
implements the ISerializable interface and will basically turn all of the
data it carries into XML format to pass back to the client.
A DataSet object containing the authors table in the pubs database would
look something like the soap response below. You would have to implement
the ISerializable interface if you want something like that.

<?xml version="1.0" encoding="utf-8" ?>
- <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
- <soap:Body>
- <GimmeDataResponse xmlns="http://tempuri.org/">
- <GimmeDataResult>
- <xs:schema id="ScottsDataSet" xmlns=""
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
- <xs:element name="ScottsDataSet" msdata:IsDataSet="true">
- <xs:complexType>
- <xs:choice maxOccurs="unbounded">
- <xs:element name="authors">
- <xs:complexType>
- <xs:sequence>
+ <xs:element name="au_id">
- <xs:simpleType>
- <xs:restriction base="xs:string">
<xs:maxLength value="11" />
</xs:restriction>
</xs:simpleType>
</xs:element>
- <xs:element name="au_lname">
- <xs:simpleType>
- <xs:restriction base="xs:string">
<xs:maxLength value="40" />
</xs:restriction>
</xs:simpleType>
</xs:element>
- <xs:element name="au_fname">
- <xs:simpleType>
- <xs:restriction base="xs:string">
<xs:maxLength value="20" />
</xs:restriction>
</xs:simpleType>
</xs:element>
- <xs:element name="phone">
- <xs:simpleType>
- <xs:restriction base="xs:string">
<xs:maxLength value="12" />
</xs:restriction>
</xs:simpleType>
</xs:element>
- <xs:element name="address" minOccurs="0">
- <xs:simpleType>
- <xs:restriction base="xs:string">
<xs:maxLength value="40" />
</xs:restriction>
</xs:simpleType>
</xs:element>
- <xs:element name="city" minOccurs="0">
- <xs:simpleType>
- <xs:restriction base="xs:string">
<xs:maxLength value="20" />
</xs:restriction>
</xs:simpleType>
</xs:element>
- <xs:element name="state" minOccurs="0">
- <xs:simpleType>
- <xs:restriction base="xs:string">
<xs:maxLength value="2" />
</xs:restriction>
</xs:simpleType>
</xs:element>
- <xs:element name="zip" minOccurs="0">
- <xs:simpleType>
- <xs:restriction base="xs:string">
<xs:maxLength value="5" />
</xs:restriction>
</xs:simpleType>
</xs:element>
<xs:element name="contract" type="xs:boolean" />
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:choice>
</xs:complexType>
- <xs:unique name="Constraint1" msdata:primaryKey="true">
<xs:selector xpath=".//authors" />
<xs:field xpath="au_id" />
</xs:unique>
</xs:element>
</xs:schema>
- <diffgr:diffgram xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"
xmlns:diffgr="urn:schemas-microsoft-com:xml-diffgram-v1">
- <ScottsDataSet xmlns="">
- <authors diffgr:id="authors1" msdata:rowOrder="0">
<au_id>172-32-1176</au_id>
<au_lname>Black</au_lname>
<au_fname>Johnson</au_fname>
<phone>408 496-7223</phone>
<address>10932 Bigge Rd.</address>
<city>Menlo Park</city>
<state>CA</state>
<zip>94025</zip>
<contract>true</contract>
</authors>
- <authors diffgr:id="authors2" msdata:rowOrder="1">
<au_id>213-46-8915</au_id>
<au_lname>Green</au_lname>
<au_fname>Marjorie</au_fname>
<phone>415 986-7020</phone>
<address>309 63rd St. #411</address>
<city>Oakland</city>
<state>CA</state>
<zip>94618</zip>
<contract>true</contract>
</authors>

etc.


Thank you,
Scott Mason
Microsoft

This posting is provided "AS IS", with no warranties, and confers no rights.
 
M

Manni

There are 2 Problems with your solutuion!
I can't implement ISerializable since the thing shuold work on the CF,
where serialization is not available!

Secound it is not what I want!

All what I want are 2 things (and it is done wiht classes like DataSet and
ArrayList).

I want that the proxy-generatro includes my Namespace as it does with
System.Data.
Second I want that the proxy-generator does NOT build it's own class XXXX.

So another MS Guy form MS (Dino Chiesa) told me:
The DataSet is special. It works because the Web Service infrastructure
in
the .NET Framework looks for a special flag in the runtime-provided XML
Schema definition called IsDataSet. I believe if wsdl.exe finds this,
it
generates a dataset in the proxy.

So from that point of view - I had to find another solution!
I found it, by writing a macro for VS.
This enters the namespace - and then removes the class definitions!
After a "refresh" on the WS I call this macro - and the rest works fine!

My one and only question was - if there is a way to let the proxy-gernator
know
He, this class is a "Shared assembly class" (like DataSet) - so please
include the Namespace
and don't declare this class.

But since this seems to be done "internal" I have to live with the macro -
not very hard to do so :)

Thanks

Manfred
 
M

Madhu Ponduru [MSFT]

I did some research on this problem

By deafult Web service proxy will include all public classes ,This is
generated by .NET frame work,We can't change this behaviour

If you don't want to change this behaviour,Make sure Web service return
type to Native type objects (Example :native type can be Dataset or object
type)

Following document explains about native types
XML Web service Type Marshaling
http://samples.gotdotnet.com/quickstart/aspplus/doc/webservicetypes.aspx

in my example I didn't see any Namespace differences between Dataset and
Custom class

If i mis understood this question,Can you please send me your sample
application and please give me brief description,What kind of results you
are expecting and What is the current behaviour

-Thank you
Madhu
(Microsoft .NET DS Team)
 
M

Manni

Hy Madhu!

Thanks for your information!

The senteces
By deafult Web service proxy will include all public classes ,This is
generated by .NET frame work,We can't change this behaviour
would explain all. But there is an "except" to this senteces!
....will include all public classes, except classes like DataSet,
ArrayList.....

It would be good (for my solution) to have a way to tell the FW not to
generate
proxy classes for my custom classes it I don't like it! Some behaviour like
"if class exists in the referneces don't build a proxy class".

You write
in my example I didn't see any Namespace differences between Dataset and
Custom class

There is a difference - for DataSet no proxy class will be gernated. For
ArrayList it is the same.
For your custom class there will be a proxy class generated so that means
you have:
System.Data.DataSet
and
ApplicationNS.ServiceNS.CustomClass.

A small example:
You have a WS with two methods - MethodReturnDataSet and
MethodReturnMyClass.
You generate a proxy and get:
namespace ApplicationNS.WhatIvChosen {
using ......
using System.Data; /!!!!!!!!!

class TheSvcName {

[XML.....]
public DataSet MethodReturnDataSet() {
........

[XML.....]
public MyClass MethodReturnMyClass {
.......

} //end of TheSvcName class

class MyClass {
public.....
//all the public members (attributes)
} //end of MyClass

} // end of NS

As you see, there is a difference - for DataSet there is no proxy class
generated.
Instead System.Data is included with using.

What I would like to have is the following code:
namespace ApplicationNS.WhatIvChosen {
using ......
using System.Data; /!!!!!!!!!
using MyAssembly; //assume my class is from that assembly!

class TheSvcName {

[XML.....]
public DataSet MethodReturnDataSet() {
........

[XML.....]
public MyClass MethodReturnMyClass {
.......

} //end of TheSvcName class

//NO PROXY CLASS FOR MyClass
} // end of NS


Somehow the proxy gernerator must decide when to generate a proxy class and
when not.
And that is the behavior wich would be great if it is "changeable".
I think about something like a checkbox in the discovering wizard like "dont
generate proxy for referneced classes".
This apporoach is an easy thing I think - since it is done with DataSet and
such classes!

You are right - I could use object instead of my class - but then I would
loose typechecking at compile time.
I would have to writ code like
MyClass Var=(MyClass) TheSvc.MethodReturnMyClass();
And that kind of upcast is not checkable for the compiler. So an exception
would occur at runtime.

I hope you can understand better what my questions are about!

For the moment I have a macro in VS.NET wich changes the proxy file.
It is easy since the proxy classes follow the serviceclass and the using
statements are right
befor the service class begins.

So search for the first class in the file. Search back for a ; (ending the
last using statement).
Go down one line - enter "using MyNamespace;"
Search forward for class (now again at the serviceclass), search forward for
the next class.
So I find the first proxy class.
Search back for the closing bracket }.
Go down one line and replace the whole code to the rest of the file with a
closing bracket (for the namespace).

This macro approach works fine if my service only returns classes for wich I
have a reference at the client.

Manfred
 
M

Madhu Ponduru [MSFT]

Hi Manfred,

Thanks for giving such a valuable information

Your feedback is very important to us,You can always submit your feedback
online from this link

http://register.microsoft.com/mswish/suggestion.asp

I will send your feedback to Microosft VIsual studio.NET tools team,They
may consider this request in netx release of VS.NET

-Thank you
Madhu
 

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

Forum statistics

Threads
473,968
Messages
2,570,154
Members
46,702
Latest member
LukasConde

Latest Threads

Top