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