472,121 Members | 1,512 Online
Bytes | Software Development & Data Engineering Community
Post +

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 472,121 software developers and data experts.

Passing Inherited types to a web service method

Consider the following:

Class A
{
....
}

Class B:A
{
....
}

Class C:A
{
....
}

Now consider a webservice with the following method

[WebMethod]
public int doSomething(ref A theAInstance)
{
....
}

When I create an application which tries to call the doSomething
method as follows:

status=doSomething(ref instanceOfB);

I get the following error:

cannot convert from 'ref B' to 'ref A'

According to all the docs I have on .Net and webservices, this should
work. I have tried to use xmlinclude to declare the inherited types
in both the definition of A and at the method level (I have seen
people suggest both) and still no go. Are we saying that it is
impossible to pass an inherited type by ref in a web service. If not
any guidance or sample code that would work is greatly appreciated.

Paul
Nov 21 '05 #1
3 3065
To elaborate I also tried the following:

[XmlInclude(typeof(B))]
[XmlInclude(typeof(C))]
Class A
{
...
}

and

[XmlInclude(typeof(B))]
[XmlInclude(typeof(C))]
[WebMethod]
public int doSomething(ref A theAInstance)
{
...
}

Paul

"Paul Michaud" <pm******@earthlink.net> wrote in message
news:5c**************************@posting.google.c om...
Consider the following:

Class A
{
...
}

Class B:A
{
...
}

Class C:A
{
...
}

Now consider a webservice with the following method

[WebMethod]
public int doSomething(ref A theAInstance)
{
...
}

When I create an application which tries to call the doSomething
method as follows:

status=doSomething(ref instanceOfB);

I get the following error:

cannot convert from 'ref B' to 'ref A'

According to all the docs I have on .Net and webservices, this should
work. I have tried to use xmlinclude to declare the inherited types
in both the definition of A and at the method level (I have seen
people suggest both) and still no go. Are we saying that it is
impossible to pass an inherited type by ref in a web service. If not
any guidance or sample code that would work is greatly appreciated.

Paul

Nov 21 '05 #2
This is a very interesting issue! There are no restrictions on passing
custom types to Web services, by VALUE, including inherited types, such as
your B : A. I wrote some basic test code to verify this. In order for this
to work, the Web service and the client must have a common understanding of
the data types. You need to make sure that the type definitions are broken
out into a separate referanceable file, or type definition assembly, with a
dedicated namespace, so that you can drop it into whatever projects need it.
In your case, the Web service and the client. Then, when you set the Web
service calls, you can do so using these qualified types. (And of course, in
Web services terms what you are doing here is referencing the same
XSD-qualified type). For example:

namespace WSTypes
{
public class A {}
public class B : A {}
}

I think you already know this, and have something like this implemented. Now
regarding your use of "ref". This is the cause of your issue. If you define
a Web method that accepts A by VALUE, then you can pass in either A or B.
However, if your Web method accepts A by REF then you can only pass in A.
The reason appears to have to do with the way data types are deserialized on
the receiving end. Call it a bug or a known issue, but it is clearly
something that does not work as it should.

So what I would do is to write your Web methods to accept A and then return
B, as in:

[WebMethod]
public WSTypes.B doSomething(ref WSTypes.A objA)
{

}

This should be an acceptable workaround. Hope this helps -

Jeffrey Hasan, MCSD
President, Bluestone Partners, Inc.
-----------------------------------------------
Author of: Expert SOA in C# Using WSE 2.0 (APress, 2004)
http://www.bluestonepartners.com/soa.aspx

"Paul Michaud" <NO_SPAM_pmichaud@NO_SPAM_earthlink.net> wrote in message
news:ef**************@TK2MSFTNGP10.phx.gbl...
To elaborate I also tried the following:

[XmlInclude(typeof(B))]
[XmlInclude(typeof(C))]
Class A
{
...
}

and

[XmlInclude(typeof(B))]
[XmlInclude(typeof(C))]
[WebMethod]
public int doSomething(ref A theAInstance)
{
...
}

Paul

"Paul Michaud" <pm******@earthlink.net> wrote in message
news:5c**************************@posting.google.c om...
Consider the following:

Class A
{
...
}

Class B:A
{
...
}

Class C:A
{
...
}

Now consider a webservice with the following method

[WebMethod]
public int doSomething(ref A theAInstance)
{
...
}

When I create an application which tries to call the doSomething
method as follows:

status=doSomething(ref instanceOfB);

I get the following error:

cannot convert from 'ref B' to 'ref A'

According to all the docs I have on .Net and webservices, this should
work. I have tried to use xmlinclude to declare the inherited types
in both the definition of A and at the method level (I have seen
people suggest both) and still no go. Are we saying that it is
impossible to pass an inherited type by ref in a web service. If not
any guidance or sample code that would work is greatly appreciated.

Paul


