Common Custom tasks
Common_CustomTasks_VBNet\OptimizeTask_VBNet\AsyncOptimizer.vb
' 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.
' 

Imports Microsoft.VisualBasic
Imports System
Imports System.Collections.Generic
Imports System.Text
Imports ESRI.ArcGIS.ADF.Web.UI.WebControls
Imports System.Collections.Specialized

Public Class AsyncOptimizer
  Private task As CompositeControl
  Private stateManager As StateManager
  Public Sub New(ByVal task As CompositeControl)
    Me.task = task
    stateManager = task.StateManager
  End Sub
  #Region "Properties"
  ''' <summary>
  ''' Child controls of the task that handle async calls
  ''' </summary>
  Public Property ChildControlsHandlingAsyncCalls() As List(Of String)
    Get
      Dim list As List(Of String) = TryCast(stateManager.GetProperty("childControlsHandlingAsyncCalls"), List(Of String))
      If list Is Nothing Then
        list = New List(Of String)()
                Me.ChildControlsHandlingAsyncCalls = list
      End If
      Return list
    End Get
    Set
      stateManager.SetProperty("childControlsHandlingAsyncCalls", Value)
    End Set
  End Property

  ''' <summary>
  ''' Names of the map tools on the task (Tool.Name)
  ''' </summary>
  Public Property MapToolsHandlingAsyncCalls() As List(Of String)
    Get
      Dim list As List(Of String) = TryCast(stateManager.GetProperty("mapToolsHandlingAsyncCalls"), List(Of String))
      If list Is Nothing Then
        list = New List(Of String)()
        MapToolsHandlingAsyncCalls = list
      End If
      Return list
    End Get
    Set
      stateManager.SetProperty("mapToolsHandlingAsyncCalls", Value)
    End Set
  End Property

  ''' <summary>
  ''' The unique id of the map control associated with this task
  ''' </summary>
  Public Property MapUniqueID() As String
    Get
      Dim id As String = TryCast(stateManager.GetProperty("mapid"), String)
      If String.IsNullOrEmpty(id) Then
        Dim iTask As ITask = TryCast(task, ITask)
        Dim i As Integer = 0
        Do While i < iTask.TaskResultsContainers.Count
          Dim _taskResults As ITaskResultsContainer = TryCast(Utility.FindControl(iTask.TaskResultsContainers(i).Name, task.Page), ITaskResultsContainer)
          If Not _taskResults Is Nothing AndAlso Not _taskResults.MapInstance Is Nothing Then
            id = _taskResults.MapInstance.UniqueID
            MapUniqueID = id
            Exit Do
          End If
          i += 1
        Loop
      End If
      Return id
    End Get
    Set
      stateManager.SetProperty("mapid", Value)
    End Set
  End Property

  ''' <summary>
  ''' Whether child control creation is required for a page life cycle
  ''' </summary>
  Public ReadOnly Property RequiresChildControls() As Boolean
    Get
      'if not an async call, need to create child controls
      If (Not task.IsAsync) Then
        Return True
      End If

      'if this control is handling the async call, create child controls
      Dim callingControl As String = GetCallingControlID()
      If callingControl = task.UniqueID Then
        Return True
      End If

      'if the child is handling the call, create child controls
      If ChildControlsHandlingAsyncCalls.Contains(callingControl) Then
        Return True
      End If

      'if the call is handled by a tool on a toolbar on this control, create child controls
      If callingControl = MapUniqueID Then 'call to map associated with this task?
        Dim tool As String = GetCallingMapTool(MapUniqueID)
        If Not tool Is Nothing AndAlso MapToolsHandlingAsyncCalls.Contains(tool) Then 'call from tool action from this control's toolbar?
          Return True
        End If
      End If
      Return False
    End Get
  End Property
  #End Region


  ''' <summary>
  ''' Gets the Unique ID of the control that created the asynchronous call.
  ''' </summary>
  ''' <returns>Unique ID of the control that initiated the asynchronous call,
  ''' or null if not asynchronous or not found.</returns>
  Public Shared Function GetCallingControlID() As String
    ' Get the context of the current request
    Dim httpContext As System.Web.HttpContext = System.Web.HttpContext.Current
    If httpContext Is Nothing Then
    Return Nothing
    End If

    ' Get the current page from the context
    Dim page As System.Web.UI.Page = TryCast(httpContext.CurrentHandler, System.Web.UI.Page)
    If page Is Nothing Then
    Return Nothing
    End If

    ' Check whether the request was generated by a callback or partial postback
    If page.IsCallback Then
      ' Since the request was issued by a callback, the ID of the calling control
      ' will be stored in the __CALLBACKID request parameter
      Dim controlID As String = httpContext.Request.Params("__CALLBACKID")
      Return controlID
    ' Check whether the request was generated by a partial postback
    ElseIf page.IsPostBack AndAlso Not System.Web.UI.ScriptManager.GetCurrent(page) Is Nothing AndAlso System.Web.UI.ScriptManager.GetCurrent(page).IsInAsyncPostBack Then
      ' Use ScriptManager.ClientID as argument to retrieve control which initiated partial postback.
      Dim postValue As String = httpContext.Request(System.Web.UI.ScriptManager.GetCurrent(page).ClientID)

      ' Use the vertical bar in the argument value to divide items.  The item before the bar is the ClientID of either the ScriptManager
      ' or an UpdatePanel (depending on how the async control is registered).  The UniqueID of the control that initiated the async
      ' request (partial postback) is located after the bar.              
      Dim index As Integer = postValue.IndexOf("|"c)
      Dim controlID As String = postValue.Substring(index + 1)
      Return controlID
    Else ' Not an asynchronous request
      Return Nothing
    End If
  End Function

  ''' <summary>
  ''' Gets the control that created the asynchronous call.
  ''' </summary>
  ''' <returns>Control that initiated the asynchronous call,
  ''' or null if not asynchronous or not found.</returns>
  Public Shared Function GetCallingControl() As System.Web.UI.Control
    ' Get the context of the current request
    Dim httpContext As System.Web.HttpContext = System.Web.HttpContext.Current
    If httpContext Is Nothing Then
    Return Nothing
    End If

    ' Get the current page from the context
    Dim page As System.Web.UI.Page = TryCast(httpContext.CurrentHandler, System.Web.UI.Page)
    If page Is Nothing Then
    Return Nothing
    End If
    Dim controlID As String = GetCallingControlID()

    If (Not String.IsNullOrEmpty(controlID)) Then
      Dim control As System.Web.UI.Control = page.FindControl(controlID)

      Return control
    Else ' Not an asynchronous request
      Return Nothing
    End If
  End Function

  ''' <summary>
  ''' Gets the name of the map tool that created the asynchronous call.
  ''' </summary>
  ''' <param name="mapUniqueID">The unique id of the map control</param>
  ''' <returns>The name of the tool</returns>
  Public Shared Function GetCallingMapTool(ByVal mapUniqueID As String) As String
    ' Get the context of the current request
    Dim httpContext As System.Web.HttpContext = System.Web.HttpContext.Current
    If httpContext Is Nothing Then
    Return Nothing
    End If

    ' Get the current page from the context
    Dim page As System.Web.UI.Page = TryCast(httpContext.CurrentHandler, System.Web.UI.Page)
    If page Is Nothing Then
    Return Nothing
    End If

    ' Check whether the request was generated by a callback or partial postback
    If page.IsCallback Then
      Dim keyValColl As NameValueCollection = CallbackUtility.ParseStringIntoNameValueCollection(page.Request.Form("__CALLBACKPARAM"))
      Dim mapModeKey As String = mapUniqueID & "_mode"
      Dim mapModeVal As String = keyValColl(mapModeKey)
      Return mapModeVal
    ' Check whether the request was generated by a partial postback
    ElseIf page.IsPostBack AndAlso Not System.Web.UI.ScriptManager.GetCurrent(page) Is Nothing AndAlso System.Web.UI.ScriptManager.GetCurrent(page).IsInAsyncPostBack Then
      Dim keyValColl As NameValueCollection = CallbackUtility.ParseStringIntoNameValueCollection(page.Request.Form("__EVENTARGUMENT"))
      Dim mapModeKey As String = mapUniqueID & "_mode"
      Dim mapModeVal As String = keyValColl(mapModeKey)
      Return mapModeVal
    End If
    Return Nothing
  End Function

End Class