C # How can I return the base class in webservice

I have a Car class and a derivative of SportsCar: Car
Something like that:

public class Car { public int TopSpeed{ get; set; } } public class SportsCar : Car { public string GirlFriend { get; set; } } 

I have a web service with methods that return cars ie:

 [WebMethod] public Car GetCar() { return new Car() { TopSpeed = 100 }; } 

It returns:

 <Car> <TopSpeed>100</TopSpeed> </Car> 

I have another method that also returns such cars:

 [WebMethod] public Car GetMyCar() { Car mycar = new SportsCar() { GirlFriend = "JLo", TopSpeed = 300 }; return mycar; } 

It compiles everything and everything, but when I call, I get:
System.InvalidOperationException: An error occurred while generating an XML document. ---> System.InvalidOperationException: Type wsBaseDerived.SportsCar was not expected. Use the XmlInclude or SoapInclude attribute to indicate types that are not known statically.

It seems strange to me that he cannot serialize it as a direct car, since my car is a car.

Adding XmlInclude to WebMethod of our method fixes the error:

 [WebMethod] [XmlInclude(typeof(SportsCar))] public Car GetMyCar() { Car mycar = new SportsCar() { GirlFriend = "JLo", TopSpeed = 300 }; return mycar; } 

and now it returns:

 <Car xsi:type="SportsCar"> <TopSpeed>300</TopSpeed> <GirlFriend>JLo</GirlFriend> </Car> 

But I really want to return the base class, without additional properties, etc. from a derived class.

Is this possible without creating maps, etc.?

Say yes;)

+6
c # serialization web-services base
source share
7 answers

I would execute the copy constructor in the base class.

  public class Car { public int TopSpeed { get; set; } public Car(Car car) { TopSpeed = car.TopSpeed; } public Car() { TopSpeed = 100; } } public class SportsCar : Car { public string GirlFriend { get; set; } } 

You can then return the new SportsCar-based car in the GetMyCar method. I think this method clearly expresses the intention of the method.

  public Car GetMyCar() { var sportsCar = new SportsCar { GirlFriend = "JLo", TopSpeed = 300 }; return new Car(sportsCar); } 
+2
source share

Do it:

 [WebMethod] public Car GetMyCar() { Car mycar = new SportsCar() { GirlFriend = "JLo", TopSpeed = 300 }; return new Car() {TopSpeed = mycar.TopSpeed}; } 

The reason is because the XMLSerializer checks the type of the GetType () object and expects it to be the same as the declared one.

I know this is a pain, but I do not know an alternative.

+1
source share

Or use the XmlIgnoreAttribute attributes that you want to ignore. Or an even more painful way would be to implement custom serialization for your attributes.

Good luck.

 public class SportsCar : Car { [XmlIgnoreAttribute] public string GirlFriend { get; set; } } 
0
source share

Just a hit, but have you tried it? Throw on a refund.

 [WebMethod] public Car GetMyCar() { Car mycar = new SportsCar() { GirlFriend = "JLo", TopSpeed = 300 }; return (Car)mycar; } 
0
source share

Try WCF, [KnownType] exists.

I do not know, however, if this is possible using the oldskool SOAP web services.

0
source share

Other comments and answers here made me think, and if I need to create a Mapper method, let it be like this:

 public class Car: ICloneable { public int TopSpeed{ get; set; } public object Clone() { return new Car() { TopSpeed = this.TopSpeed }; } } 

and web method:

 [WebMethod] public Car GetMyNewCar() { Car mycar = new SportsCar() { GirlFriend = "HiLo", TopSpeed = 300 }; return (Car)mycar.Clone(); } 

This works as expected:

 <Car> <TopSpeed>300</TopSpeed> </Car> 

This defeats the goal of having a derived object in my view, but until someone comes up with another solution that I will fly ...

0
source share

If you want to always be serialized as "Car" instead of "SportsCar", add [XmlRoot("Car")] .

 public class Car { //stuff } [XmlRoot("Car")] public class SportsCar { //Sporty stuff } 

Edit: using XmlSerializer as follows:

 XmlSerializer ser = new XmlSerializer(typeof(SportsCar)); SportsCar car = new SportsCar() //stuff ser.Serialize(Console.out, car) 

you should get

 <Car> <TopSpeed>300</TopSpeed> <GirlFriend>JLo</GirlFriend> </Car> 
0
source share

All Articles