How to return a KML content

2.5k views Asked by At

I'm trying to cook a web api that connects to my DB, fetch some geographical data, then returns a KML content that will be consumed by a webpage (displaying the info on a google maps iframe/div).

I'm using sharpKML (and I don't know if it's the right choice):

public class KmlController : ApiController
{
    public HttpResponseMessage Get()
    {
        Point point = new Point();
        point.Coordinate = new Vector(37.42052549, -122.0816695);

        Placemark placemark = new Placemark();
        placemark.Name = "Somewhere";
        placemark.Geometry = point;

        Kml kml = new Kml();
        kml.Feature = placemark;

        return Request.CreateResponse(HttpStatusCode.OK, kml, new XmlMediaTypeFormatter(), "application/vnd.google-earth.kml+xml");
    }
}

But when I call http://something.on.my.lan/api/kml I get this exception:

System.InvalidOperationException: The 'ObjectContent`1' type failed to serialize the response body for content type 'application/vnd.google-earth.kml+xml; charset=utf-8'.

What am I missing?

SOLUTION

Unfortunately, as said in this answer, even if I manage to create a KML content on the fly, it won't display on a map, because the URL must be publicly accessed by Google (for caching purposes). I have to change approach.

2

There are 2 answers

6
Dalorzo On

Try this first, I wonder if there is an issue with the serialization of any of the objects:

private string SerializeObject<T>(this T toSerialize)
{
    XmlSerializer xmlSerializer = new XmlSerializer(toSerialize.GetType());
    StringWriter textWriter = new StringWriter();

    xmlSerializer.Serialize(textWriter, toSerialize);
    return textWriter.ToString();
}


public class KmlController : ApiController
{
    public string Get()
    {
        Point point = new Point();
        point.Coordinate = new Vector(37.42052549, -122.0816695);

        Placemark placemark = new Placemark();
        placemark.Name = "Somewhere";
        placemark.Geometry = point;

        Kml kml = new Kml();
        kml.Feature = placemark;

        return SerializeObject<Kml>(kml);;
    }
}

If it fails I recommend you to refer to Serialization documentation so you can find which object is not serializing properly.

http://msdn.microsoft.com/en-us/library/system.serializableattribute.aspx

0
Jimbo On

This is working for me...

    public static byte[] SerializeKml(this KmlFile kml)
    {
        var serializer = new Serializer(); 
        serializer.Serialize(kml.Root); 
        var str = serializer.Xml;

        var bytes = new byte[str.Length * sizeof(char)];
        Buffer.BlockCopy(str.ToCharArray(), 0, bytes, 0, bytes.Length);
        return bytes;
    }

    public ActionResult GetKml()
    {
        Placemark placemark = new Placemark
        {
            Geometry = new Point { Coordinate = new Vector(-13.163959, -72.545992) },
            Name = "Machu Picchu",
        };

        var kml = KmlFile.Create(placemark, false);
        var fcResult = new FileContentResult(kml.SerializeKml(), "application/vnd.google-earth.kml+xml") { FileDownloadName = "MachuPicchu.kml" };
        return fcResult;
    }