ArcGIS REST API: Generate

3968
16
Jump to solution
04-23-2018 11:37 AM
JamesCrandall
MVP Frequent Contributor

I'm not sure what to do as I don't see any error and dev tools doesn't report anything.  I'm attempting to implement this Add Shapefile sample into a button click on a new custom widget.  The issue seems to be happening in setting up the "request"

        generateFeatureCollection: function (fileName) {
            var name1 = fileName.split(".");
            
            //Chrome and IE add c:\fakepath to the value - we need to remove it
            //See this link for more info: http://davidwalsh.name/fakepath
            var name = name1[0].replace("c:\\fakepath\\", "");
            console.log("processing filename: ", name)
            //dom.byId('upload-status').innerHTML = '<b>Loading </b>' + name;

            //Define the input params for generate see the rest doc for details
            //http://www.arcgis.com/apidocs/rest/index.html?generate.html
            var params = {
                'name': name,
                'targetSR': map.spatialReference,
                'maxRecordCount': 1000,
                'enforceInputFileSizeLimit': true,
                'enforceOutputJsonSizeLimit': true
            };
            console.log("params: ", params)

            //generalize features for display Here we generalize at 1:40,000 which is approx 10 meters
            //This should work well when using web mercator.
            var extent = scaleUtils.getExtentForScale(map, 40000);
            var resolution = extent.getWidth() / map.width;
            params.generalize = true;
            params.maxAllowableOffset = resolution;
            params.reducePrecision = true;
            params.numberOfDigitsAfterDecimal = 0;

            var myContent = {
                'filetype': 'shapefile',
                'publishParameters': JSON.stringify(params),
                'f': 'json',
                'callback.html': 'textarea'
            };
            console.log("myContent: ", myContent)
            console.log("setting up request")
            //use the rest generate operation to generate a feature collection from the zipped shapefile
            request({
                url: portalUrl + '/sharing/rest/content/features/generate',
                content: myContent,
                form: lang.hitch(this, dom.byId('uploadForm')),
                form: dom.byId('uploadForm'),
                handleAs: 'json',
                load: lang.hitch(this, function (response) {
                    if (response.error) {
                        this.errorHandler(response.error);                        
                        return;
                    }                   
                        var layerName = response.featureCollection.layers[0].layerDefinition.name;
                        console.log("layerName: ", layerName)
                        this.addShapefileToMap(response.featureCollection);
                   
                }),
                error: lang.hitch(this, this.errorHandler)

            });            
        },
        errorHandler: function (error) {
            //dom.byId('upload-status').innerHTML = "<p style='color:red'>" + error.message + "</p>";
            console.log("1 errorHandler: ", error.message)
        },
            
        addShapefileToMap: function (featureCollection) {
            //add the shapefile to the map and zoom to the feature collection extent
            //If you want to persist the feature collection when you reload browser you could store the collection in
            //local storage by serializing the layer using featureLayer.toJson()  see the 'Feature Collection in Local Storage' sample
            //for an example of how to work with local storage.
            var fullExtent;
            var layers = [];

            console.log("addShapefileToMap initiated")
            arrayUtils.forEach(featureCollection.layers, function (layer) {
                var infoTemplate = new InfoTemplate("Details", "${*}");
                var featureLayer = new FeatureLayer(layer, {
                    infoTemplate: infoTemplate
                });
                //associate the feature with the popup on click to enable highlight and zoom to
                featureLayer.on('click', function (event) {
                    map.infoWindow.setFeatures([event.graphic]);
                });
                //change default symbol if desired. Comment this out and the layer will draw with the default symbology
                changeRenderer(featureLayer);
                fullExtent = fullExtent ?
                  fullExtent.union(featureLayer.fullExtent) : featureLayer.fullExtent;
                layers.push(featureLayer);
            });
            map.addLayers(layers);
            map.setExtent(fullExtent.expand(1.25), true);

            dom.byId('upload-status').innerHTML = "";
        },

I've added a few console.log prints to try and track down what's going wrong.  No errors, but request doesn't seem to do anything (it's supposed to call "addShapefileToMap" function but seems to just go right to errorHandler: function. 

Line #37 above console.log("setting up request") is the last thing in the console before errorHandler is then reached.  Hopefully just something silly I'm doing.

0 Kudos
16 Replies
JamesCrandall
MVP Frequent Contributor

Yes, that is correct!  Also, on the network tab (dev tools) generate looks entirely different and is not issuing POST only GET requests.

My implementation:

Sandbox:

0 Kudos
RobertScheitlin__GISP
MVP Emeritus

