By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
429,373 Members | 1,792 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 429,373 IT Pros & Developers. It's quick & easy.

Passing complex type/class to WebService

P: n/a

Hi

How do I pass a complex type to a webservice??

What I have is a Class 'MyComplexClass' which lives in it's own dll/namespace. I'd like to pass this class to my webmethod:

<WebMethod()_
Public Sub MyMethod(ByVal arg As MyComplexClass)

End Sub

When I add a webreference to my client project VS2005 creates a class similar to the 'MyComplexClass' and put it in the proxy code.

This means that I have to give an instance of the 'MyComplexClass' defined in the proxy, rather than an instance of the 'MyComplexClass' defined by me.

How do I make it pass the correct class?? Do I have to make an SubClass of my proxy which converts between the two types??

TIA

Søren
Apr 25 '07 #1
Share this Question
Share on Google+
7 Replies


P: n/a
"Søren M. Olesen" <sm******@hotmail.comwrote in message news:Oz**************@TK2MSFTNGP04.phx.gbl...

Hi

How do I pass a complex type to a webservice??

What I have is a Class 'MyComplexClass' which lives in it's own dll/namespace. I'd like to pass this class to my webmethod:

<WebMethod()_
Public Sub MyMethod(ByVal arg As MyComplexClass)

End Sub

When I add a webreference to my client project VS2005 creates a class similar to the 'MyComplexClass' and put it in the proxy code.

This means that I have to give an instance of the 'MyComplexClass' defined in the proxy, rather than an instance of the 'MyComplexClass' defined by me.

How do I make it pass the correct class?? Do I have to make an SubClass of my proxy which converts between the two types??

TIA

Søren

Let me see if I understand you correctly. On your server, you have a class SomeNamespace.MyComplexClass. Your web service has a WebMethod which takes a parameter of that type.

In developing your client, you use Add Web Reference to add a reference to this web service. This produces a proxy class for the web service, and proxy classes for the types used as parameters or return values from the web service.

Am I correct so far?

If I understand you correctly, then you want the client to use the assembly containing the server-side class MyComplexType, and to pass that to the web service through the proxy? But since there is no relationship between the server-side class and the proxy class (which is why they call it a proxy class), the two classes are not the same thing and cannot be interchanged.

Web Services do not pass objects: they pass XML. A client-side object is serialized into XML before sending it to the server, which deserializes it _into an object of a different type_.

The two types have little in common. For instance, try creating a server-side type with non-default constructors, indexers, write-only properties and methods. Try using that in a WebMethod and take a look at the proxy class. It will not have the non-default constructors, indexers, write-only properties or methods. And it's not meant to have them.

Perhaps if you'll tell us what you need to accomplish, we'll be able to help you accomplish it.
--

John Saunders [MVP]
Apr 25 '07 #2

P: n/a
>Let me see if I understand you correctly. On your server, you have a class SomeNamespace.MyComplexClass. Your web service has a WebMethod which takes a parameter of that type.
>In developing your client, you use Add Web Reference to add a reference to this web service. This produces a proxy class for the web service, and proxy classes for the types used as >parameters or return values from the web service.
>Am I correct so far?
Yes, that's true.
>Perhaps if you'll tell us what you need to accomplish, we'll be able to help you accomplish it.
What I'd like is to have two different webservices MyWebService1.MyMethod and MyWebService2.MyMethod each taking a parameter of SomeNameSpace.MyComplexClass. The SomeNameSpace.MyComplexClass exists in it's own assembly, so it's very easy to link to it to both the servers and the clients.

What I'd like to do is to pass the SomeNameSpace.MyComplexClass between the two services without having to convert the class to and from the two proxyclasses for the two webservices.

Of course the SomeNameSpace.MyComplexClass has to be XML serializeable and everything, but when that's the case, there shouldn't be any problems passing it around.

Regards,

Søren
Apr 26 '07 #3

P: n/a
"Søren M. Olesen" <sm******@hotmail.comwrote in message news:uz*************@TK2MSFTNGP06.phx.gbl...
>Let me see if I understand you correctly. On your server, you have a class SomeNamespace.MyComplexClass. Your web service has a WebMethod which takes a parameter of that type.
>In developing your client, you use Add Web Reference to add a reference to this web service. This produces a proxy class for the web service, and proxy classes for the types used as >parameters or return values from the web service.
>Am I correct so far?
Yes, that's true.
>Perhaps if you'll tell us what you need to accomplish, we'll be able to help you accomplish it.
What I'd like is to have two different webservices MyWebService1.MyMethod and MyWebService2.MyMethod each taking a parameter of SomeNameSpace.MyComplexClass. The SomeNameSpace.MyComplexClass exists in it's own assembly, so it's very easy to link to it to both the servers and the clients.

