ArcGIS Buffer geoprocessing
ArcGIS_Buffer_Geoprocessing_VBNet\Default.aspx.vb
' Copyright 2010 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.
' 

Imports Microsoft.VisualBasic
Imports System
Public Partial Class _Default
  Inherits System.Web.UI.Page

#Region "Instance Variable Declarations"

    ' Name of the geoproccessing resource containing the BufferPoints task
    Private _geoprocessingResourceName As String = "Buffer Resource"

    ' Name of the resource in which to store geoprocessing results
    Private _graphicsResourceName As String = "Web ADF Graphics"

    ' Name of the graphics layers that will hold result buffers and user-placed points
    Private _bufferGraphicsLayerName As String = "Buffer"
    Private _pointGraphicsLayerName As String = "Points"

    Private _callbackResultCollection As ESRI.ArcGIS.ADF.Web.UI.WebControls.CallbackResultCollection = New ESRI.ArcGIS.ADF.Web.UI.WebControls.CallbackResultCollection()

#End Region

#Region "ASP.NET Page Life Cycle Event Handlers"

    Protected Sub Page_PreRender(ByVal sender As Object, ByVal eventArgs As System.EventArgs)
        Try
            ' Initialize session variables only if the page request is occurring at the beginning of a session
            If Page.Session.IsNewSession Then
                Session("graphicsResourceName") = _graphicsResourceName
                Session("pointGraphicsLayerName") = _pointGraphicsLayerName
            End If

            'Make sure control initialization only occurs during initial page load or on page refresh

            If (Not ScriptManager1.IsInAsyncPostBack) Then
                ' Add all the ArcGIS Server unit types to the units drop-down list except for unknown, points, 
                ' and decimal degress
                Dim agsUnitTypes As System.Array = System.Enum.GetValues(GetType(ESRI.ArcGIS.ADF.Web.DataSources.Units))
                For Each agsUnitType As Integer In agsUnitTypes
                    Dim unit As String = agsUnitTypes.GetValue(agsUnitType).ToString()
                    If (unit <> "Unknown") AndAlso (unit <> "DecimalDegrees") AndAlso (unit <> "Points") Then
                        unitsDropDownList.Items.Add(unit)
                    End If
                Next agsUnitType
            End If
        Catch exception As System.Exception
            Dim jsErrorAlertString As String = String.Format("<script>{0}</script>", Utility.GetJavaScriptErrorString(exception))
            Response.Write(jsErrorAlertString)
        End Try
    End Sub

    ' Generate custom callback function string for non-ADF controls\elements in page that generate callbacks
    Protected Sub Page_Load(ByVal sender As Object, ByVal eventArgs As System.EventArgs)
        ScriptManager1.RegisterAsyncPostBackControl(BufferButton)
        ScriptManager1.RegisterAsyncPostBackControl(ClearGraphicsButton)
    End Sub

#End Region

#Region "Request Handling"
    Protected Sub PostbackManager1_RequestReceived1(ByVal sender As Object, ByVal args As PostbackManager_VBNet.AdfRequestEventArgs) Handles PostbackManager1.RequestReceived
        ' Use the Web ADF's callback utility to parse the arguments into a NameValueCollection
        Dim requestArgs As System.Collections.Specialized.NameValueCollection = ESRI.ArcGIS.ADF.Web.UI.WebControls.CallbackUtility.ParseStringIntoNameValueCollection(args.RequestArguments)

        If requestArgs("EventArg") = "CheckJobStatus" Then
            Try
                ' Call the method to heck whether the geoprocssing job is finished and process results if so
                CheckJobStatus(requestArgs("JobID"), requestArgs("TaskName"), requestArgs("OutputParameters"))
            Catch exception As System.Exception
                Dim errorCallbackResult As ESRI.ArcGIS.ADF.Web.UI.WebControls.CallbackResult = Utility.CreateErrorCallbackResult(exception)
                _callbackResultCollection.Add(errorCallbackResult)
            Finally
                PostbackManager1.CallbackResults.CopyFrom(_callbackResultCollection)
            End Try
        End If
    End Sub