Nov 21 '05 #3
Hi Jeffrey,
Thanks for the reply. The reason I don't want to pass the variable back
through the return type, is that I always use the return for error codes. I
think I have figured out the issue. Consider the following:

A,B, etc defined as below.

Now call
status=doSomething(ref instanceOfB);

This doesn't work because of the issue you mentioned below.

so create a new variable called tempA and point it at instanceOfB (or so we
might think)
A tempA=(A)instanceOfB;

now call the function with tempA.

status=doSomething(ref instanceOfB);
Here is what I have found to have happened.
1) tempA comes back knowing its of type B (or at least when you do a watch
it has the additional attributes present in B and not in A in a substructure
, which by the way manifests differently on either side of the web service
call which is odd, but it does appear to have worked)
2) if I now cast tempA to type B and access the B specific properties it
works fine. All the data is there correctly.
3) Even though tempA was set to be equal to instanceOfB when the function
returns, tempA and instanceOfB are no longer the same insance, they are two
different instances after the de-serialization of tempA. Thus the original
variable instanceOfB is not filled unless you set
instanceOfB=tempA after the call.

The real issue is that according to the web service spec, I should be able
to pass instanceOfB directly and it should work. The fact that I can't
seems to be specifically a .Net bug. The other possibility is that there
may be some settings to export the class hierarchy through the web service
definition so that .Net knows B is a type of A and thus doesn't throw the
compile error (I do have a using statement with an interface dll which
com=ntains the class hierarchy but that doesn't do it). But if there is
something like that I haven't found it yet. I have tried the settings I
mentioned before which I thought was supposed to work but no go.

If anyone knows how to accomplish this I would appreciate it. I have spoken
to a number of others about this and they have had the same problem and
haven't found a decent work around yet.
Paul Michaud
"Jeffrey Hasan" <je**@noreply.com> wrote in message
news:OR**************@TK2MSFTNGP10.phx.gbl...
This is a very interesting issue! There are no restrictions on passing
custom types to Web services, by VALUE, including inherited types, such as
your B : A. I wrote some basic test code to verify this. In order for this
to work, the Web service and the client must have a common understanding of the data types. You need to make sure that the type definitions are broken
out into a separate referanceable file, or type definition assembly, with a dedicated namespace, so that you can drop it into whatever projects need it. In your case, the Web service and the client. Then, when you set the Web
service calls, you can do so using these qualified types. (And of course, in Web services terms what you are doing here is referencing the same
XSD-qualified type). For example:

namespace WSTypes
{
public class A {}
public class B : A {}
}

I think you already know this, and have something like this implemented. Now regarding your use of "ref". This is the cause of your issue. If you define a Web method that accepts A by VALUE, then you can pass in either A or B.
However, if your Web method accepts A by REF then you can only pass in A.
The reason appears to have to do with the way data types are deserialized on the receiving end. Call it a bug or a known issue, but it is clearly
something that does not work as it should.

So what I would do is to write your Web methods to accept A and then return B, as in:

[WebMethod]
public WSTypes.B doSomething(ref WSTypes.A objA)
{

}

This should be an acceptable workaround. Hope this helps -

Jeffrey Hasan, MCSD
President, Bluestone Partners, Inc.
-----------------------------------------------
Author of: Expert SOA in C# Using WSE 2.0 (APress, 2004)
http://www.bluestonepartners.com/soa.aspx

"Paul Michaud" <NO_SPAM_pmichaud@NO_SPAM_earthlink.net> wrote in message
news:ef**************@TK2MSFTNGP10.phx.gbl...
To elaborate I also tried the following:

[XmlInclude(typeof(B))]
[XmlInclude(typeof(C))]
Class A
{
...
}

and

[XmlInclude(typeof(B))]
[XmlInclude(typeof(C))]
[WebMethod]
public int doSomething(ref A theAInstance)
{
...
}

Paul

"Paul Michaud" <pm******@earthlink.net> wrote in message
news:5c**************************@posting.google.c om...
Consider the following:

Class A
{
...
}

Class B:A
{
...
}

Class C:A
{
...
}

Now consider a webservice with the following method

[WebMethod]
public int doSomething(ref A theAInstance)
{
...
}

When I create an application which tries to call the doSomething
method as follows:

status=doSomething(ref instanceOfB);

I get the following error:

cannot convert from 'ref B' to 'ref A'

According to all the docs I have on .Net and webservices, this should
work. I have tried to use xmlinclude to declare the inherited types
in both the definition of A and at the method level (I have seen
people suggest both) and still no go. Are we saying that it is
impossible to pass an inherited type by ref in a web service. If not
any guidance or sample code that would work is greatly appreciated.

Paul



Nov 21 '05 #4

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

22 posts views Thread by Arne | last post: by
reply views Thread by brian.mills | last post: by
6 posts views Thread by nickname | last post: by
8 posts views Thread by =?Utf-8?B?UmF2aQ==?= | last post: by

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.