What I'd like to do is to pass the SomeNameSpace.MyComplexClass between the two services without having to convert the class to and from the two proxyclasses for the two webservices.

Of course the SomeNameSpace.MyComplexClass has to be XML serializeable and everything, but when that's the case, there shouldn't be any problems passing it around.

Sorry, I guess I'm not being clear enough. You do not "pass objects" between the client and server using Web Services. The server takes an object and serializes it into some XML. The client deserializes it into a proxy object. The server object and proxy object are completely unrelated. Period.

The client should absolutely not have a reference to the assembly which the server uses to define the type that the server sends on the wire.

Any attempt to hack around this fundamental restriction will very likely lead to failure and frustration. If you really need the client and server objects to be "the same", then you need to use .NET Remoting or WCF.
--

John Saunders [MVP]

Apr 26 '07 #4

P: n/a
Søren,

You should modify the proxy class (either directly or via a partial class declaration) and add a public constructor to Proxy.MyComplexClass that takes an instance of SomeNamespace.MyComplexClass. In the constructor you can initialize the properties based on the values of SomeNamespace.MyComplexClass. This will deal with web service methods that use MyComplexClass as an input parameter. If MyComplexClass is returned from the web service then you should add a public method on Proxy.MyComplexClass that will return SomeNamespace.MyComplexClass.
"Søren M. Olesen" <sm******@hotmail.comwrote in message news:uz*************@TK2MSFTNGP06.phx.gbl...
>Let me see if I understand you correctly. On your server, you have a class SomeNamespace.MyComplexClass. Your web service has a WebMethod which takes a parameter of that type.
>In developing your client, you use Add Web Reference to add a reference to this web service. This produces a proxy class for the web service, and proxy classes for the types used as >parameters or return values from the web service.
>Am I correct so far?
Yes, that's true.
>Perhaps if you'll tell us what you need to accomplish, we'll be able to help you accomplish it.
What I'd like is to have two different webservices MyWebService1.MyMethod and MyWebService2.MyMethod each taking a parameter of SomeNameSpace.MyComplexClass. The SomeNameSpace.MyComplexClass exists in it's own assembly, so it's very easy to link to it to both the servers and the clients.

What I'd like to do is to pass the SomeNameSpace.MyComplexClass between the two services without having to convert the class to and from the two proxyclasses for the two webservices.

Of course the SomeNameSpace.MyComplexClass has to be XML serializeable and everything, but when that's the case, there shouldn't be any problems passing it around.

Regards,

Søren
Apr 26 '07 #5

P: n/a
"Scott Holman" <sh*****@micros.comwrote in message news:OZ**************@TK2MSFTNGP03.phx.gbl...
Søren,

You should modify the proxy class (either directly or via a partial class declaration) and add a public constructor to Proxy.MyComplexClass that takes an instance of SomeNamespace.MyComplexClass. In the constructor you can initialize the properties based on the values of SomeNamespace.MyComplexClass. This will deal with web service methods that use MyComplexClass as an input parameter. If MyComplexClass is returned from the web service then you should add a public method on Proxy.MyComplexClass that will return SomeNamespace.MyComplexClass.
Scott, have you tried this before? I would be concerned about maintainability in terms of keeping the client in sync with the server. By giving the client knowledge of the server (i.e., the client now knows the actual class the server is using, as opposed to knowing the WSDL and proxy class), the two are now tightly coupled.

Again, .NET Remoting and WCF both address this scenario. "Standard" Web Services do not.
--

John Saunders [MVP]

Apr 26 '07 #6

P: n/a
As I interpreted the OP questions, the OP has a client side implementation of MyComplexClass. This implementation may or maynot be the same implementation on the server-side...it doesn't really matter. The OP needs to marshall the data in SomeNameSpace.MyComplexClass to the proxy class so that the proxy can marshall to the server. The OP could
1 - write a helper class such as
class foo
{
public static Proxy.MyComplexClass Bar(MyNameSpace.MyComplexClass value)
{
//Code to Initialize and return Proxy.MyComplexClass
}
}

2 - or...assuming that the code generated for Proxy.MyComplexClass is declared as a partial class...the OP could extend the proxy class in another file and implement the logic in 1 above in a constructor and leave the generated proxy class code unmodified. (This would seem to be exactly the situation called for by a partial class).

