Identify on WMS source

3025
6
09-09-2010 07:30 AM
MikeTischler
New Contributor II
hi,
I've made an ArcGIS service from a WMS service by loading it as an .mxd, and publishing that .mxd. 

If I run an identify task following the method in the samples on the ArcGIS service all I get back is a very long url string, rather than the normal identify results

Has anyone tried using an identify task this way?  I'm thinking about parsing the url for info, but I thought I'd see if anyone has run up against this before.
0 Kudos
6 Replies
MonikaOligschläger
New Contributor
Hi Mike,

that's funny, because I have the same problem. I don't have a solution until now, but an idea.
This text you got is the "xml-Format" but you need the "image-format". I have no clue, where you can fix this adjustment.

At work we use ArcGIS 10 - there I can see the information (in our case a html-document), but at another computer with a ArcGIS 9.2 Version we just get the .xml output.

In the Desktop help are some explaining topics like "using WMS service layers" and "communication with a WMS service in a web browser", but this is also not very helpful.

Therefore, I would be lucky too if somebody has an answer for us.

see you,

Monika
0 Kudos
MikeTischler
New Contributor II
Monika,
Thanks for your comments.

Actually, the very long url I get is not the response from the WMS server, but rather the "GetFeatureInfo" request url that the Silverlight API builds.  Some interesting notes...

If I copy the URL that and paste it into a browser...voila - I get the html response I expect from the ORIGINAL wms server...not ArcGIS server.

Using c# code behind to use the WebClient class to manually send the GetFeatureInfo request to the server doesn't work, because the WMS server I'm requesting from doesn't have a crossdomain.xml .

I may have a workaround that I'm cranking on this morning.  I can call a javascript function from the .html page for my silverlight application.  Using js I should be able to manually send the GetFeatureInfo request to the WMS server, and get a response back.  I'm using Fiddler to track my http traffic, and I'm very nearly there.
0 Kudos
MikeTischler
New Contributor II
I gave up on this, but would love to see if anyone has any suggestions.

I did figure out a way to hit a WMS server directly with a GetFeatureInfo request within SL, and get hold of the response.  This required a js function (to make the WMS request, and pass the response back to SL) called from within the code-behind in SL.  From there, I got pretty close to parsing the response back directly...but I'm running out of time.  So, I'll have to bag using the identify task on WMS layers being served through ArcGIS server.  If anyone's interested, here's the code I used to hit the WMS server.

in Default.html
function getfeatureinfo(myurl)
  
  //for this to work in firefox, enter about:config in the URL bar and change signed.applets.codebase_principal_support to true
  {
  var req = false;
  req = new ajaxRequest();
  
  try {
            netscape.security.PrivilegeManager.enablePrivilege("UniversalBrowserRead");
         } catch (e) {
            alert("Permission could be denied for cross-browser scripting.");
        }
  if (req){
  
  }
  else {
  
  }
  
  req.open('GET', myurl,false);
  
     req.send();
  if(req.status == 200)  
   
   
   return req.responseText;
  } 
  function ajaxRequest(){
   var activexmodes=["Msxml2.XMLHTTP", "Microsoft.XMLHTTP"] //activeX versions to check for in IE
   if (window.ActiveXObject){ //Test for support for ActiveXObject in IE first (as XMLHttpRequest in IE7 is broken)
    for (var i=0; i<activexmodes.length; i++){
     try{
     return new ActiveXObject(activexmodes)
     }
     catch(e){
     //suppress error
     }
   }
  }
   else if (window.XMLHttpRequest) // if Mozilla, Safari etc
    return new XMLHttpRequest()
  else
    return false
  }


