How can I make classes available to the client?

B

Burak

Hello,

I read in a book that if we want a class in a web
service to be available on the client, we should precede it with the
"WebService" attribute.

I created a simple web service as follows

Public Class Strings
Inherits System.Web.Services.WebService

<WebService()> _
Public Class MeasureClass
Public height As Integer
Public width As Integer
End Class

<WebService()> _
Public Class ColorClass
Public red As Integer
Public blue As Integer
Public green As Integer
End Class

<WebMethod()> _
Public Function ToUpper(ByVal inputString As String) As String
Return inputString.ToUpper
End Function

End Class

When I access this web service from a client, I only
see the Strings class and neither the MeasureClass nor
the ColorClass.

How can I make these two classes available to the
client?

Thank you,

Burak
 
S

Sami Vaaraniemi

To make classes available to your client, simply use the classes as web
method parameter or return types. Copies of the classes will then be
generated along with the web service proxy class.

Regards,
Sami
 
B

Burak Gunay

Hello,

Yes, I noticed this too. If I am returning a class or using a class as
input parameter, then the class shows up on the client.

I was trying to see if there was a way to show classes on the client
without associating it with a webmethod.

I guess not.

Thanks,

Burak
 
D

Dan Rogers

Hi Burak,

The book you read apparently has some of the attributes mixed up. The
WebServiceAttribute is used to describe a service which consists of
callable methods. These methods themselves may take classes as input or
return them as outputs.

There are quite a number of attributes provided to control the shape of the
XML on classes exposed in this way, but in general, there is nothing you
need to do beyond exposing them directly. In order to get more classes
than you have listed in your inputs/outputs to show up on the automatically
generated proxy class that is created with Add Web Reference, you can also
use the XmlIncludeAttribute on your web service class or on one of your
data classes. This attribute identifies any other class type. When the
WSDL for the service is generated, the schema for the added classes will be
included, and thus will show up in your web service proxy.

I hope this helps

Dan Rogers
Microsoft Corporation

--------------------
 
B

Burak Gunay

Hi Dan,

You wrote,
In order to get more classes
than you have listed in your inputs/outputs to show up on >the automatically
generated proxy class that is created with Add Web >Reference, you can also
use the XmlIncludeAttribute on your web service class or >on one of
your data classes.

Could you give me an example of this please?

For example, how do I use the XmlIncludeAttribute on the following class
declaration to make it visible on the client?

Public Class MeasureClass
Public height As Integer
Public width As Integer
End Class

Thank you,

Burak
 
D

Dan Rogers

Hi Burak,

You would place the XmlInclude statement on your web service class.

Let's say you have a web service class MyService, then the markup might
look like the following:

[WebService]
[XmlInclude(typeof(MeasureClass))]
public MyService : ...

--------------------
 
B

Burak Gunay

Hello Dan,

I put the xmlincludeattribute before class definitions and it still did
not work. I did this because I could not place it before the webservice
class declaration.

Here is my web service, written in vb:

Imports System.Web.Services
Imports System.Data.OleDb
Imports System.Xml.Serialization

<System.Web.Services.WebService(Namespace:="http://tempuri.org/StringPro
c/Service1")> _
Public Class Strings
Inherits System.Web.Services.WebService

<XmlIncludeAttribute(GetType(MeasureClass)), Serializable()> _
Public Class MeasureClass
Public height As Integer
Public width As Integer
End Class

<XmlIncludeAttribute(GetType(ColorClass)), Serializable()> _
Public Class ColorClass
Public red As Integer
Public blue As Integer
Public green As Integer
End Class

<WebMethod()> _
Public Function ToUpper(ByVal inputString As String) As String
Return inputString.ToUpper
End Function
End Class

Do you know how to fix this?

Thanks,

Burak
 
D

Dan Rogers

Hi Burak,

Putting the include attributes in front of the classes they refernce won't
help you. You need to get it into the serialization stream for your method.
The issue you're facing is a bit unusual. You seem to want to create class
definitions in your generated proxy, even though those classes aren't used
by the proxy to do anything particularly useful for the methods your
service defines. Since the WSDL and Schema generation parts of the
serialization infrastructure only emit definitions for types that are or
possibly are encountered in the methods that are exposed by your service,
you need to make sure that you work around the optimizations in the
serializer's reflection step.

Since your only method exposes only basic types, the serializer is
optimizing the WSDL definition. To get the proxy to have extraneous
classes, you need to make it possible for a caller to NEED the classes you
want to have copied over. One way to do this is to expose a simple object
method that should not be called, but that makes it possible for a set of
defined types to be passed as parameters. Here's an example of code that
WILL get classes defined in the proxy classes namespace. I'll explain an
issue you will probably face in a few lines below the sample:

Imports System.Web.Services
Imports System.Xml.Serialization

Public Class MeasureClass
Public height As Integer
Public width As Integer
End Class

Public Class ColorClass
Public red As Integer
Public blue As Integer
Public green As Integer
End Class

<System.Web.Services.WebService(Namespace:="http://tempuri.org/Burak/Service
1")> _
Public Class Service1
Inherits System.Web.Services.WebService <WebMethod()> _
Public Function ToUpper(ByVal inputString As String) As String
Return inputString.ToUpper
End Function

<WebMethod(), _
XmlInclude(GetType(MeasureClass)), _
XmlInclude(GetType(ColorClass))> _
Public Sub doNothing(ByVal x As Object)
End Sub

Note that I've defined a new method that makes it possible to pass the
named classes. The XmlInclude statements do this. These could go on the
method, or on the service class (no difference, except scope). They do NOT
go on the classes they reference (this would not do anything). If you look
at the generated service description after adding these 5 lines (the
doNothing method is all I added), you 'll see that the types are now
defined.

An issue you may face is one of expectation. Even though the caller side
proxy now has the types you seem to want it to have, they will not always
work the way you could desire. For instance, if you are expecting this to
be a general mechanism for deploying shared classes, you'll find that only
the exposed public data members will be projected, and no business logic
from the server side will accompany them. Another thing is the .NET
namespace itself for these "projected" classes will not match the server
side unless you are very careful to name the proxy the same thing as the
shared classes .NET namespace on the client side.

In all, I am not sure I see a value in this, but this is one way to, I
think, accomplish what you are seeking.

Hope this helps

Dan Rogers
Microsoft Corporation
 

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,755
Messages
2,569,536
Members
45,007
Latest member
obedient dusk

Latest Threads

Top