Reputation: 2961
I have this scenario where a webservice method I'm consuming in C# returns a Business object, when calling the webservice method with the following code I get the exception "Unable to cast object of type ContactInfo to type ContactInfo" in the reference.cs class of the web reference
Code:
ContactInfo contactInfo = new ContactInfo();
Contact contact = new Contact();
contactInfo = contact.Load(this.ContactID.Value);
Any help would be much appreciated.
Upvotes: 6
Views: 12361
Reputation: 6782
Actually this is not a bug. It's a problem with the version changes of your own project! Because your final run don't use the original imported references on compile!
For example, I was making a chat server, client. I used a packet structure to transmit data on client project. Then imported the same reference to server project.
When casting Packet packet = (Packet)binaryFormatter.Deserialize(stream);
I got the same error. Because the actual running reference at server project is not the reference now at client project! Because I have rebuilt client project many times after!
In casting <new object>=(<new object>) <old object>
always the new object needs to be a newer or same version as the old object!
So what I did was I built a separate project to create a DLL for the Packet class and imported the DLL file to both projects.
If I did any change to Packet class, I have to import the reference to both client and server again.
Then the casting won't give the above exception!
Upvotes: 1
Reputation: 978
You can also modify your References.cs file generated by Visual Studio when the web reference is added. If you remove the proxy generated classes and add a reference (using statements) to your personal classes, you'll be able to use them straight away, without shallow copy / reflection or heavy mapping. (but you'll have to re-apply your modification if you regenerate the proxy layer).
I also tried to serialize the proxy object and deserialize them back in my DTO classes but it was quite heavy resources wise so I ended up modifying the References cs generated layer.
Hope it will help other people coming here :)
Kindly.
Upvotes: 0
Reputation: 42145
This is because one of the ContactInfo
objects is a web service proxy, and is in a different namespace.
It's a known problem with asmx-style web services. In the past I've implemented automatic shallow-copy to work around it (here's how, although if I were doing it again I'd probably look at AutoMapper instead).
For example, if you have an assembly with the following class:
MyProject.ContactInfo
and you return an instance of it from a web method:
public class DoSomethingService : System.Web.Services.WebService
{
public MyProject.ContactInfo GetContactInfo(int id)
{
// Code here...
}
}
Then when you add the web reference to your client project, you actually get this:
MyClientProject.DoSomethingService.ContactInfo
This means that if, in your client application, you call the web service to get a ContactInfo
, you have this situation:
namespace MyClientProject
{
public class MyClientClass
{
public void AskWebServiceForContactInfo()
{
using (var service = new DoSomethingService())
{
MyClientProject.DoSomethingService.ContactInfo contactInfo = service.GetContactInfo(1);
// ERROR: You can't cast this:
MyProject.ContactInfo localContactInfo = contactInfo;
}
}
}
}
It's on that last line that I use my ShallowCopy
class:
namespace MyClientProject
{
public class MyClientClass
{
public void AskWebServiceForContactInfo()
{
using (var service = new DoSomethingService())
{
MyClientProject.DoSomethingService.ContactInfo contactInfo = service.GetContactInfo(1);
// We actually get a new object here, of the correct namespace
MyProject.ContactInfo localContactInfo = ShallowCopy.Copy<MyClientProject.DoSomethingService.ContactInfo, MyProject.ContactInfo>(contactInfo);
}
}
}
}
NOTE
This only works because the proxy class and the "real" class have exactly the same properties (one is generated from the other by Visual Studio).
Upvotes: 11
Reputation: 20076
Seems like you have two different classes on both ends. Your application has ContactInfo class and your webservice also have the ContactInfo class. Both are two completely different classes. One way is to use the WebService class on your side. If you are using ContactInfo inside your web service then it will be serialized and will be available on the client side for use.
Upvotes: 0
Reputation: 6840
As several of the other answers have suggested, it is because .NET sees them as two different classes. I personally would recommend using something like AutoMapper. I've been using it, and it seems pretty awesome. You can copy your objects in 1-2 lines of code.
Mapper.CreateMap<SourceClass, DestinationClass>();
destinationInstance = Mapper.Map<SourceClass, DestinationClass>(sourceInstance);
Upvotes: 1
Reputation: 161781
This isn't a problem - it's a feature.
They are two independent classes. Compare the two, and notice that the proxy class has none of the constructors, methods, indexers, or other behavior from the original class. This is exactly the same thing that would happen if you consumed the ASMX service with a Java program.
Upvotes: 0
Reputation: 147381
How are you referencing the class in your web service project as well as consumer project? If you have simply used a file link, this could well explain the cause of the error. The way serialiasation works for .NET (Web Services or otherwise I believe) is by using reflection to load/dump the data of an object. If the files are simply linked, then they are actually getting compiled to different types in different assemblies, which would explain why you have the same name but can't cast between them. I recommend creating a 'Core' library which both the web service and consumer project references, and contains the ContactInfo
class which you use everywhere.
Upvotes: 0