Hi group,
I am having a web service which returns an array of type custom object.
The custom class is defined in a Class Library that is included in the
web-service project.
The same class lib is included in the ASP.NET Web Application that calls the
web-method.
it gives type cast error when i try to call the web method of my webservice.
Cannot implicitly convert type 'wsMyProjectName.Employee[] to 'MyProjectName.Domain.Employee[]'
i think the problem is What the web method is returning is a
proxy-type, and not the type that web service originally returned.
i am using vs.net 2005 and this happens while i am doing this through adding web reference.
I tried creating proxy class using wsdl.exe manually and used that also but it gives different eror in some of the methods in my presentation layer
Any help in this regard would be greatly appreciated.
thanks,
Nikhil.

Web Method returns array of custom type : casting error
Ggreg
you say "The purpose of web services is to expose business logic", and I'm sure that is true, but as is often the case when designing a multi-tiered system, the client UI generated layer often must have efficient and fast access to some of the business logic in order to produce the UI. This could be so it can do local validation; so it can display something in a special format; so a specific set of calculations can be done for display purposes.
This is all business logic, but if it had to be accessed thru the web service would be incredibly slow and wire-inefficient (sending duplicat data).
So, typically in a multi-tiered, thick client system the business entity objects have this type of business logic encapsulated within them and are available for use in the client, creating a fast and efficient client.
If I could use my own deserialisation at the client, so I can deserialise the objects back into their original types then I could do this, as the types passed as parameters have this sort of display/calculation/local validation logic.
sarc Development
David,
Actually no marshalling technology is going to solve this one for you. To be honest this is more of an architectural issue than technology.
Entities represent data and operations or methods 'operate' on entities. Object Orientation advocates that you separate your entities and operations. Entities expose operations on self only if they are self describing. Heres my question: Why do you need the server to send the 'operation' down to the client The 'server' or 'client' should only know about the operation if it is going to perform it. See the pseudo code below.
class Server
{
SomeEntity getEntity(parms)
{
//perform server logic here but return only data. Logic here applies to all entities irrespective of client. Clients are only interested in result.
// the data is my server contract. This is also the entity service boundary.
return new SomeEntity();
}
}
class Client
{
void performSomeBusinessFunctionOnEntity()
{
Server service = new Server();
Server.SomeEntity myBusinessData = service.getEntity(parms);
//we have the business data now perform client specific operation
myBusinessLogicSpecifictotheClient(myBusinessData);
}
void myBusinessLogicSpecifictotheClient(Server.SomeEntity parms) // note that the entity is described on the server.
{
//client specific logic.
}
}
This keeps your server 'abstracted' of client specific logic and your clients 'agnostic' of central entity specific logic. I.e. the server doesnt care what the client does. The client cares what the server does (which is described in the contract) but doesnt care how.
This is the kind of pattern that most marhsalling technologies (especially webservices) are meant to solve. Having said that, remoting probably comes close to doing what you want. Remoted services return a transparent proxy i.e. a copy of the data. However since you have a copy of the metaData (data describing the data) on the client side, you can 'create' a self describing entity on the client. But note that its still a copy of the data in the entity that is sent over the wire, not the entity itself. Which means that operations 'in' the entity that describe it are performed on the server!! and the results marshalled back to the client. If you need the operations local to the client (in remoting its an illusion performed using mirrors) the above pattern still applies. And rightly so, if you find the need to actually share self describing entities across clients (which is what you seem to be trying to do) then the Service should describe the entity and its operations in its contract. That way you get a central place for all your logic and also provides scalability, resiliency etc.
I hope this has been of help to you. Happy coding!
Cheerio!
Ramesh_Kumar_02a072
David,
The purpose of web services is to expose business logic, often around complex entities. In your case the entity (object) should be abstracted from this business logic. Define a serializable class/complex type. The functions providing business logic should be on the web service. If the functions are local then they should normally operate on a XML contract or on a mapped type.
eg:
public class MyComplexType
{
prop1;
prop2;
}
public class MyWebService : WebService
{
[WebMethod]
public MyComplexType MyBusinessFunction(string someParam)
{
}
[WebMethod]
public bool MyBusinessFunction1(MyComplexType complexType) {}
}
Hope this helps!
thukralz
MMCool
Could you explain a little more.
What is the best practice for converting a complex type or proxy complex type to a business logic object explicit/implicit cast, Adaptor pattern or other.
What do you mean by "...should normally operate on a XML contract or on a mapped type."
Adding on to your example, using an explicit cast is this good practice
public class MyType
{
prop1
prop2
MyBusinessFunction
MyBusinessFunction1
static explicit operator MyType(MyComplexType rhs)
static explicit operator MyComplexType(MyType rhs)
}
[WebMethod]
public MyComplexType MyBusinessFunction(string someParam)
{
MyClass myClass = new MyClass();
myClass.MyBusinessFunction(someParam);
return (MyComplexType)myClass;
}
[WebMethod]
public bool MyBusinessFunction1(MyComplexType complexType)
{
MyClass myClass = (MyClass)complexType;
myClass.MyBusinessFunction1()
}
shahidferoz
agreed, I could certainly serialize using my BO type, send the xml, and de-serialize to the same BO type, but as you say, type safety could be an issue. But there are mechanisms to address versioning, etc in serialization.
Its just a shame that the web service itself (well the .NET implementation anyway) cant handle all that for me...I think I'm getting lazy now so much plumbing code is written for us ;-)
I see what you are saying about contract, as the proxy type is defined by the web service contract, just as fields I guess, but it has no way of defining a contract in terms of fields+business logic. which is why I would need a DIY approach.
still, just cos web services are a great way of exposing business services and logic to the outside world doesnt mean that is the only way they can be used. In my case I am using them as simply a communication mechanism between a client and a server that both have intimate knowledge of one-another - perhaps remoting over http might be more appropriate for my purposes.
I'm not sure if remoting might have the same limitations, in the case when a method of a remote class returns a type, does it just return a proxy again. Oh no, it'll return a remote instance wont it, so that doesnt help me either, unless there is some way to specify whether it serialises and de-serialises the returned type so I have a real copy (ie not a proxy) locally and can use the business logic etc.
DrOats
Just seen this response that matches a problem I'm having too (cast problem with returning a complex type from a webservice)
However, I'd quite like to use my actual class from my class lib, which is serialisable, and has several methods that provide business logic on the data returned.
is there anyway to do this, or is it, as I suspect, just "wrong".
I should perhaps define a seperate class for the interface, pass that accross and then load that into my complex type defined in my class lib and have it then do the business logic.
Dvlnblk
Xml Serialization is native to webservices and the cost of serialization is the same whether you do it or rely on the webservice native interface. However what you have a problem with is basic type safety. A custom type in a webservice over the contract is not the same as the type copied to the other side. The custom type will be 'exposed' in the webservice contract and clients will have to refer to the same for type safety. If you want to serialize your documents manually into a custom type consider sending an string or XmlDocument into/out of the web service method. Use the XmlSerializer to serialize to and from a stream. However the cost of serialization is going to be the same (if not more due to custom Stream to XmlDocument/String operations and added encoding complexities.).
You also lose type safety as the contract is no longer well defined. (there is no way for a arbitrary client to know what the return 'type' is going to be. You can do some clever stuff with reflection (see web service factories) however this is more expensive than native serialization). In this case you should also consider merging the two layers together. The tradeoff is scalability of the 2nd tier with performance, ease of development and maintenance, which in your case seems more important anyways. WebServices are rather inefficient as a marshalling technology. They are mainly meant to be used to define well formed contracts for 'multiple' clients.
Xelestial
You dont need to share an assembly with your shared type. When you put a custom type in a WebMethod it will be exposed as a WSDL complex type. This will be created in the proxy that is generated when you reference the webservice on the client side. You need to use that as it is a Xml Serialization class. Your custom class in the shared assembly most probably isnt.
localhost.MyService service = new MyService();
localhost.MyCustomReturnType[] custom = service.GetCustomTypeArray();