And to answer your question, yes I have done this with proxies generated by svcutil. In fact, I have even replaced a specific class within the proxy with my own implementation.

In reading the orignial post, it is likely that the OP is using the same implementation of MyComplexClass on both the client and server. This however does not result in a tightly coupled client and server. The client application still has to marshal data from the Proxy.MyComplexClass to the SomeNameSpace.MyComplexClass. The only coupling that exists is the coupling to the data contract as represented by Proxy.MyComplexClass and this coupling exists in all clients that consume the web service. However, the client and server implementation do have a physical coupling due to the shared assembly. The OP should realize that bugs in SomeNameSpace.MyComplexClass will require that both client and server be rebuilt and redistributed. The OP can minimize this by refactoring the class and 1) separating common logic and 2) separating the data representation from the business logic (for example: MyComplexClassData and MyComplexClassCommonLogic, MyComplexClassServerLogic, MyComplexClassClientLogic). Refactoring along these lines is more consistent with the Patterns and Practices guidance in the Web Service Software Factory.
"John Saunders [MVP]" <john.saunders at trizetto.comwrote in message news:uk**************@TK2MSFTNGP03.phx.gbl...
"Scott Holman" <sh*****@micros.comwrote in message news:OZ**************@TK2MSFTNGP03.phx.gbl...
Søren,

You should modify the proxy class (either directly or via a partial class declaration) and add a public constructor to Proxy.MyComplexClass that takes an instance of SomeNamespace.MyComplexClass. In the constructor you can initialize the properties based on the values of SomeNamespace.MyComplexClass. This will deal with web service methods that use MyComplexClass as an input parameter. If MyComplexClass is returned from the web service then you should add a public method on Proxy.MyComplexClass that will return SomeNamespace.MyComplexClass.
Scott, have you tried this before? I would be concerned about maintainability in terms of keeping the client in sync with the server. By giving the client knowledge of the server (i.e., the client now knows the actual class the server is using, as opposed to knowing the WSDL and proxy class), the two are now tightly coupled.

Again, .NET Remoting and WCF both address this scenario. "Standard" Web Services do not.
--

John Saunders [MVP]

Apr 27 '07 #7

P: n/a
"Scott Holman" <sh*****@micros.comwrote in message news:ud**************@TK2MSFTNGP06.phx.gbl...
As I interpreted the OP questions, the OP has a client side implementation of MyComplexClass. This implementation may or maynot be the same implementation on the server-side...it doesn't really matter. The OP needs to marshall the data in SomeNameSpace.MyComplexClass to the proxy class so that the proxy can marshall to the server. The OP could
1 - write a helper class such as
class foo
{
public static Proxy.MyComplexClass Bar(MyNameSpace.MyComplexClass value)
{
//Code to Initialize and return Proxy.MyComplexClass
}
}

2 - or...assuming that the code generated for Proxy.MyComplexClass is declared as a partial class...the OP could extend the proxy class in another file and implement the logic in 1 above in a constructor and leave the generated proxy class code unmodified. (This would seem to be exactly the situation called for by a partial class).

And to answer your question, yes I have done this with proxies generated by svcutil. In fact, I have even replaced a specific class within the proxy with my own implementation.

In reading the orignial post, it is likely that the OP is using the same implementation of MyComplexClass on both the client and server. This however does not result in a tightly coupled client and server. The client application still has to marshal data from the Proxy.MyComplexClass to the SomeNameSpace.MyComplexClass. The only coupling that exists is the coupling to the data contract as represented by Proxy.MyComplexClass and this coupling exists in all clients that consume the web service. However, the client and server implementation do have a physical coupling due to the shared assembly. The OP should realize that bugs in SomeNameSpace.MyComplexClass will require that both client and server be rebuilt and redistributed. The OP can minimize this by refactoring the class and 1) separating common logic and 2) separating the data representation from the business logic (for example: MyComplexClassData and MyComplexClassCommonLogic, MyComplexClassServerLogic, MyComplexClassClientLogic). Refactoring along these lines is more consistent with the Patterns and Practices guidance in the Web Service Software Factory.

Thanks, Scott, this puts your suggestion into perspective.

My concern was that the OP, like many, wanted the client and server to use the same exact class. You have correctly stated the difficulties this presents.

In addition, there will be a temptation to use other features of this class, so that the clients will come not only to depend on the data representation of the class, but on the methods etc. This is the coupling I warned about.
--
John Saunders [MVP]

Apr 27 '07 #8

This discussion thread is closed

Replies have been disabled for this discussion.