And following the Identify SL example at http://help.arcgis.com/en/webapi/silverlight/samples/start.htm#Identify inside Mainpage.xaml.cs in the ShowFeature function

    foreach (IdentifyResult result in results)
                {
     
                    Graphic feature = result.Feature;
     htmlreq = feature.Attributes["URL"].ToString();
     htmlmarkup = (string)HtmlPage.Window.Invoke("getfeatureinfo",htmlreq);
     
     
     
                    string title = result.Value.ToString() + " (" + result.LayerName + ")";
     IdentifyComboBox.Items.Add(title);
                    _dataItems.Add(new DataItem()
                    { 


I messed with changing the INFO_FORMAT of the request from the default of "text/html" to "text/Plain" and "text/xml", to see which was easier for me to work with. 

But, in the end, trying to parse the results from this request turned out to be too much for me - at least in my timeframe.

But, I did successfully figure out a way to hit a WMS server directly using SL and JS, though it wasn't terribly easy.

Thanks!
0 Kudos
dotMorten_esri
Esri Notable Contributor
Cool!

"I did figure out a way to hit a WMS server directly with a GetFeatureInfo request within SL, and get hold of the response"
Another approach than using JavaScript (which might be blocked on some computers) is to use a proxy hosted on the same domain as the .xap file.
0 Kudos
MikeTischler
New Contributor II
Thanks!

Any word on whether or not the next version of Silverlight API will handle WMS GetFeatureInfo requests?  Or will we be limited to only displaying, and not querying/identifying?

Thanks,
Mike
0 Kudos
MikeTischler
New Contributor II
I gave it another go, and I was able to come up with a good solution!

Basically, I followed the code above to use js to send/receive the WMS GetFeatureInfo query.  I used "INFO_FORMAT=text/xml", and wrote a function in csharp to parse the results and add it to the datagrid.

private void GetDataFromXml(IdentifyResult result, string xmlmarkup)
  {
   XmlReader reader = XmlReader.Create(new StringReader(xmlmarkup));
  
   int i = -1;
   while (reader.Read())
                {
                    switch (reader.NodeType)
                    {
                        case XmlNodeType.Element: // The node is an element.
       
                           
       IDictionary<string,object> featureatts = new Dictionary<string,object>();
                            while (reader.MoveToNextAttribute())
       {// Read the attributes.
 
        featureatts.Add(reader.Name,reader.Value);
       }
       i+=1;
       adddataitems(i,result,featureatts);
       
                            break;
                        case XmlNodeType.Text:
                            break;
                        case XmlNodeType.EndElement:
                            break;
                    }
                }
  }
  public void adddataitems(int i, IdentifyResult result, IDictionary<string,object> featureatts)
  {
   if (featureatts.Count > 0)
   {
         string title = result.Value.ToString() + "_" + i +  " (" + result.LayerName + ")";
     IdentifyComboBox.Items.Add(title);
                    _dataItems.Add(new DataItem()
                    { 
      
                        Title = title,
      Data=featureatts
                    });
   }
  }
  
  public void ShowFeatures(List<IdentifyResult> results)
        {
            _dataItems = new List<DataItem>();

            if (results != null && results.Count > 0)
            {
                IdentifyComboBox.Items.Clear();

    string htmlreq = "";
    string xmlreq = "";
    string xmlmarkup = "";
    
    foreach (IdentifyResult result in results)
                {
                    Graphic feature = result.Feature;
     if (result.Value.ToString().IndexOf("WMS") >= 0)
     {
      htmlreq = feature.Attributes["URL"].ToString();
      xmlreq = htmlreq.Replace("INFO_FORMAT=text/html","INFO_FORMAT=text/xml");
      xmlmarkup = (string)HtmlPage.Window.Invoke("getfeatureinfo",xmlreq);
      GetDataFromXml(result,xmlmarkup);
     }
     else
     {
                     string title = result.Value.ToString() + " (" + result.LayerName + ")";
      IdentifyComboBox.Items.Add(title);
                     _dataItems.Add(new DataItem()
                    { 
                        Title = title,
      Data=feature.Attributes
                    });
     } 
                }
                IdentifyComboBox.SelectedIndex = 0;
            }
        }


I'm sure this could be beefed up, but it works for now.  My goal was to handle Identify requests to both ArcGIS Server and WMS layers, with the output presented in the same way for each type of layer.  This code does that, at least on my system. 

Caution: One headache - Firefox users...in order to use the js and overcome the crossdomain problem, you must enter about:config in the URL bar and change signed.applets.codebase_principal_support to true.  I'm not entirely sure how this affects Firefox, so buyer beware.  I do believe this alters the proxy settings in FF.  I had to repeatedly change them in Tools->Options->Advanced, Network Tab in Firefox.  The default is to use system proxy settings, but I believe this code (something definitely was...not sure of the culprit) was changing to a manual proxy configuration, which kills many other webpages.

Hope this is of use

Mike
0 Kudos