[GIS] OpenLayers2: Showing WKT data via JSON from MVC

jsonopenlayers-2well-known-text

I am trying to read geographic data from MS SQL Server 2012 and display it using the JavaScript library OpenLayers in an MVC4 view. I can confirm that the data leaves MVC OK but I have problem is getting the data to be processed by OpenLayers. I have tried two approaches:

a. using OpenLayers.Protocol.Script

b. using $.getJSON to read the data and adding using addfeatures.

Both fail for different reasons. I will describe the method using OpenLayers.Protocol.Script as it is the preferred method.

My MVC View looks like this:

<body onload="init()">
<h2>Open Layers - Two layer from SQL, Massive</h2>
<div id="map-canvas"></div>
</body>
@section scripts {
<script src="http://maps.google.com/maps/api/js?sensor=false"></script>
<script src="http://openlayers.org/api/OpenLayers.js"></script>

<script type="text/javascript">
    var map, layer1, layer1;

    function init() {
        var proj_4326 = new OpenLayers.Projection('EPSG:4326');
        var proj_900913 = new OpenLayers.Projection('EPSG:900913');
        map = new OpenLayers.Map({
            div: "map-canvas",
            projection: proj_900913,
            displayProjection: proj_4326,
            numZoomLevels: 21,
            maxExtent: new OpenLayers.Bounds(-20037508.34, -20037508.34, 20037508.34, 20037508.34)
        });

        var google_base_layer = new OpenLayers.Layer.Google("Google Streets", {
            sphericalMercator: true,
            baselayer: true
        });
        map.addLayer(google_base_layer);

        //Create an array of strategy objects
        var vector_strategies = [new OpenLayers.Strategy.Fixed()];

        var wktReader = new OpenLayers.Format.WKT();

        var layer1 = new OpenLayers.Layer.Vector("Layer 1", {
            projection: proj_4326,
            strategies: vector_strategies,
            protocol: new OpenLayers.Protocol.Script({
                url: "GetGeoLayerData",
                params: { layerId: 1 },
                format: new OpenLayers.Format.JSON({
                    read: function(json) {
                        var features = [];
                        $.each(json, function(i, item) {
                            var feature = wktReader.read(item.wktgeography);
                            feature.attributes = { value: item.value, info: item.info };
                            features.push(feature);
                        });
                        return features;
                    }
                })
            })
        });

        map.addLayer(layer1);

        // Add a layer switcher control
        map.addControl(new OpenLayers.Control.LayerSwitcher({}));

        if (!map.getCenter()) {
            map.zoomToMaxExtent();
        }
    }
</script>
}

And my MVC action that responds to the OpenLayers.Protocol.Script looks like this (note that the field 'Location' is of type DbGeography and .ToString() returns the WKT version of the geography). The service simply returns a IQueryable of type IGeoItem.

public JsonResult GetGeoLayerData( int layerId, IServiceGetSpecificList<IGeoItem, int> service)
    {
        var formattedData = service.GetSpecificList(layerId).Select(x => 
            new { wktgeography = x.Location.AsText(), value = x.Value, info = x.Info });
        return Json(formattedData, JsonRequestBehavior.AllowGet);
    }

What happens is:

  1. A request to the MVC action happens and a valid JSON result is handed back (as seen by FireBug NET console).
  2. The read function never gets called (checked with Firebug breakpoint and Console.Log message).
  3. … Therefore no vector features are added to layer1.

I would appreciate help on solving this as I have tried a number of approaches and none of them work. Maybe I have made a silly mistake but I can't see it.

UPDATE with solution:

Following the advice from cavila (see below) I have fixed this problem. The change was in the definition of the Vector layer protocol from Script to HTTP. I have included just that section of the view below in case it helps anyone else

var layer1 = new OpenLayers.Layer.Vector("Layer 1", {
    projection: proj_4326,
    strategies: vector_strategies,
    protocol: new OpenLayers.Protocol.HTTP({
        url: "GetGeoLayerData?layerId=1",
        format: new OpenLayers.Format.JSON({
            read: function(jsonp) {
                var features = [];
                $.each($.parseJSON(jsonp), function(i, item) {
                    var feature = wktReader.read(item.wktgeography);
                    feature.attributes = { value: item.value, info: item.info };
                    features.push(feature);
                });
                return features;
            }
        })
    })
});

Best Answer

The protocol OpenLayers.Protocol.Script is to be used with JSONP. I guess you missing the function to be called in responde with this protocol.

Replace it with OpenLayers.Protocol.HTTP.