I haven't quite tamped-down this issue, but I'm having trouble piping-in a SQL-sourced, secured layer into my map. Here's the code snippet:
featureLayer = FeatureLayer(this._objLayers.MyLayer.attColl.URL.val, { id: 'myLayer', mode: FeatureLayer.MODE_ONDEMAND, infoTemplate: popupTemplate, outFields: ["field1", "field2", "field3", "field4", "FOOBAR", "field6"] });
I've found that if I remove the column [FOOBAR], it seems to be added to the map without issue. If I add [FOOBAR], the map doesn't load anything at the normal, starting extent. No errors are reported in console - fiddler just shows an open request (no response). If I zoom-in and reduce extent, some features begin to show, but console reports the message:
dojo.io.script error CancelError: Request canceled "dojo.io.script error" { [functions]: , description: "Request canceled", dojoType: "cancel", log: undefined, message: "Request canceled", name: "CancelError", response: { }, stack: undefined }
I tried debugging the proxy, but found nothing constructive - my assumption was that there were either unsafe chars, or maybe a length issue with the return. The latter didn't make sense, though, since the proxy should handle large requests.
As a test, I adjusted the data in the SQL back-end and hard-coded a text value maxing-out the column width. This was piped-in without issue, so I'm beginning to think the proxy is rejecting some unsafe chars.
Has anyone had a similar experience? I'm using the latest release version of the proxy from GitHub (1.1.0).
Solved! Go to Solution.
Ok, I think I've resolved it, for now at least. Probably not the best idea, but, if I hardcode encoding in fetchAndPassBackToClient(), everything works!
using (StreamReader sr = new StreamReader(byteStream))
becomes...
using (StreamReader sr = new StreamReader(byteStream, Encoding.GetEncoding(28591)))
Here's the full method:
private bool fetchAndPassBackToClient(System.Net.WebResponse serverResponse, HttpResponse clientResponse, bool ignoreAuthenticationErrors) { //System.Net.HttpWebResponse serverResponseAux = null; //var req = (HttpWebRequest)WebRequest.Create(serverResponse.ResponseUri); //serverResponseAux = (System.Net.HttpWebResponse)req.GetResponse(); if (serverResponse != null) { using (Stream byteStream = serverResponse.GetResponseStream()) { // Text response if (serverResponse.ContentType.Contains("text") || serverResponse.ContentType.Contains("json") || serverResponse.ContentType.Contains("xml")) { using (StreamReader sr = new StreamReader(byteStream, Encoding.GetEncoding(28591))) //using (StreamReader sr = new StreamReader(byteStream, Encoding.GetEncoding(serverResponseAux.CharacterSet))) //using (StreamReader sr = new StreamReader(byteStream)) { string strResponse = sr.ReadToEnd(); if ( !ignoreAuthenticationErrors && strResponse.Contains("error") && (strResponse.Contains("\"code\": 498") || strResponse.Contains("\"code\": 499") || strResponse.Contains("\"code\":498") || strResponse.Contains("\"code\":499")) ) return true; //Copy the header info and the content to the reponse to client copyHeaders(serverResponse, clientResponse); clientResponse.Write(strResponse); } } else { // Binary response (image, lyr file, other binary file) //Copy the header info to the reponse to client copyHeaders(serverResponse, clientResponse); // Tell client not to cache the image since it's dynamic clientResponse.CacheControl = "no-cache"; byte[] buffer = new byte[32768]; int read; while ((read = byteStream.Read(buffer, 0, buffer.Length)) > 0) { clientResponse.OutputStream.Write(buffer, 0, read); } clientResponse.OutputStream.Close(); } serverResponse.Close(); } } return false; }
I suppose I'll mark this as the answer - if anyone has any better ideas, let me know!
One thing to keep in mind if you're debugging proxy logs - unless it's an error, you will need to configure logLevel in the proxy.config - I don't think this is documented, at least I couldn't see it here: resource-proxy/README.md at master · Esri/resource-proxy · GitHub
This should be using .NET trace, so the enums will be honored:
Error - Output error-handling messages.
Info - Output informational messages, warnings, and error-handling messages.
Off - Output no tracing and debugging messages.
Verbose - Output all debugging and tracing messages.
Warning - Output warnings and error-handling messages.
https://msdn.microsoft.com/en-us/library/system.diagnostics.tracelevel(v=vs.110).aspx
E.g.:
<ProxyConfig allowedReferers="*" mustMatch="true" logFile="proxylog.txt" logLevel="Info"> </ProxyConfig>
If you are having trouble allowing ASP.NET to write the log files, try this following the guide here:
I was successful in giving full control of my local build's proxy folder to IIS_IUSRS on my local machine. I'm still having trouble figuring this out, but it seems almost certain that it's some encoding or unsafe chars issue...
I had a chance to look more into this - it seems to be an issue with special chars... I'm not sure it's even a proxy issue, but, so far, I've found the request cancels as soon as the following chars are encountered:
*
#
•
¢
é
I have a PowerShell script I'm using to create a list of unique chars so I can debug easier:
$letters = @{} ; gc file.txt | select -Skip 2 | % { $_.ToCharArray() } | % { $letters[$_] = $true } ; $letters.Keys
I'm going through the list now and testing suspect chars - there's about 50 of them, unfortunately.
UPDATE:
Adding link to QueryTask.ExecuteAsync() /w Special Characters
Just to isolate this a bit more, I tried loading a static (from a shapefile), secured map service requiring the proxy - the same encoding issue occurred, so it doesn't appear to be an SQL oddity. I then removed security on the SQL-based map service and removed the proxy rule in my mapping application - the layer loads without issue.
It appears there is some evidence that it is an encoding/decoding bug within the proxy - just need to isolate where.
Ok, I think I've resolved it, for now at least. Probably not the best idea, but, if I hardcode encoding in fetchAndPassBackToClient(), everything works!
using (StreamReader sr = new StreamReader(byteStream))
becomes...
using (StreamReader sr = new StreamReader(byteStream, Encoding.GetEncoding(28591)))
Here's the full method:
private bool fetchAndPassBackToClient(System.Net.WebResponse serverResponse, HttpResponse clientResponse, bool ignoreAuthenticationErrors) { //System.Net.HttpWebResponse serverResponseAux = null; //var req = (HttpWebRequest)WebRequest.Create(serverResponse.ResponseUri); //serverResponseAux = (System.Net.HttpWebResponse)req.GetResponse(); if (serverResponse != null) { using (Stream byteStream = serverResponse.GetResponseStream()) { // Text response if (serverResponse.ContentType.Contains("text") || serverResponse.ContentType.Contains("json") || serverResponse.ContentType.Contains("xml")) { using (StreamReader sr = new StreamReader(byteStream, Encoding.GetEncoding(28591))) //using (StreamReader sr = new StreamReader(byteStream, Encoding.GetEncoding(serverResponseAux.CharacterSet))) //using (StreamReader sr = new StreamReader(byteStream)) { string strResponse = sr.ReadToEnd(); if ( !ignoreAuthenticationErrors && strResponse.Contains("error") && (strResponse.Contains("\"code\": 498") || strResponse.Contains("\"code\": 499") || strResponse.Contains("\"code\":498") || strResponse.Contains("\"code\":499")) ) return true; //Copy the header info and the content to the reponse to client copyHeaders(serverResponse, clientResponse); clientResponse.Write(strResponse); } } else { // Binary response (image, lyr file, other binary file) //Copy the header info to the reponse to client copyHeaders(serverResponse, clientResponse); // Tell client not to cache the image since it's dynamic clientResponse.CacheControl = "no-cache"; byte[] buffer = new byte[32768]; int read; while ((read = byteStream.Read(buffer, 0, buffer.Length)) > 0) { clientResponse.OutputStream.Write(buffer, 0, read); } clientResponse.OutputStream.Close(); } serverResponse.Close(); } } return false; }
I suppose I'll mark this as the answer - if anyone has any better ideas, let me know!
The encoding addition doesn't fix it for me. I'm also using latest DotNet proxy (1.1.0), along with IE 11 + JS API 3.17 + ArcGIS 10.22. The cancel error is caused by either of the following, specifically due to interrupting the map redrawing, as the response url points to the "export" task ( "/...proxy.ashx?http://myserver.domain/..../MapServer/export?")
1) Using LayerDrawingOptions on a dynamic map service to render a layer with a custom symbol
drawingOptions.renderer = new SimpleRenderer(polygonSymbol); optionsArray[0] = drawingOptions; app.myMapServiceLayer.setLayerDrawingOptions(optionsArray);
2) Using LayerDrawingOptions with LabelClass on multiple layers within a dynamic map service
var drawingOptionsLabelClass = new LayerDrawingOptions(); var labelClass = new LabelClass({ labelExpression: '[my_field_name]', labelPlacement: 'above-center', symbol: labelSymbol }); drawingOptionsLabelClass.labelingInfo = [labelClass]; drawingOptionsLabelClass.showLabels = true; optionsArray[1] = drawingOptionsLabelClass; optionsArray[2] = drawingOptionsLabelClass; app.SomeOtherMapServiceLayer.setLayerDrawingOptions(optionsArray);
No cancel errors are displayed when only applying LabelClass against one layer.
Not expecting help, just thought I'd point this out. There may be no way to eliminate the console message because I suspect it's a case where the ESRI JS API's deferreds are being cancelled and "cancel error" is the generic catch all message.
From DoJo documentation:
dojo/errors/CancelError is the default error if a promise is canceled without a reason