Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
HomeAnnouncementsFree MagazinesWhite PapersSubmit Content
Discussion GroupsASP.NETWindows FormsLanguages.NET FrameworkVisual Studio.NET
Articles.NET FrameworkASP.NETToolsWindows Forms
.NET DirectoryOpen Source ProjectsUser GroupsWeb Resources
Related Topics
Visual Basic 6SQL ServerMS AccessOther DB ProductsMS Server ProductsMore Topics ...

.NET Forum / ASP.NET / Web Services / February 2006

Tip: Looking for answers? Try searching our database.

complex types in a Web service

Thread view: 
Enable EMail Alerts  Start New Thread
Thread rating: 
William F. Kinsley - 13 Feb 2006 20:48 GMT
I'm trying to use complex types in a Web service as follows:

// In Some Util Library
[Serializable]
public class PatientFilter
{
   ....
}

[Serializable]
public class PatientCollection : IEnumerable
{
   ....
}

// In the webservice asmx.cs
[WebMethod]
public PatientCollection GetPatients(PatientFilter filter)
{
   ....
}

So this all works great, except that on the client side, after adding a web
reference, two things happen that aren't so good.

The first is that another PatientFilter class is auto generated in the
Reverence.cs in the WebReference namespace.  This causes type problems
between the original PatientFilter class and the one in the Reference.cs.  A
solution to this is to delete the auto generated class in Reference.cs and
everything works, but this is annoying as the class is constantly being
regenerated and I'm pretty sure there's a better way.  When using a DataSet
class as a parameter, the auto generating tool does not make a new class in
Reference.cs.  As best I can guess this is because the WSDL defines the
DataSet parameter as:

<s:complexType>
<s:sequence>
 <s:element ref="s:schema" />
 <s:any />
</s:sequence>
</s:complexType>

So my 1st question is how do I get my class to do the same, or similar thing
so that a new class does not get auto generated in Reference.cs

The second thing that happens that is annoying is that the GetPatients()
returns an object[] instead of a PatientCollection in the WebReference
class.  Again, editing the Reference.cs and replacing the object[] return
parameter with PatientCollection fixes the problem and everything works.
The WSDL for this return value ends up being:
<s:complexType>
<s:sequence>
 <s:element minOccurs="0" maxOccurs="1" name="GetPatientsResult"
type="tns:ArrayOfAnyType" />
</s:sequence>
</s:complexType>

So my second question is how do I get the method to return a
PatientCollection instead of an ArrayOfAnyType automatically in the auto
generated class.
Steven Cheng[MSFT] - 14 Feb 2006 07:22 GMT
Hi William,

Welcome to the MSDN newsgroup.

As for the two question you mentioned, here are some of my understanding
and suggestion:

1.So my 1st question is how do I get my class to do the same, or similar
thing
so that a new class does not get auto generated in Reference.cs
===============================
This is a bit hard since the client webservice proxy generate the types
according to the webservice's WSDL document. And WSDL document use XML
schema's standard types to represent different object types used in
webservice methods, this is for interop consideration since the webservice
will be consumed by different client platform (c++, java, php.....). And
for list/collection like type, WSDL will always use SOAP Array to represent
it, thus the .NET client proxy will generate the Array for such
objects(parameter or return type). If you do need to use .NET specific
type, you need to manually change the client genernated proxy code.

2.So my second question is how do I get the method to return a
PatientCollection instead of an ArrayOfAnyType automatically in the auto
generated class.
===============================
I think this is likely caused by the custom collection class you used only
implement IEnumerable interface which is not sufficient to let the ASP.NET
webservice engine automatically use SOAP Array to represent it in WSDL.   I
think you can consider the following means:

1) Instead of only implment IEnumerable, you can consider make the
colleciton class derived from CollectionBase class and implements those
methods. Such collectionbase derived class will be represend by SOAP
Array(of certain custom class type) automatically in WSDL document.

2) You can also try explicitly apply the following attribute in your
webmethod to indicate that the return type of the webmethod is an Array
(and the Array item's type). For example:

[WebMethod]
[return:XmlArray()]
[return:XmlArrayItem(typeof(User))]
public UserCollection GetWebUsers(int count)
{
            ...............
}

Hope this helps.

Regards,

Steven Cheng
Microsoft Online Support

Signature

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

William F. Kinsley - 14 Feb 2006 19:58 GMT
Hi Steven,

I understand that the WSDL specifies the complex types for interop purposes,
however it does not do this for the DataSet type, yet the Reference.cs file
still manages to type it to a DataSet. So my question #1 is really how do I
do what the DataSet (and some other .net types) are doing?

As for question #2, having it return an array of Patients types isn't what
I'm looking for, I want the return type in the Reference.cs to actually be
my original type (without of course another proxy class from question #1,
but that's a separate issue). So is there an attribute that will change the
return type to be my class in the WSDL?

Thanks

> Hi William,
>
[quoted text clipped - 55 lines]
> (This posting is provided "AS IS", with no warranties, and confers no
> rights.)
Steven Cheng[MSFT] - 15 Feb 2006 08:00 GMT
Thanks for your response William,

So the further question you mentioned all aims at make the autogenerated
client proxy use our custom class type(.NET specific). I'm afraid this is
not available through the buildin webservice client proxy genenration
tool(wsdl.exe). The DataSet class you mentioned is a particular class(which
is somewhat hardcoded in the wsdl.exe tool's generation logic since there
is not particular attributes in description for DataSet as we can see).
I've tried DataTable class also which can not be recognized.    
I think for your scenario, it is more likely that you're going to build a
custom webservice client proxy generation tool rather than extend the
current one. Anyway, currently the simplest means is to modify the
autogenerated proxy class code.

Regards,

Steven Cheng
Microsoft Online Support

Signature

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

Javier G. Lozano - 17 Feb 2006 04:09 GMT
Have you tried controlling the XML serialization for your classes using
the attributes under the System.Xml.Serialization namespace?  I've
written web services that return lists and are represented as arrays on
the client (why?  You're actually exchange a contract (collection of
objects) rather than a type (IEnumerable)).

Free Magazines

Get these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...

Oracle MagazineNetwork ComputingComputer WorldBio-IT WorldeWeekInformation WeekInfosecurity
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2009 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.