Common_CustomTasks_CSharp\AsyncTask_CSharp\BasicAsyncTask.cs
// Copyright 2011 ESRI // // All rights reserved under the copyright laws of the United States // and applicable international laws, treaties, and conventions. // // You may freely redistribute and use this sample code, with or // without modification, provided you include the original copyright // notice and use restrictions. // // See the use restrictions. // namespace AsyncTask_CSharp { // Task specifying an architecture for submitting a job for asynchronous processing. This architecture // can be used for jobs that may take a long time to process. Once operation input is submitted via // the task's interface, the job is started and a response is returned to the client immediately, // allowing the user to submit additional jobs. In progress jobs are indicated via a task result node. // Job status checking is managed by JavaScript timeouts that issue callbacks to the server. [System.Web.UI.ToolboxData(@"<{0}:BasicAsyncTask runat=""server"" Width=""200px"" Transparency=""35"" BackColor=""White"" TitleBarColor=""WhiteSmoke"" TitleBarSeparatorLine=""True"" TitleBarHeight=""20px"" BorderColor=""LightSteelBlue"" BorderStyle=""Outset"" BorderWidth=""1px"" Font-Names=""Verdana"" Font-Size=""8pt"" ForeColor=""Black""> </{0}:BasicAsyncTask>")] public class BasicAsyncTask : ESRI.ArcGIS.ADF.Web.UI.WebControls.FloatingPanelTask { // Creates the Execute button protected override void CreateChildControls() { base.CreateChildControls(); // Instantiate the Execute button, set its text, and add it to the task's cotnrols System.Web.UI.HtmlControls.HtmlInputButton executeButton = new System.Web.UI.HtmlControls.HtmlInputButton(); executeButton.Value = "Execute"; Controls.Add(executeButton); // Create JavaScript that calls the Web ADF executeTask function. We pass executeTask // the task's callback function string so the call is linked to the current task // instance. string executeTaskJavaScript = string.Format("ESRI.ADF.Tasks.executeTask('',\"{0}\");", this.CallbackFunctionString); // Wire the JavaScript to fire when the Execute button is clicked executeButton.Attributes.Add("onclick", executeTaskJavaScript); } #region FloatingPanelTask Overrides - ExecuteTask, GetGISResourceItemDependencies // Submits and checks the status of asynchronous jobs, then creates a task results node // accordingly public override void ExecuteTask() { System.Collections.Specialized.NameValueCollection callbackArgsCollection = ESRI.ArcGIS.ADF.Web.UI.WebControls.CallbackUtility.ParseStringIntoNameValueCollection( this.CallbackEventArgument); // Retrieve the task and async job IDs from the callback arguments. The task job ID is // created by the Task framework and is used to link the task to task results. The // asynchronousJobID is created in this implementation and is used to check the status // of the job submitted for asynchronous processing. string taskFrameworkJobID = callbackArgsCollection["taskJobID"]; string asynchronousJobID = callbackArgsCollection["asyncJobID"]; // Initialize the task results this.Results = null; // If an async job ID was not included in the callback arguments, then the callback was // generated by the initial click of the Execute button. The job therefore needs to be // submitted for asynchronous processing. if (string.IsNullOrEmpty(asynchronousJobID)) { // Call method to submit the job and get the job's ID asynchronousJobID = SubmitSimJob(); // Uncomment to test against the BufferPoints tool of the BufferTools Geoprocessing service //asynchronousJobID = SubmitBufferPointsJob(); asynchronousJobID = asynchronousJobID.Trim(); // Add the job ID to the list of in-progress jobs this.JobsInProgress.Add(asynchronousJobID); } // Get the job's status ESRI.ArcGIS.ADF.Web.DataSources.JobStatus jobStatus; jobStatus = GetSimJobStatus(asynchronousJobID); // Uncomment to test against the BufferPoints tool of the BufferTools Geoprocessing service //jobStatus = GPFunctionality.GetJobStatus(asynchronousJobID); // Construct a task result node to show the status ESRI.ArcGIS.ADF.Web.UI.WebControls.TaskResultNode taskResultNode = new ESRI.ArcGIS.ADF.Web.UI.WebControls.TaskResultNode(); // Pass the node instance and the task job ID to the node setup method TaskResults.SetupTaskResultNode(this, taskFrameworkJobID, null, taskResultNode); // Give the node an indentation taskResultNode.TextCellStyleAttributes.Add("padding-left", "5px"); // Set up the node to do nothing when clicked taskResultNode.ClickBehavior = ESRI.ArcGIS.ADF.Web.UI.WebControls.TreeViewPlusNodeClickBehavior.None; // Convert the job status to a string string jobStatusString = jobStatus.ToString(); // Check the status and take action accordingly switch (jobStatus) { // Job succeeded case ESRI.ArcGIS.ADF.Web.DataSources.JobStatus.Succeeded: // Get the messages for the completed job string jobResultMessages = GetSimJobResult(asynchronousJobID); // Uncomment to test against the BufferPoints tool of the BufferTools Geoprocessing service //string jobResultMessages = GetBufferPointsResult(asynchronousJobID); // Set the text of the task result node to include the task's title, the job // status, and the job messages taskResultNode.Text = string.Format("{0} {1} <BR> {2}", this.Title, jobStatusString, jobResultMessages); // Remove the job from the in-progress list this.JobsInProgress.Remove(asynchronousJobID); break; // Job is still in progress default: // Set the task result node's text to include the task's title and job status taskResultNode.Text = string.Format("{0} {1}", this.Title, jobStatusString); // Set the task result node's image to be the Web ADF's callback activity indicator taskResultNode.LegendCollapsedImage = "/aspnet_client/ESRI/WebADF/images/callbackActivityIndicator.gif"; taskResultNode.LegendExpandedImage = "/aspnet_client/ESRI/WebADF/images/callbackActivityIndicator.gif"; // Construct JavaScript to set a timeout that calls the Web ADF startJob function. // This function issues a callback with the specified arguments and task ID. In // this implementation, this callback is handled to check the async job's status string checkStatusJavaScript = string.Format("window.setTimeout(" + "\"ESRI.ADF.Tasks.startJob('asyncJobID={0}',\\\"{1}\\\",{2})\", 2000);", asynchronousJobID, this.CallbackFunctionString, taskFrameworkJobID); // Package the JavaScript as a CallbackResult and add it to the task's collection ESRI.ArcGIS.ADF.Web.UI.WebControls.CallbackResult checkStatusCallbackResult = ESRI.ArcGIS.ADF.Web.UI.WebControls.CallbackResult.CreateJavaScript(checkStatusJavaScript); this.CallbackResults.Add(checkStatusCallbackResult); break; } // Return the job status task result node as the task's results Results = taskResultNode; } // The task has no resource dependencies, so this method is overriden to return an empty list public override System.Collections.Generic.List< ESRI.ArcGIS.ADF.Web.UI.WebControls.GISResourceItemDependency> GetGISResourceItemDependencies() { return new System.Collections.Generic.List< ESRI.ArcGIS.ADF.Web.UI.WebControls.GISResourceItemDependency>(); } #endregion #region Instance Methods // Submits a new job and returns the job's ID private string SubmitSimJob() { // Return a new GUID return System.Guid.NewGuid().ToString(); } // Retrieves the status of the job with the specified ID private ESRI.ArcGIS.ADF.Web.DataSources.JobStatus GetSimJobStatus(string JobID) { // Generate a random number between 0 and 3 System.Random randomizer = new System.Random(); int randomInteger = randomizer.Next(0, 4); // If the random number is 0, return a successful result. Otherwise, return a result // indicating the job is still in progress. if (randomInteger == 0) return ESRI.ArcGIS.ADF.Web.DataSources.JobStatus.Succeeded; else return ESRI.ArcGIS.ADF.Web.DataSources.JobStatus.Submitted; } // Retrieves the result of the job having the passed-in ID private string GetSimJobResult(string JobID) { // Return a string with the Job ID and time return string.Format("JobID: {0} <br />Time Returned: {1}", JobID, System.DateTime.Now.ToLongTimeString()); } #endregion #region Instance Properties // Returns a list containing the IDs of submitted jobs private System.Collections.Generic.List<string> JobsInProgress { get { // Try retrieving the jobs list from state System.Collections.Generic.List<string> jobsInProgress = StateManager.GetProperty("JobsInProgress") as System.Collections.Generic.List<string>; // If the list was not found, instantiate a new list and store it in state if (jobsInProgress == null) { jobsInProgress = new System.Collections.Generic.List<string>(); StateManager.SetProperty("JobsInProgress", jobsInProgress); } return jobsInProgress; } } // Retrieves the task's first buddied TaskResults control private ESRI.ArcGIS.ADF.Web.UI.WebControls.TaskResults TaskResults { get { ESRI.ArcGIS.ADF.Web.UI.WebControls.TaskResults taskResults = null; if (TaskResultsContainers[0] != null) taskResults = ESRI.ArcGIS.ADF.Web.UI.WebControls.Utility.FindControl( TaskResultsContainers[0].Name, Page) as ESRI.ArcGIS.ADF.Web.UI.WebControls.TaskResults; return taskResults; } } #endregion #region Members for Testing Against the BufferTools Geoprocessing Service ESRI.ArcGIS.ADF.Web.DataSources.ArcGISServer.GeoprocessingFunctionality _geoprocessingFunctionality = null; // Submits a new BufferPoints geoprocessing operation private string SubmitBufferPointsJob() { // Retrieve an array containing information about BufferPoints' parameters string gpTaskName = "BufferPoints"; ESRI.ArcGIS.ADF.Web.DataSources.GPToolInfo gpToolInfo = GPFunctionality.GetTask(gpTaskName); ESRI.ArcGIS.ADF.Web.DataSources.GPParameterInfo[] gpParameterInfoArray = gpToolInfo.ParameterInfo; // Get a reference to the operation's input graphics layer from the parameter array ESRI.ArcGIS.ADF.Web.DataSources.GPFeatureGraphicsLayer inputGpFeatureGraphicsLayer = (ESRI.ArcGIS.ADF.Web.DataSources.GPFeatureGraphicsLayer)gpParameterInfoArray[0].Value; ESRI.ArcGIS.ADF.Web.Display.Graphics.FeatureGraphicsLayer inputFeatureGraphicsLayer = inputGpFeatureGraphicsLayer.Layer; // Create a point and add it to the input graphics layer ESRI.ArcGIS.ADF.Web.Geometry.Point adfPoint = new ESRI.ArcGIS.ADF.Web.Geometry.Point(730324, 2309070); inputFeatureGraphicsLayer.Add(adfPoint); // Initialize the input linear unit (distance) to be 300 miles ESRI.ArcGIS.ADF.Web.DataSources.GPLinearUnit gpLinearUnit = new ESRI.ArcGIS.ADF.Web.DataSources.GPLinearUnit(); gpLinearUnit.Units = ESRI.ArcGIS.ADF.Web.DataSources.Units.Miles; gpLinearUnit.Value = 300; // Package the input parameters in an array and submit the job ESRI.ArcGIS.ADF.Web.DataSources.GPValue[] gpValueArray = new ESRI.ArcGIS.ADF.Web.DataSources.GPValue[2]; gpValueArray[0] = inputGpFeatureGraphicsLayer; gpValueArray[1] = gpLinearUnit; string jobID = GPFunctionality.SubmitJob(gpTaskName, gpValueArray); // Return the submitted job's ID return jobID; } // Retrieves the result of the BufferPoints job having the passed-in ID private string GetBufferPointsResult(string jobID) { // Get the geoprocessing result of the BufferPoints job with the passed-in ID ESRI.ArcGIS.ADF.Web.DataSources.GPResult gpResult = GPFunctionality.GetJobResult("BufferPoints", jobID, null, false); ESRI.ArcGIS.ADF.Web.DataSources.GPValue[] resultsGpValuesArray = gpResult.Values; // Get the graphics layer containing the result. Note that nothing is done with this graphics // layer here; the code to retrieve the result is included to for instructive purposes. ESRI.ArcGIS.ADF.Web.DataSources.GPFeatureGraphicsLayer resultsGpFeatureGraphicsLayer = resultsGpValuesArray[0] as ESRI.ArcGIS.ADF.Web.DataSources.GPFeatureGraphicsLayer; ESRI.ArcGIS.ADF.Web.Display.Graphics.FeatureGraphicsLayer resultsFeatureGraphicsLayer = resultsGpFeatureGraphicsLayer.Layer; // Return the result messages or an empty string if there are no messages if (gpResult.Messages != null) return gpResult.Messages[gpResult.Messages.Length - 1].MessageDesc; else return ""; } // Gets the geoprocessing functionailty for the first geoprocessing resource referenced by the // GeoprocessingResourceManager having an ID of "GeoprocessingResourceManager1" private ESRI.ArcGIS.ADF.Web.DataSources.ArcGISServer.GeoprocessingFunctionality GPFunctionality { get { // Check whether the GP functionality member variable has already been initialized if (_geoprocessingFunctionality == null) { // Get the geoprocessing resource manager ESRI.ArcGIS.ADF.Web.UI.WebControls.GeoprocessingResourceManager geoprocessingResourceManager = Page.FindControl("GeoprocessingResourceManager1") as ESRI.ArcGIS.ADF.Web.UI.WebControls.GeoprocessingResourceManager; // Get the first resource from the resource manager ESRI.ArcGIS.ADF.Web.DataSources.IGeoprocessingResource geoprocessingResource = geoprocessingResourceManager.GetResource(0); // Create a geoprocessing functionality from the resource and assign it to the GP functionality member // variable _geoprocessingFunctionality = (ESRI.ArcGIS.ADF.Web.DataSources.ArcGISServer.GeoprocessingFunctionality) geoprocessingResource.CreateFunctionality( typeof(ESRI.ArcGIS.ADF.Web.DataSources.IGeoprocessingFunctionality), null); // Make sure the GP functionality is initialized if (!_geoprocessingFunctionality.Initialized) _geoprocessingFunctionality.Initialize(); } return _geoprocessingFunctionality; } } #endregion } }