OK,

   The the issue is likely the POST vs Get. So in your change to the esri request you added usePost: ture but you put it in the wrong location.

            request({
                url: this.portalUrl + '/sharing/rest/content/features/generate',
                content: myContent,
                form: this.uploadForm,
                handleAs: 'json',
                load: lang.hitch(this, function (response) {
                    if (response.error) {
                        this.errorHandler(response.error);
                        return;
                    }
                    var layerName = response.featureCollection.layers[0].layerDefinition.name;
                    this.uploadstatus.innerHTML = '<b>Loaded: </b>' + layerName;
                    this.addShapefileToMap(response.featureCollection);
                }),
                error: lang.hitch(this, this.errorHandler)
            }, {usePost: 'true'});
JamesCrandall
MVP Frequent Contributor

*Edit: The issue below may be related to the form: this.uploadForm attribute of the request.  I've changed this to

form: dom.byId('uploadForm') and it will now run thru without error to the

addShapefileToMap function (but I have an error in there now so I'm working thru that).

Never would have thought to add it there!  Thanks!  The generate request appears to be correct now and method is POST. Unfortunately, I the error.message is printing in the console output as:

errorHandler: Unable to generate features

The Network response in dev tools is:

{"error":{"code":400,"message":"Unable to generate features","details":["'itemid', 'sourceUrl' or 'text' must be specified."]}}

Your assistance is appreciated!  I'll continue to work on this, can't believe how much this is fighting me.

0 Kudos
JamesCrandall
MVP Frequent Contributor

Robert,

Thanks for working thru this one, turns out that it was a combination of the request method defaulting to GET (and me not correctly forcing POST) and then me failing to properly reference the "uploadForm" in the form attribute of the request.  Full function updated with working version.

Thank you again!

generateFeatureCollection: function(fileName) {
            var name = fileName.split(".");
            //Chrome and IE add c:\fakepath to the value - we need to remove it
            //See this link for more info: http://davidwalsh.name/fakepath
            name = name[0].replace("c:\\fakepath\\", "");

            //this.uploadstatus.innerHTML = '<b>Loading… </b>' + name;

            //Define the input params for generate see the rest doc for details
            //http://www.arcgis.com/apidocs/rest/index.html?generate.html
            console.log("var params name: ", name)
            var params = {
                'name': name,
                'targetSR': this.map.spatialReference,
                'maxRecordCount': 1000,
                'enforceInputFileSizeLimit': true,
                'enforceOutputJsonSizeLimit': true
            };

            console.log("var params: ", params)

            //generalize features for display Here we generalize at 1:40,000 which is approx 10 meters
            //This should work well when using web mercator.
            var extent = scaleUtils.getExtentForScale(this.map, 40000);
            var resolution = extent.getWidth() / this.map.width;
            params.generalize = true;
            params.maxAllowableOffset = resolution;
            params.reducePrecision = true;
            params.numberOfDigitsAfterDecimal = 0;

            var myContent = {
                'filetype': 'shapefile',
                'publishParameters': JSON.stringify(params),
                'f': 'json'
                //'callback.html': 'textarea'
            };
            console.log("myContent: ", myContent)

            //use the rest generate operation to generate a feature collection from the zipped shapefile.            
            request({
                url: this.portalUrl + '/sharing/rest/content/features/generate',
                content: myContent,
                form: dom.byId('uploadForm'), //this.uploadForm,
                handleAs: 'json',
                load: lang.hitch(this, function (response) {
                    if (response.error) {
                        console.log("response.error: ", response.error)
                        this.errorHandler(response.error);
                        return;
                    }
                    var layerName = response.featureCollection.layers[0].layerDefinition.name;
                    //this.uploadstatus.innerHTML = '<b>Loaded: </b>' + layerName;
                    this.addShapefileToMap(response.featureCollection);
                }),
                error: lang.hitch(this, this.errorHandler)
            }, { usePost: 'true', });
        },
0 Kudos
RobertScheitlin__GISP
MVP Emeritus

James,

   So the uploadForm was not part of your widgets template and could not be referenced by "this".

JamesCrandall
MVP Frequent Contributor

Yes! 

Also, I have no need for the changeRenderer function and I'm altering the addShapefileToMap function because I need to get the featureColleciton result into an existing feature layer client side (or graphic layer, can't remember).  Ultimately, the results of the upload will get dissolved into existing features.

0 Kudos
MichaelLev
Frequent Contributor

Dear Robert, please see my question at ArcGIS REST API: Generate - how to use it without html form.

Thanks, 

Michael

0 Kudos