c# - How to process layer templates using mapscript to respond to a WMS GetFeatureInfo request -
i'm trying handle getfeaturinfo wms requests using c# mapscript. prior using mapscript our software passed wms requests through cgi mapserver hosted on iis. processed html template associated each queried layer , substituted number of tokens within template data.
we cannot use mapserver cgi implementation i'm attempting reimplement mechanism using mapscript via c# mapscript mechanism.
the summary of code have far here. problem call processquerytemplate causes accessviolation exception thrown.
public string getfeatureinfofromwms(namevaluecollection wmsquerystring) { //set projection library environment variable used mapscript.dll environment.setenvironmentvariable("proj_lib", projectionlibrarypath); string output = string.empty; try { using (mapobj map = new mapobj(mapfile)) { //add aditional layer specific params - ie location of plugins etc processlayers(map, wmsquerystring); map.web.metadata.set("wms_onlineresource", wmsonlineresourceurl); string xval = wmsquerystring["x"]; string yval = wmsquerystring["y"]; if (xval == null || yval == null) { throw new argumentnullexception("the x or y point value has not been suppplied in getfeatureinfo request"); } double pointx = 0.0; double pointy = 0.0; try { pointx = convert.todouble(xval); pointy = convert.todouble(yval); } catch (exception e) { throw new argumentexception("the x or y point value supplied in getfeatureinfo request not valid decimal",e); } string layersqs = wmsquerystring["query_layers"]; if (layersqs == null) { throw new argumentnullexception("the query_layers parameter of wms getfeatureinfo request not specified correctly"); } //load parameters wms request map using (owsrequest request = new owsrequest()) { (int = 0; < wmsquerystring.count; i++) { request.setparameter(wmsquerystring.getkey(i), wmsquerystring.get(i)); } string wmsversion = wmsquerystring["version"]; if (wmsversion == null || wmsversion == string.empty) wmsversion = default_wms_version; map.loadowsparameters(request, wmsversion); } //reproject x & y pixel co-ordinates in map co-ordintes. double minx = map.extent.minx; double maxx = map.extent.maxx; double geox = minx + ((pointx / (double)map.width) * (maxx - minx)); double miny = map.extent.miny; double maxy = map.extent.maxy; double geoy = maxy - ((pointy / (double)map.height) * (maxy - miny)); string[] querylayers = layersqs.split(','); using (pointobj point = new pointobj(geox, geoy, 0, 0)) { foreach (string layername in querylayers) { using (layerobj layer = map.getlayerbyname(layername)) { int queryresult = layer.querybypoint(map, point, (int)ms_query_mode.ms_query_single, -1); } } } map.preparequery(); string[] names = { "token1" }; string[] values = { "value1" }; //bang!!!!!! output = map.processquerytemplate(names, values, 10); } return output; } catch (exception ex) { throw; } }
the associated map file follows:
map # # start of map file # name esdm status on templatepattern "." size 400 600 units meters extent 0 0 800000 1200000 imagecolor 255 255 255 fontset fonts.txt #debug on imagetype png projection "init=epsg:27700" end outputformat name "png" driver "gd/png" imagemode rgba mimetype image/png extension png transparent on end # outputformat # name "imagemap" # mimetype text/html; driver=imagemap # driver "imagemap" # end # # start of web interface definition (including wms enabling metadata) # web metadata "wms_title" "sql mapping data" "wms_srs" "epsg:27700 epsg:4326 epsg:54004 epsg:54005 epsg:900913" "wms_feature_info_mime_type" "text/plain" "wms_include_items" "all" end end include "mapsymbols.inc" # barsactions point layer #----------------------------------------------------------------------------------------- layer name "actions" maxscaledenom 100000000 minscaledenom 0 metadata "wms_title" "barsactions" "wfs_title" "barsactions" "wms_srs" "epsg:27700" end connectiontype plugin plugin "sqlplugin" data "geom maploadtest using unique actionid using srid=27700" filter "(orgunitid = 1 , %actionstatusid% , %actiontypeid% , %areaidst(geom)%)" type point status on tolerance 50 template "barstemplate.htm" class color 0 0 255 outlinecolor 0 0 0 symbol 'star' size 15 #maxsize 6 #minsize 3 end # end of class object projection "init=epsg:27700" end dump true end # end of layer object # barsactions polygon layer #----------------------------------------------------------------------------------------- layer name "actionspolygons" maxscaledenom 100000000 minscaledenom 0 metadata "wms_title" "barsactionspolygons" "wfs_title" "barsactionspolygons" "wms_srs" "epsg:27700" end connectiontype plugin plugin "sqlplugin" data "geom maploadtest using unique actionid using srid=27700" filter "(orgunitid = 2 , actionid = 200 , %actionstatusid% , %actiontypeid% , %areaidst(geom)%)" type polygon status on tolerance 50 template "barstemplate.htm" class color 0 0 255 outlinecolor 0 0 0 end # end of class object projection "init=epsg:27700" end dump true end # end of layer object end # map file
various items in map file tokenised (ie sql plugin location , filters applied data) handled call processlayers in previous method. mechanism doesn't appear cause problems when drawing maps. call querybypoint works. returns success , query run against sql db returns expected data.
i'm unsure proceed here , else needs done produce output templates. expecting call processquerytemplate return populated templetes. don't quite know preparequery supposed do.
cheers
never figured out how templates work. managed database id's of shapes returned query. use these prepare html result elsewhere.
note i'm using map.querybypoint deal situations there layer groups (in case layergroup name come across layer name in wms request.
/// <summary> /// handles getfeature info request , returns matching actionid's. /// </summary> /// <param name="wmsquerystring">the wm squery string.</param> /// <returns>a list of matching action id's.</returns> /// <exception cref="argumentnullexception">thrown if x or y point values not supplied in wms getfeatureinfo request</exception> /// <exception cref="argumentexception">thrown in x or y point values supplied in wms getfeatureinfo request cannot converted valid doubles</exception> public list<int> getfeatureinfoactionid(namevaluecollection wmsquerystring) { //set projection library environment variable used mapscript.dll environment.setenvironmentvariable("proj_lib", projectionlibrarypath); try { list<int> resultslist = new list<int>(); using (mapobj map = new mapobj(mapfile)) { processlayers(map, wmsquerystring); map.web.metadata.set("wms_onlineresource", wmsonlineresourceurl); //load parameters wms request map using (owsrequest request = new owsrequest()) { (int = 0; < wmsquerystring.count; i++) { request.setparameter(wmsquerystring.getkey(i), wmsquerystring.get(i)); } string wmsversion = wmsquerystring["version"]; if (wmsversion == null || wmsversion == string.empty) wmsversion = default_wms_version; map.loadowsparameters(request, wmsversion); } string xval = wmsquerystring["x"]; string yval = wmsquerystring["y"]; if (xval == null || yval == null) { throw new argumentnullexception("the x or y point value has not been suppplied in getfeatureinfo request"); } double pointx = 0.0; double pointy = 0.0; try { pointx = convert.todouble(xval); pointy = convert.todouble(yval); } catch (exception e) { throw new argumentexception("the x or y point value supplied in getfeatureinfo request not valid decimal",e); } //reproject x & y pixel co-ordinates in map co-ordintes. double minx = map.extent.minx; double maxx = map.extent.maxx; double geox = minx + ((pointx / (double)map.width) * (maxx - minx)); double miny = map.extent.miny; double maxy = map.extent.maxy; double geoy = maxy - ((pointy / (double)map.height) * (maxy - miny)); ms_return_value queryresult; using (pointobj point = new pointobj(geox, geoy, 0, 0)) { queryresult = (ms_return_value)map.querybypoint(point, (int)ms_query_mode.ms_query_multiple, -1); } if (queryresult != ms_return_value.ms_success) { return null; } map.preparequery(); (int layerindex = 0; layerindex < map.numlayers; layerindex++) { using (layerobj layer = map.getlayer(layerindex)) { int resultcount = layer.getnumresults(); if (resultcount > 0) { layer.open(); (int resultindex = 0; resultindex < resultcount; resultindex++) { using (resultcachememberobj resultcache = layer.getresult(resultindex)) { int actionid = resultcache.shapeindex; if (actionid != 0 && resultslist.contains(actionid) == false) { resultslist.add(actionid); } } } layer.close(); } } } } return resultslist; } catch (exception ex) { throw; } }
Comments
Post a Comment