ArcGIS JSAPI Print/Validation Issue: SyntaxError: Unexpected token <

1783
7
Jump to solution
04-21-2017 10:22 AM
ChrisSmith7
Frequent Contributor

Here's what I'm using:

JSAPI v3.20

ArcGIS Server 10.3

ASP.NET Proxy 1.1.0

ASP.NET 4.0

I am having an issue when printing a map using Print (Print | API Reference | ArcGIS API for JavaScript 3.20 ). This occurs only after entering an address into the Search widget, and then plotting the result - the request is blocked during any export attempt after this action.

The issue "Unexpected token <" results from the API expecting a JSON response, but getting an HTML page... the page in question is a custom error page capturing a Microsoft validation issue with "potentially dangerous content". Here's the request going through Fiddler:

{
 "mapOptions": {
 "showAttribution": false,
 "extent": {
 "xmin": -9758929.205244847,
 "ymin": 5153837.351343746,
 "xmax": -9757291.78077969,
 "ymax": 5155062.73245334,
 "spatialReference": {
 "wkid": 102100,
 "latestWkid": 3857
 }
 },
 "spatialReference": {
 "wkid": 102100,
 "latestWkid": 3857
 },
 "scale": 4513.98870499674
 },
 "operationalLayers": [{
 "id": "layer0",
 "title": "layer0",
 "opacity": 1,
 "minScale": 591657527.591555,
 "maxScale": 70.5310735,
 "url": "https://services.arcgisonline.com/ArcGIS/rest/services/Canvas/World_Light_Gray_Base/MapServer"
 },
 {
 "id": "map_graphics",
 "opacity": 1,
 "minScale": 0,
 "maxScale": 0,
 "featureCollection": {
 "layers": [{
 "layerDefinition": {
 "name": "pointLayer",
 "geometryType": "esriGeometryPoint"
 },
 "featureSet": {
 "geometryType": "esriGeometryPoint",
 "features": [{
 "geometry": {
 "x": -9758110.34234326,
 "y": 5154449.96419052,
 "spatialReference": {
 "wkid": 102100,
 "latestWkid": 3857
 }
 },
 "attributes": {
 "Addr_type": "StreetName",
 "Match_addr": "Main Ave, Chicago, Illinois, 60613",
 "StAddr": "Main Ave",
 "City": "Chicago",
 "score": 100,
 "searchTheme": "arcgisSearch",
 "searchResult": "Main Ave, Chicago, Illinois, 60613",
 "searchMoreResults": "moreResults",
 "searchMoreResultsItem": "moreItem",
 "searchMoreResultsId": "search_more_results",
 "searchMoreResultsHtml": ""
 },
 "symbol": {
 "angle": 0,
 "xoffset": 6.75,
 "yoffset": 13.5,
 "type": "esriPMS",
 "url": "https://js.arcgis.com/3.20/esri/dijit/Search/images/search-pointer.png",
 "width": 27,
 "height": 27
 },
 "infoTemplate": {
 "title": "Search result",
 "content": "<div class=\"${searchTheme}\"><div id=\"${searchMoreResultsId}\" class=\"${searchMoreResults}\"><div class=\"${searchMoreResultsItem}\">${searchResult}</div><div>${searchMoreResultsHtml}</div></div></div>"
 }
 }]
 }
 }]
 }
 },
 {
 "id": "layer1",
 "title": "layer1",
 "opacity": 1,
 "minScale": 591657527.591555,
 "maxScale": 70.5310735,
 "url": "https://services.arcgisonline.com/ArcGIS/rest/services/Canvas/World_Light_Gray_Reference/MapServer"
 }],
 "exportOptions": {
 "outputSize": [800,
 1100],
 "dpi": 96
 },
 "layoutOptions": {
 "titleText": "My map title",
 "copyrightText": "My map copyright text",
 "scaleBarOptions": {
 "metricUnit": "esriKilometers",
 "metricLabel": "km",
 "nonMetricUnit": "esriMiles",
 "nonMetricLabel": "mi"
 },
 "legendOptions": {
 "operationalLayers": []
 }
 }
}‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

