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:
- A request to the MVC action happens and a valid JSON result is handed back (as seen by FireBug NET console).
- The read function never gets called (checked with Firebug breakpoint and Console.Log message).
- … 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.