#End Region

#Region "ASP.NET Web Control Event Handlers"

    Protected Sub BufferButton_Click1(ByVal sender As Object, ByVal e As System.EventArgs) Handles BufferButton.Click
        Try
            ' Get the buffer operation parameters specified by the user
            Dim bufferDistanceString As String = BufferDistanceTextBox.Text
            Dim bufferDistance As Double = 0
            Double.TryParse(bufferDistanceString, bufferDistance)

            ' Invoke the method to initiate the geoprocessing task
            StartBufferJob(bufferDistance, UnitsDropDownList.SelectedValue)
        Catch exception As System.Exception
            Dim errorCallbackResult As ESRI.ArcGIS.ADF.Web.UI.WebControls.CallbackResult = Utility.CreateErrorCallbackResult(exception)
            _callbackResultCollection.Add(errorCallbackResult)
        Finally
            ScriptManager1.RegisterDataItem(Page, _callbackResultCollection.ToString(), False)
        End Try
    End Sub

    Protected Sub ClearGraphicsButton_Click1(ByVal sender As Object, ByVal e As System.EventArgs) Handles ClearGraphicsButton.Click
        Try
            ' Invoke the method to clear the graphics from the map
            ClearGraphics()
        Catch exception As System.Exception
            Dim errorCallbackResult As ESRI.ArcGIS.ADF.Web.UI.WebControls.CallbackResult = Utility.CreateErrorCallbackResult(exception)
            _callbackResultCollection.Add(errorCallbackResult)
        Finally
            ScriptManager1.RegisterDataItem(Page, _callbackResultCollection.ToString(), False)
        End Try
    End Sub

#End Region