...it appears the info window content HTML is the culprit. In my proxy web.config, if I revert validation to 2.0:

<httpRuntime requestValidationMode="2.0" />

...the request works. This is because .NET 2.0 only validates page requests, whereas 4.0 validates ALL HTTP requests. I'd like to call it a day and just implement the web.config change, but I'm wary about making such a modification due to XSS/security concerns. I thought about maybe encoding/decoding, but there doesn't seem to be a way to do this without modifying the JSAPI directly.

Anyone have any ideas? Geonet is pretty quiet about this issue... Is it a bug? Print works fine otherwise!

Thank you!

0 Kudos
1 Solution

Accepted Solutions
ThomasSolow
Regular Contributor

It seems to me that the only solution to this problem is to re-engineer the API to ensure that nothing that IIS doesn't accept ever gets posted.  If the issue here is the HTML strings, then this probably means finding a different way to store infoTemplates.  I don't know if this has been considered and rejected, if it has never been considered, or if it's currently in progress.

The next-best solution (in my opinion) would just be to prevent the infoTemplate from getting posted during print requests, or any requests that pass through IIS.  Like FC Basson mentioned, it looks like the setRequestPreCallback is an ideal way to do this.

I agree that ideally the JSON representation of a map should never cause this kind of issue with IIS, but stripping out the infoTemplate seems like a pretty harmless solution to me.

View solution in original post

7 Replies
ThomasSolow
Regular Contributor

I'm not sure I understand the issue here.  Is .NET request validation preventing the request from being sent because it contains an html string?

Is there a reason print needs to know about your infoTemplate?  If not, and I understand the issue correctly, I would consider storing the infoTemplate's content in a temp variable, setting it to null on the map, making the print request, and then resetting the content from the temp variable when the request finishes.

ChrisSmith7
Frequent Contributor

Thomas,

That's correct, well, technically, IIS is preventing the request. The only difference I can see between successful and unsuccessful print tasks relates to the embedded HTML content in the JSON. The issue occurs even when the infoWindow is closed (the object is still supplied in the JSON) - it only works if you clear the address string from the Search widget.

Regarding your suggestion, the thought has crossed my mind, but wouldn't you say this is a kludge? There are other issues with the Print task I've discovered when the infoWindow is open (with different failure points/errors) - it really seems like there are bugs.

I don't recall these issues in years past, so maybe it was not an issue in earlier API versions. I cannot test the hypothesis since the features breaking Print weren't actually available in previous versions, e.g. the Search widget was added in v3.13, and I didn't convert to it right away.

0 Kudos
ChrisSmith7
Frequent Contributor

And FYI, the JSON map prints perfectly fine when posting directly on the server; no infoWindow is printed on the map (using server 10.3).

0 Kudos
ThomasSolow
Regular Contributor

It seems to me that the only solution to this problem is to re-engineer the API to ensure that nothing that IIS doesn't accept ever gets posted.  If the issue here is the HTML strings, then this probably means finding a different way to store infoTemplates.  I don't know if this has been considered and rejected, if it has never been considered, or if it's currently in progress.

The next-best solution (in my opinion) would just be to prevent the infoTemplate from getting posted during print requests, or any requests that pass through IIS.  Like FC Basson mentioned, it looks like the setRequestPreCallback is an ideal way to do this.

I agree that ideally the JSON representation of a map should never cause this kind of issue with IIS, but stripping out the infoTemplate seems like a pretty harmless solution to me.

ChrisSmith7
Frequent Contributor

It's not a bad solution - I will let you know how the resolution works. Thanks!

0 Kudos
ChrisSmith7
Frequent Contributor

The solution works, but I discovered another issue! I wrote this up as a separate incident (it looks like a genuine bug to me):

https://community.esri.com/message/682207-arcgis-jsapi-print-issue-error-executing-tool-layer-mapgra... 

0 Kudos
FC_Basson
MVP Regular Contributor

I agree with Thomas - try removing the infoTemplate with the setRequestPreCallback function.