Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C# How can I return my base class in a webservice

I have a class Car and a derived SportsCar: Car
Something like this:

public class Car
{
    public int TopSpeed{ get; set; }
}


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

I have a webservice with methods returning Cars i.e:

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

It returns:

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

I have another method that also returns cars like this:

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

It compiles fine and everything, but when invoking it I get:
System.InvalidOperationException: There was an error generating the XML document. ---> System.InvalidOperationException: The type wsBaseDerived.SportsCar was not expected. Use the XmlInclude or SoapInclude attribute to specify types that are not known statically.

I find it strange that it can't serialize this as a straight car, as mycar is a car.

Adding XmlInclude on the WebMethod of ourse removes the error:

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

and it now returns:

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

But I really want the base class returned, without the extra properties etc from the derived class.

Is that at all possible without creating mappers etc?

Please say yes ;)

like image 383
HenriM Avatar asked May 12 '10 11:05

HenriM


2 Answers

I would implement a 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; }
    }

Then you can return a new Car based on the SportsCar in the GetMyCar-method. I think this way clearly express the intent of the method.

    public Car GetMyCar()
    {
        var sportsCar = new SportsCar { GirlFriend = "JLo", TopSpeed = 300 };
        return new Car(sportsCar);
    }
like image 82
Olsenius Avatar answered Oct 07 '22 14:10

Olsenius


Do this:

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

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

I know it's a pain but i don't know of an alternative.

like image 39
Adrian Zanescu Avatar answered Oct 07 '22 14:10

Adrian Zanescu