#Region "Instance Methods"

    ' Initiates the buffer points geoprocessing job with the passed-in parameters
    Private Sub StartBufferJob(ByVal bufferDistance As Double, ByVal units As String)
        '    #Region "Initialize resources and functionalities"

        ' Initialize GP resource and functionality
        Dim geoprocessingResourceItem As ESRI.ArcGIS.ADF.Web.UI.WebControls.GeoprocessingResourceItem = GeoprocessingResourceManager1.ResourceItems.Find(_geoprocessingResourceName)

        ' Make sure the geoprocessing resource is initialized
        If (Not geoprocessingResourceItem.Resource.Initialized) Then
            geoprocessingResourceItem.InitializeResource()
        End If

        ' Get a reference to the GP resource and its functionality
        Dim geoprocessingResource As ESRI.ArcGIS.ADF.Web.DataSources.IGeoprocessingResource = CType(geoprocessingResourceItem.Resource, ESRI.ArcGIS.ADF.Web.DataSources.IGeoprocessingResource)

        Dim commonGeoprocessingFunctionality As ESRI.ArcGIS.ADF.Web.DataSources.IGeoprocessingFunctionality = CType(geoprocessingResource.CreateFunctionality(GetType(ESRI.ArcGIS.ADF.Web.DataSources.IGeoprocessingFunctionality), Nothing), ESRI.ArcGIS.ADF.Web.DataSources.IGeoprocessingFunctionality)

        Dim agsGeoprocessingFunctionality As ESRI.ArcGIS.ADF.Web.DataSources.ArcGISServer.GeoprocessingFunctionality = TryCast(commonGeoprocessingFunctionality, ESRI.ArcGIS.ADF.Web.DataSources.ArcGISServer.GeoprocessingFunctionality)

        ' Make sure the geoprocessing functionality is initialized
        If (Not agsGeoprocessingFunctionality.Initialized) Then
            agsGeoprocessingFunctionality.Initialize()
        End If

        '    #End Region

        '    #Region "Prepare inputs and start the GP task"

        ' Set the name of the geoprocessing (GP) task
        Dim GPTaskName As String = "BufferPoints"

        ' Get an array of the GP task's parameters
        Dim adfGPToolInfo As ESRI.ArcGIS.ADF.Web.DataSources.GPToolInfo = agsGeoprocessingFunctionality.GetTask(GPTaskName)
        Dim adfGPParamterInfoArray() As ESRI.ArcGIS.ADF.Web.DataSources.GPParameterInfo = adfGPToolInfo.ParameterInfo

        ' Get a reference to the first input parameter (a feature set) as a Web ADF feature graphics layer
        Dim adfGPFeatureGraphicsLayer As ESRI.ArcGIS.ADF.Web.DataSources.GPFeatureGraphicsLayer = CType(adfGPParamterInfoArray(0).Value, ESRI.ArcGIS.ADF.Web.DataSources.GPFeatureGraphicsLayer)
        Dim featureGraphicsLayer As ESRI.ArcGIS.ADF.Web.Display.Graphics.FeatureGraphicsLayer = adfGPFeatureGraphicsLayer.Layer

        ' Get the graphics resource containing the layer that holds the user-placed points
        Dim adfGraphicsMapResource As ESRI.ArcGIS.ADF.Web.DataSources.Graphics.MapResource = TryCast(Map1.GetFunctionality(_graphicsResourceName).Resource, ESRI.ArcGIS.ADF.Web.DataSources.Graphics.MapResource)

        ' Get the graphics layer containing the user-placed points
        Dim pointElementGraphicsLayer As ESRI.ArcGIS.ADF.Web.Display.Graphics.ElementGraphicsLayer = TryCast(adfGraphicsMapResource.Graphics.Tables(_pointGraphicsLayerName), ESRI.ArcGIS.ADF.Web.Display.Graphics.ElementGraphicsLayer)

        ' If there are no points in the layer, alert the user and exit the function
        If (pointElementGraphicsLayer Is Nothing) OrElse (pointElementGraphicsLayer.Rows.Count < 1) Then
            Dim noPointsAlertCallbackResult As ESRI.ArcGIS.ADF.Web.UI.WebControls.CallbackResult = ESRI.ArcGIS.ADF.Web.UI.WebControls.CallbackResult.CreateJavaScript("alert('No points to buffer')")
            _callbackResultCollection.Add(noPointsAlertCallbackResult)
            _callbackResultCollection.Add(HideActivityIndicators())
            Return
        End If

        ' Add each point to the feature graphics layer that we're using as input to the GP task
        For Each dataRow As System.Data.DataRow In pointElementGraphicsLayer.Rows
            Dim adfPoint As ESRI.ArcGIS.ADF.Web.Geometry.Point = TryCast(pointElementGraphicsLayer.GeometryFromRow(dataRow), ESRI.ArcGIS.ADF.Web.Geometry.Point)
            featureGraphicsLayer.Add(adfPoint)
        Next dataRow

        ' Get the Web ADF Unit enumeration value corresponding to the user-defined unit 
        Dim adfGPLinearUnit As New ESRI.ArcGIS.ADF.Web.DataSources.GPLinearUnit()
        Dim adfUnits As ESRI.ArcGIS.ADF.Web.DataSources.Units = CType(System.Enum.Parse(GetType(ESRI.ArcGIS.ADF.Web.DataSources.Units), units, True), ESRI.ArcGIS.ADF.Web.DataSources.Units)

        ' Set the GP task's second input parameter (linear unit) using the user-defined
        ' distance and units 
        adfGPLinearUnit.Units = adfUnits
        adfGPLinearUnit.Value = bufferDistance

        ' Put the parameters in an input array and start the geoprocessing job
        Dim adfGPValueArray(1) As ESRI.ArcGIS.ADF.Web.DataSources.GPValue
        adfGPValueArray(0) = adfGPFeatureGraphicsLayer
        adfGPValueArray(1) = adfGPLinearUnit
        Dim jobID As String = agsGeoprocessingFunctionality.SubmitJob(GPTaskName, adfGPValueArray)

        '    #End Region

        '    #Region "Construct a callback to check the GP task's status"

        ' Get the output parameter names to use when retrieving geoprocessing job results
        Dim outputParameters As String = Nothing
        Dim agsGPParameterInfo As ESRI.ArcGIS.ADF.Web.DataSources.GPParameterInfo
        For i As Integer = 0 To adfGPParamterInfoArray.Length - 1
            agsGPParameterInfo = adfGPParamterInfoArray(i)

            ' Only append output parameters to the parameter string
            If agsGPParameterInfo.Direction = ESRI.ArcGIS.ADF.Web.DataSources.GPParameterDirection.Output Then
                outputParameters &= agsGPParameterInfo.Name
                If i <> adfGPParamterInfoArray.Length - 1 Then
                    outputParameters &= ";"
                End If
            End If
        Next i

        Dim checkJobStatusCallbackResult As ESRI.ArcGIS.ADF.Web.UI.WebControls.CallbackResult = GetStatusCheckJavaScript(GPTaskName, jobID, outputParameters, 1000)

        _callbackResultCollection.Add(checkJobStatusCallbackResult)

        '    #End Region
    End Sub

    ' Check the GP job status for the job with the passed-in parameters and take action accordingly
    Protected Sub CheckJobStatus(ByVal jobID As String, ByVal taskName As String, ByVal outputParameters As String)
        'Initialize geoprocessing resources and functionalities"

        ' Initialize GP resource and functionality
        Dim geoprocessingResourceItem As ESRI.ArcGIS.ADF.Web.UI.WebControls.GeoprocessingResourceItem = GeoprocessingResourceManager1.ResourceItems.Find(_geoprocessingResourceName)

        ' Make sure the geoprocessing resource is initialized
        If (Not geoprocessingResourceItem.Resource.Initialized) Then
            geoprocessingResourceItem.InitializeResource()
        End If

        ' Get a reference to the GP resource and its functionality
        Dim geoprocessingResource As ESRI.ArcGIS.ADF.Web.DataSources.IGeoprocessingResource = CType(geoprocessingResourceItem.Resource, ESRI.ArcGIS.ADF.Web.DataSources.IGeoprocessingResource)

        Dim commonGeoprocessingFunctionality As ESRI.ArcGIS.ADF.Web.DataSources.IGeoprocessingFunctionality = CType(geoprocessingResource.CreateFunctionality(GetType(ESRI.ArcGIS.ADF.Web.DataSources.IGeoprocessingFunctionality), Nothing), ESRI.ArcGIS.ADF.Web.DataSources.IGeoprocessingFunctionality)

        Dim agsGeoprocessingFunctionality As ESRI.ArcGIS.ADF.Web.DataSources.ArcGISServer.GeoprocessingFunctionality = TryCast(commonGeoprocessingFunctionality, ESRI.ArcGIS.ADF.Web.DataSources.ArcGISServer.GeoprocessingFunctionality)

        ' Make sure the geoprocessing functionality is initialized
        If (Not agsGeoprocessingFunctionality.Initialized) Then
            agsGeoprocessingFunctionality.Initialize()
        End If



        'Construct callback to alert user if GP task failed or to check job status again if task is not complete"

        ' Get the GP job's status
        Dim adfJobStatus As ESRI.ArcGIS.ADF.Web.DataSources.JobStatus = agsGeoprocessingFunctionality.GetJobStatus(jobID)

        ' If GP job failed, get job's last message and return it in an alert box
        If adfJobStatus = ESRI.ArcGIS.ADF.Web.DataSources.JobStatus.Failed OrElse adfJobStatus = ESRI.ArcGIS.ADF.Web.DataSources.JobStatus.TimedOut Then
            ' Get the GP job's messages
            Dim adfJobMessageArray() As ESRI.ArcGIS.ADF.Web.DataSources.JobMessage = agsGeoprocessingFunctionality.GetJobMessages(jobID)
            Dim messageCount As Integer = adfJobMessageArray.Length

            ' Create the alert javascript and package it in a callback
            Dim jsAlertGPError As String = String.Format("alert('GP job failed: {0}')", adfJobMessageArray(messageCount - 1).MessageDesc)
            Dim gpErrorAlertCallbackResult As ESRI.ArcGIS.ADF.Web.UI.WebControls.CallbackResult = ESRI.ArcGIS.ADF.Web.UI.WebControls.CallbackResult.CreateJavaScript(jsAlertGPError)

            ' Add the error alert to the callback results collection
            _callbackResultCollection.Add(gpErrorAlertCallbackResult)

            ' Add a callback result to hide the operation activity indicators to the callback results collection
            _callbackResultCollection.Add(HideActivityIndicators())
            Return
        ElseIf Not adfJobStatus = ESRI.ArcGIS.ADF.Web.DataSources.JobStatus.Succeeded Then
            ' Since the GP job is not yet complete, create the javascript necessary to trigger another callback
            ' that will check the GP job status in 5 seconds.  Package this javascript in a callback result and
            ' add it to the callback results collection
            _callbackResultCollection.Add(GetStatusCheckJavaScript(taskName, jobID, outputParameters, 5000))
            Return
        End If

        'Process the GP task's results

        ' Parse the GP task's output parameter names
        Dim outputParametersArray() As String = outputParameters.Split(";"c)
        ' Get the result of the GP task
        Dim adfGPResult As ESRI.ArcGIS.ADF.Web.DataSources.GPResult = agsGeoprocessingFunctionality.GetJobResult(taskName, jobID, outputParametersArray, False)

        ' Get the results of the GP operation
        Dim adfGPValueArray() As ESRI.ArcGIS.ADF.Web.DataSources.GPValue = adfGPResult.Values

        ' Get the output feature set containing buffers as a Web ADF feature graphics layer
        Dim adfGPFeatureGraphicsLayer As ESRI.ArcGIS.ADF.Web.DataSources.GPFeatureGraphicsLayer = TryCast(adfGPValueArray(0), ESRI.ArcGIS.ADF.Web.DataSources.GPFeatureGraphicsLayer)
        Dim featureGraphicsLayer As ESRI.ArcGIS.ADF.Web.Display.Graphics.FeatureGraphicsLayer = adfGPFeatureGraphicsLayer.Layer

        ' If the graphics layer has no features, alert the user that the operation did not create 
        ' any output
        If (featureGraphicsLayer Is Nothing) OrElse (featureGraphicsLayer.Rows.Count < 1) Then
            Dim noResultsAlertCallbackResult As ESRI.ArcGIS.ADF.Web.UI.WebControls.CallbackResult = ESRI.ArcGIS.ADF.Web.UI.WebControls.CallbackResult.CreateJavaScript("alert('No results returned');")
            _callbackResultCollection.Add(noResultsAlertCallbackResult)

            ' Add a callback result to hide the operation activity indicators and enable the
            ' Buffer Points button
            _callbackResultCollection.Add(HideActivityIndicators())
            Return
        End If

        ' Get the graphics layer's symbols and set their transparency to 50%
        Dim featureSymbolList As New System.Collections.Generic.List(Of ESRI.ArcGIS.ADF.Web.Display.Symbol.FeatureSymbol)()
        featureGraphicsLayer.Renderer.GetAllSymbols(featureSymbolList)
        For Each featureSymbol As ESRI.ArcGIS.ADF.Web.Display.Symbol.FeatureSymbol In featureSymbolList
            featureSymbol.Transparency = 50
        Next featureSymbol

        ' Set the buffer graphics layer's name
        featureGraphicsLayer.TableName = _bufferGraphicsLayerName

        ' Get the graphics resource to put the results layer in
        Dim graphicsMapResource As ESRI.ArcGIS.ADF.Web.DataSources.Graphics.MapResource = TryCast(Map1.GetFunctionality(_graphicsResourceName).Resource, ESRI.ArcGIS.ADF.Web.DataSources.Graphics.MapResource)

        ' If the resource already has a buffer graphics layer, remove it
        If graphicsMapResource.Graphics.Tables.Contains(_bufferGraphicsLayerName) Then
            graphicsMapResource.Graphics.Tables.Remove(_bufferGraphicsLayerName)
        End If

        ' Add new graphics layer to display the buffers
        graphicsMapResource.Graphics.Tables.Add(featureGraphicsLayer)

        ' Refresh the graphics resource and copy the map's callback results to the callback collection
        ' so the operation results are displayed
        Map1.RefreshResource(graphicsMapResource.Name)
        _callbackResultCollection.CopyFrom(Map1.CallbackResults)

        ' Since the operation is complete, hide its activity indicators
        _callbackResultCollection.Add(HideActivityIndicators())


    End Sub
    
    ' Creates a callback result with the client-side code needed to hide the operation activity indicator
    ' and enable the operation execution button
    Private Function HideActivityIndicators() As ESRI.ArcGIS.ADF.Web.UI.WebControls.CallbackResult
        Dim jsHideIndicators As String = "toggleActivityIndicators(false);"
        Dim hideIndicatorsCallbackResult As ESRI.ArcGIS.ADF.Web.UI.WebControls.CallbackResult = ESRI.ArcGIS.ADF.Web.UI.WebControls.CallbackResult.CreateJavaScript(jsHideIndicators)
        Return hideIndicatorsCallbackResult
    End Function

    ' Clears features from all graphics layers in the resource specified by m_graphicsResourceName
    Protected Sub ClearGraphics()
        ' Retrieve the resource and clear its graphics dataset
        Dim graphicsMapResource As ESRI.ArcGIS.ADF.Web.DataSources.Graphics.MapResource = TryCast(Map1.GetFunctionality(_graphicsResourceName).Resource, ESRI.ArcGIS.ADF.Web.DataSources.Graphics.MapResource)
        graphicsMapResource.Graphics.Clear()

        ' Refresh the resource and copy the map's callback results to the callback results collection so
        ' the graphics are removed from the map
        Map1.RefreshResource(graphicsMapResource.Name)
        _callbackResultCollection.CopyFrom(Map1.CallbackResults)
    End Sub

    Private Function GetStatusCheckJavaScript(ByVal GPTaskName As String, ByVal jobID As String, ByVal outputParameters As String, ByVal timeout As Integer) As ESRI.ArcGIS.ADF.Web.UI.WebControls.CallbackResult
        Dim arguments As String = String.Format("EventArg=CheckJobStatus&JobID={0}&TaskName={1}&OutputParameters={2}", jobID, GPTaskName, outputParameters)
        ' Construct a callback with the JavaScript needed to trigger a second callback after one second 
        ' (1000 milliseconds) that will execute logic on the server to check the GP job's status and
        ' take action accordingly
        Dim jsCheckJobStatus As String = "window.setTimeout(""ESRI.ADF.Samples.PostbackManager.doAsyncRequest('{0}');"",{1});"
        jsCheckJobStatus = String.Format(jsCheckJobStatus, arguments, timeout)
        Dim checkJobStatusCallbackResult As ESRI.ArcGIS.ADF.Web.UI.WebControls.CallbackResult = ESRI.ArcGIS.ADF.Web.UI.WebControls.CallbackResult.CreateJavaScript(jsCheckJobStatus)
        Return checkJobStatusCallbackResult

    End Function

#End Region

  
  
End Class