Responding to Cancel button click on server-side

Thread is closed for posting
3 posts, 0 answers
  1. ColinBowern
    ColinBowern avatar
    51 posts
    Member since:
    Aug 2012

    Posted 13 Apr 2010 Link to this post

    When using the RadProgressArea in a custom monitoring scenario what is the prescribed way to handle the cancel operation on the server side?  I am looping through a collection of items, doing stuff and I want to check something like RadProgressContext.Current.HasCancelBeenClicked.  Here is what I have so far.  I am getting some odd behavior on cancel along with the progress bar percentage part not updating.  If you try to invoke it a second time nothing updates.

    Default.aspx:
    <%@ Page Language="C#" AutoEventWireup="true" %> 
     
    <%@ Import Namespace="System.Collections.Generic" %> 
    <%@ Import Namespace="System.Threading" %> 
    <%@ Import Namespace="Telerik.Web.UI" %> 
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 
    <html xmlns="http://www.w3.org/1999/xhtml"
    <head runat="server"
        <title>Long running operation with Cancel support example</title> 
        <style type="text/css"
            .Hide 
            { 
                display: none; 
            } 
        </style> 
    </head> 
    <body> 
        <form id="form1" runat="server"
        <telerik:RadScriptManager ID="ScriptManager" runat="server" EnableHistory="true" 
            EnableScriptCombine="true" OutputCompression="AutoDetect"
            <Scripts> 
                <asp:ScriptReference Assembly="Telerik.Web.UI" Name="Telerik.Web.UI.Common.Core.js" /> 
                <asp:ScriptReference Assembly="Telerik.Web.UI" Name="Telerik.Web.UI.Common.jQuery.js" /> 
            </Scripts> 
        </telerik:RadScriptManager> 
        <telerik:RadAjaxLoadingPanel ID="AjaxLoadingPanel" runat="server" Skin="Default" /> 
        <telerik:RadAjaxManager ID="AjaxManager" runat="server" DefaultLoadingPanelID="AjaxLoadingPanel"
            <AjaxSettings> 
                <telerik:AjaxSetting AjaxControlID="DoWork"
                    <UpdatedControls> 
                        <telerik:AjaxUpdatedControl ControlID="DoWork" UpdatePanelRenderMode="Inline" /> 
                    </UpdatedControls> 
                </telerik:AjaxSetting> 
                <telerik:AjaxSetting AjaxControlID="CancelWork"
                    <UpdatedControls> 
                        <telerik:AjaxUpdatedControl ControlID="CancelWork" UpdatePanelRenderMode="Inline" /> 
                    </UpdatedControls> 
                </telerik:AjaxSetting> 
            </AjaxSettings> 
        </telerik:RadAjaxManager> 
        <telerik:RadWindowManager ID="WindowManager" runat="server" /> 
        <asp:Button ID="ShowOptionsDialog" runat="server" CausesValidation="false" OnClientClick="ShowOptionsDialog_Click(); return false;" 
            Text="Go!" /> 
        <asp:Button ID="DoWork" runat="server" CausesValidation="false" CssClass="Hide" OnClick="DoWork_Click" /> 
        <asp:Button ID="CancelWork" runat="server" CausesValidation="false" CssClass="Hide" 
            OnClick="CancelWork_Click" /> 
        <asp:HiddenField ID="DoWorkParameters" runat="server" /> 
        <asp:HiddenField ID="OperationId" runat="server" /> 
        <telerik:RadCodeBlock runat="server"
            <script type="text/javascript"
                window.$ = $telerik.$; 
     
                function ShowOptionsDialog_Click() { 
                    var optionsDialog = $find('<%= OptionsDialog.ClientID %>'); 
                    optionsDialog.show(); 
                } 
     
                function OptionsDialog_Close(sender, e) { 
                    var result = e.get_argument(); 
                    if (result) { 
                        var progressArea = $find($('[id$=_ProgressArea]').attr('id')); 
                        progressArea.show(); 
     
                        var cancelButton = progressArea._findElement("CancelButton"); 
                        $addHandlers(cancelButton, { "click": ProgressDialog_Cancel }, this); 
     
                        var progressDialog = $find('<%= ProgressDialog.ClientID %>'); 
                        progressDialog.show(); 
     
                        $('<%= "#" + DoWorkParameters.ClientID %>').val(result); 
     
                        // TODO: get an operation ID with AJAX 
                        var operationId = "{EE1B4300-CF80-4CF1-9C01-5E6412DAEC00}"
     
                        $('<%= "#" + OperationId.ClientID %>').val(operationId); 
                        $get('<%= DoWork.ClientID %>').click(sender, e); 
                    } 
                } 
     
                function ProgressDialog_Cancel(sender, e) { 
                    $get('<%= CancelWork.ClientID %>').click(sender, e); 
                    return false; 
                } 
     
                function ProgressDialog_Close(title, message) { 
                    var progressArea = $find($('[id$=_ProgressArea]').attr('id')); 
                    progressArea.hide(); 
     
                    var progressDialog = $find('<%= ProgressDialog.ClientID %>'); 
                    progressDialog.close(); 
     
                    var resultsDialog = $find('<%= ResultsDialog.ClientID %>'); 
                    resultsDialog.set_title(title); 
                    resultsDialog.argument = message
                    resultsDialog.show(); 
                } 
     
                Sys.WebForms.PageRequestManager.getInstance().add_beginRequest(BeginRequestHandler); 
                function BeginRequestHandler(sender, args) { 
                    var elem = args.get_postBackElement(); 
                    if (elem.id == '<%= CancelWork.ClientID %>') { 
                        args.set_cancel(false); 
                    } 
                } 
            </script> 
        </telerik:RadCodeBlock> 
        <telerik:RadWindow ID="OptionsDialog" runat="server" Behaviors="Move, Resize, Close" 
            KeepInScreenBounds="true" Modal="true" NavigateUrl="~/Options.aspx" OnClientClose="OptionsDialog_Close" 
            ReloadOnShow="true" ShowContentDuringLoad="false" Title="Operation Options" VisibleStatusbar="false" /> 
        <telerik:RadWindow ID="ProgressDialog" runat="server" Behaviors="None" KeepInScreenBounds="true" 
            Height="250px" Modal="true" ShowContentDuringLoad="false" VisibleTitlebar="false" 
            VisibleStatusbar="false" Width="500px"
            <ContentTemplate> 
                <telerik:RadProgressArea ID="ProgressArea" runat="server" DisplayCancelButton="true" 
                    ProgressIndicators="CurrentFileName,TimeElapsed,TimeEstimated,TotalProgress,TotalProgressBar,TotalProgressPercent" 
                    Width="100%" /> 
                <telerik:RadProgressManager ID="ProgressManager" runat="server" /> 
            </ContentTemplate> 
        </telerik:RadWindow> 
        <telerik:RadWindow ID="ResultsDialog" runat="server" Behaviors="Move, Resize, Close" 
            KeepInScreenBounds="true" Modal="true" NavigateUrl="~/Results.aspx" ReloadOnShow="true" 
            ShowContentDuringLoad="false" VisibleStatusbar="false" /> 
        </form> 
    </body> 
    </html> 
    <script runat="server"
         
        static Dictionary<Guid, WorkState> stateDictionary = new Dictionary<Guid, WorkState>(); 
     
        protected void DoWork_Click(object sender, EventArgs e) 
        { 
            var stateId = new Guid(OperationId.Value); 
            stateDictionary.Add(stateId, new WorkState { Argument = DoWorkParameters.Value }); 
     
            ThreadPool.QueueUserWorkItem(DoActualWork, stateId); 
     
            var state = stateDictionary[stateId]; 
            while (!state.IsComplete) 
            { 
                RadProgressContext.Current.CurrentOperationText = state.Message ?? string.Empty; 
                RadProgressContext.Current.PrimaryPercent = state.PercentComplete; 
                Thread.Sleep(500); 
            } 
     
            var resultTitle = !state.IsAborted ? "Operation successful!" : "Operation failed."; 
            var resultMessage = !state.IsAborted ? "Your request was fulfilled." : "Your request was canceled"; 
            RadProgressContext.Current.OperationComplete = true
            RadAjaxManager.GetCurrent(this).ResponseScripts.Add(string.Format("ProgressDialog_Close('{0}', '{1}');", resultTitle, resultMessage)); 
            stateDictionary.Remove(stateId); 
        } 
     
        protected void CancelWork_Click(object sender, EventArgs e) 
        { 
            var stateId = new Guid(OperationId.Value); 
            if (stateDictionary.ContainsKey(stateId)) 
            { 
                stateDictionary[stateId].AbortRequested = true
            } 
        } 
     
        void DoActualWork(object o) 
        { 
            var state = stateDictionary[(Guid)o]; 
            var maxItems = 20
     
            for (var itemIndex = 0; itemIndex < maxItems; itemIndex++) 
            { 
                System.Diagnostics.Debug.Write(itemIndex); 
     
                state.Message = string.Format("Operation {0} - {1}", state.Argument, itemIndex); 
                state.PercentComplete = itemIndex / maxItems * 100; 
                Thread.Sleep(1000); 
     
                if (state.AbortRequested) 
                { 
                    state.IsAborted = true
                    break; 
                } 
            } 
            state.IsComplete = true
        } 
     
        class WorkState 
        { 
            public object Argument; 
            public string Message; 
            public int PercentComplete; 
            public bool IsComplete; 
            public bool AbortRequested; 
            public bool IsAborted; 
        } 
    </script> 
     

    Options.aspx:
    <%@ Page Language="C#" AutoEventWireup="true" %> 
     
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 
    <html xmlns="http://www.w3.org/1999/xhtml"
    <body> 
        <form id="form1" runat="server"
        <div> 
            <input id="Name" type="text" value="Calculate Pii" /> 
        </div> 
        <div> 
            <button onclick="Close(document.getElementById('Name').value);"
                Go!</button> 
            <button onclick="Close(null);"
                Cancel</button> 
        </div> 
        <script type="text/javascript"
            function GetRadWindow() { 
                var radWindow = null
                if (window.radWindow) { 
                    radWindow = window.radWindow; 
                } 
                else if (window.frameElement.radWindow) { 
                    radWindow = window.frameElement.radWindow; 
                } 
                return radWindow; 
            } 
     
            function Close(returnValue) { 
                var radWindow = GetRadWindow(); 
                if (returnValue == undefined) { 
                    radWindow.argument = null
                    radWindow.close(); 
                } 
                else { 
                    radWindow.close(returnValue); 
                } 
            } 
        </script> 
        </form> 
    </body> 
    </html> 
     


    Result.aspx:

    <%@ Page Language="C#" AutoEventWireup="true" %> 
     
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 
    <html xmlns="http://www.w3.org/1999/xhtml"
    <head runat="server"
    </head> 
    <body> 
        <form id="form1" runat="server"
        <telerik:RadScriptManager ID="ScriptManager" runat="server" EnableHistory="true" 
            EnableScriptCombine="true" OutputCompression="AutoDetect"
            <Scripts> 
                <asp:ScriptReference Assembly="Telerik.Web.UI" Name="Telerik.Web.UI.Common.Core.js" /> 
                <asp:ScriptReference Assembly="Telerik.Web.UI" Name="Telerik.Web.UI.Common.jQuery.js" /> 
            </Scripts> 
        </telerik:RadScriptManager> 
        <div id="Message"
        </div> 
        <input type="button" value="Close" onclick="Close(null);" /> 
        <script type="text/javascript"
            window.$ = $telerik.$; 
     
            function GetRadWindow() { 
                var radWindow = null
                if (window.radWindow) { 
                    radWindow = window.radWindow; 
                } 
                else if (window.frameElement.radWindow) { 
                    radWindow = window.frameElement.radWindow; 
                } 
                return radWindow; 
            } 
     
            function Close(returnValue) { 
                var radWindow = GetRadWindow(); 
                if (returnValue == undefined) { 
                    radWindow.argument = null
                    radWindow.close(); 
                } 
                else { 
                    radWindow.close(returnValue); 
                } 
            } 
     
            $(document).ready(function () { 
                var window = GetRadWindow(); 
                $("#Message").text(window.argument); 
            }); 
        </script> 
        </form> 
    </body> 
    </html> 
     

  2. ColinBowern
    ColinBowern avatar
    51 posts
    Member since:
    Aug 2012

    Posted 14 Apr 2010 Link to this post

    I have managed to get a bit further on this.  The only thing I am struggling with is that the progress bar isn't updating at all.

    <%@ Page Language="C#" AutoEventWireup="true" Async="true" %> 
     
    <%@ Import Namespace="System.Collections.Generic" %> 
    <%@ Import Namespace="System.Threading" %> 
    <%@ Import Namespace="Telerik.Web.UI" %> 
    <%@ Import Namespace="System.ComponentModel" %> 
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 
    <html xmlns="http://www.w3.org/1999/xhtml"
    <head runat="server"
        <title>Long running operation with Cancel support example</title> 
        <style type="text/css"
            .Hide 
            { 
                display: none; 
            } 
        </style> 
    </head> 
    <body> 
        <form id="form1" runat="server"
        <telerik:RadScriptManager ID="ScriptManager" runat="server" EnableHistory="true" 
            EnableScriptCombine="true" OutputCompression="AutoDetect"
            <Scripts> 
                <asp:ScriptReference Assembly="Telerik.Web.UI" Name="Telerik.Web.UI.Common.Core.js" /> 
                <asp:ScriptReference Assembly="Telerik.Web.UI" Name="Telerik.Web.UI.Common.jQuery.js" /> 
            </Scripts> 
        </telerik:RadScriptManager> 
        <telerik:RadAjaxLoadingPanel ID="AjaxLoadingPanel" runat="server" Skin="Default" /> 
        <telerik:RadAjaxManager ID="AjaxManager" runat="server" DefaultLoadingPanelID="AjaxLoadingPanel"
            <AjaxSettings> 
                <telerik:AjaxSetting AjaxControlID="DoWork"
                    <UpdatedControls> 
                        <telerik:AjaxUpdatedControl ControlID="DoWork" UpdatePanelRenderMode="Inline" /> 
                    </UpdatedControls> 
                </telerik:AjaxSetting> 
                <telerik:AjaxSetting AjaxControlID="CancelWork"
                    <UpdatedControls> 
                        <telerik:AjaxUpdatedControl ControlID="CancelWork" UpdatePanelRenderMode="Inline" /> 
                    </UpdatedControls> 
                </telerik:AjaxSetting> 
            </AjaxSettings> 
        </telerik:RadAjaxManager> 
        <telerik:RadWindowManager ID="WindowManager" runat="server" /> 
        <asp:Button ID="ShowOptionsDialog" runat="server" CausesValidation="false" OnClientClick="ShowOptionsDialog_Click(); return false;" 
            Text="Go!" /> 
        <asp:Button ID="DoWork" runat="server" CausesValidation="false" CssClass="Hide" OnClick="DoWork_Click" /> 
        <asp:HiddenField ID="DoWorkParameters" runat="server" /> 
        <asp:HiddenField ID="OperationId" runat="server" /> 
        <telerik:RadCodeBlock runat="server"
            <script type="text/javascript"
                window.$ = $telerik.$; 
     
                function ShowOptionsDialog_Click() { 
                    var optionsDialog = $find('<%= OptionsDialog.ClientID %>'); 
                    optionsDialog.show(); 
                } 
     
                function OptionsDialog_Close(sender, e) { 
                    var result = e.get_argument(); 
                    if (result) { 
                        $('<%= "#" + DoWorkParameters.ClientID %>').val(result); 
     
                        var progressArea = $find($('[id$=_ProgressArea]').attr('id')); 
     
                        // Replace cancel button to prevent original POST from being aborted 
                        var cancelButton = progressArea._findElement("CancelButton"); 
                        $('#' + cancelButton.id).after('<input id="ProgressDialog_C_ProgressArea_Panel_CancelButton" class="ruButton ruCancel" type="button" value="Cancel" tabindex="-1" />').remove();  
                        $('#' + cancelButton.id).bind('click', ProgressDialog_Cancel); 
     
                        // Reset the progress area view in case this is the second operation 
                        progressArea.update({ PrimaryPercent: 0, CurrentOperationText: 'Initializing...', InProgress: true }); 
                        progressArea.show(); 
     
                        var progressDialog = $find('<%= ProgressDialog.ClientID %>'); 
                        progressDialog.show(); 
     
                        // Get a new operation ID and kick off the work operation 
                        $.ajax({ 
                            contentType: "application/json; charset=utf-8", 
                            data: "{}", 
                            type: "POST", 
                            url: "Default.aspx/GetOperationId", 
                            success: function (msg) { 
                                $('<%= "#" + OperationId.ClientID %>').val(msg.d); 
                                $get('<%= DoWork.ClientID %>').click(sender, e); 
                            } 
                        }); 
                    } 
                } 
     
                function ProgressDialog_Cancel(sender, e) { 
                    $.ajax({ 
                        contentType: 'application/json; charset=utf-8', 
                        data: '{\'operationId\':\'' + $('<%= "#" + OperationId.ClientID %>').val() + '\'}', 
                        type: 'POST', 
                        url: 'Default.aspx/CancelOperation', 
                    }); 
                } 
     
                function ProgressDialog_Close(title, message) { 
                    var progressArea = $find($('[id$=_ProgressArea]').attr('id')); 
                    progressArea.hide(); 
     
                    var progressDialog = $find('<%= ProgressDialog.ClientID %>'); 
                    progressDialog.close(); 
     
                    var resultsDialog = $find('<%= ResultsDialog.ClientID %>'); 
                    resultsDialog.set_title(title); 
                    resultsDialog.argument = message
                    resultsDialog.show(); 
                } 
            </script> 
        </telerik:RadCodeBlock> 
        <telerik:RadWindow ID="OptionsDialog" runat="server" Behaviors="Move, Resize, Close" 
            KeepInScreenBounds="true" Modal="true" NavigateUrl="~/Options.aspx" OnClientClose="OptionsDialog_Close" 
            ReloadOnShow="true" ShowContentDuringLoad="false" Title="Operation Options" VisibleStatusbar="false" /> 
        <telerik:RadWindow ID="ProgressDialog" runat="server" Behaviors="None" KeepInScreenBounds="true" 
            Height="250px" Modal="true" ShowContentDuringLoad="false" VisibleTitlebar="false" 
            VisibleStatusbar="false" Width="500px"
            <ContentTemplate> 
                <telerik:RadProgressArea ID="ProgressArea" runat="server" DisplayCancelButton="true" 
                    ProgressIndicators="CurrentFileName,TimeElapsed,TotalProgressBar,TotalProgressPercent" 
                    Width="100%" /> 
                <telerik:RadProgressManager ID="ProgressManager" runat="server" /> 
            </ContentTemplate> 
        </telerik:RadWindow> 
        <telerik:RadWindow ID="ResultsDialog" runat="server" Behaviors="Move, Resize, Close" 
            KeepInScreenBounds="true" Modal="true" NavigateUrl="~/Results.aspx" ReloadOnShow="true" 
            ShowContentDuringLoad="false" VisibleStatusbar="false" /> 
        </form> 
    </body> 
    </html> 
    <script runat="server"
        static Dictionary<Guid, WorkState> stateDictionary = new Dictionary<Guid, WorkState>(); 
     
        [System.Web.Services.WebMethod] 
        public static string GetOperationId() 
        { 
            var stateId = Guid.NewGuid(); 
            stateDictionary.Add(stateId, new WorkState()); 
            return stateId.ToString("B"); 
        } 
         
        protected void DoWork_Click(object sender, EventArgs e) 
        { 
            RadProgressContext.Current.OperationComplete = false
     
            var stateId = new Guid(OperationId.Value); 
            var state = stateDictionary[stateId]; 
     
            state.Argument = DoWorkParameters.Value; 
            ThreadPool.QueueUserWorkItem(DoActualWork, stateId); 
     
            while (!state.IsComplete) 
            { 
                RadProgressContext.Current.CurrentOperationText = state.Message ?? string.Empty; 
                RadProgressContext.Current.PrimaryPercent = state.PercentComplete; 
                Thread.Sleep(500); 
            } 
     
            var resultTitle = !state.IsAborted ? "Operation successful!" : "Operation failed."; 
            var resultMessage = !state.IsAborted ? "Your request was fulfilled." : "Your request was canceled"; 
            RadProgressContext.Current.OperationComplete = true
            RadAjaxManager.GetCurrent(this).ResponseScripts.Add(string.Format("ProgressDialog_Close('{0}', '{1}');", resultTitle, resultMessage)); 
     
            stateDictionary.Remove(stateId); 
        } 
     
        protected void DoActualWork(object o) 
        { 
            var state = stateDictionary[(Guid)o]; 
            try 
            { 
                var maxItems = 15
                for (var itemIndex = 0; itemIndex < maxItems; itemIndex++) 
                { 
                    System.Diagnostics.Debug.Write(itemIndex); 
                    state.Message = string.Format("{0} - {1}", state.Argument, itemIndex); 
                    state.PercentComplete = itemIndex / maxItems * 100; 
     
                    Thread.Sleep(1000); 
     
                    if (state.AbortRequested) 
                    { 
                        state.IsAborted = true
                        break; 
                    } 
                } 
            } 
            catch (Exception exception) 
            { 
                state.Error = exception
                state.IsAborted = true
            } 
            finally 
            { 
                state.IsComplete = true
            } 
        } 
     
        [System.Web.Services.WebMethod] 
        public static void CancelOperation(string operationId) 
        { 
            var stateId = new Guid(operationId); 
            if (stateDictionary.ContainsKey(stateId)) 
            { 
                stateDictionary[stateId].AbortRequested = true
            } 
        } 
     
        class WorkState 
        { 
            public object Argument; 
            public string Message; 
            public int PercentComplete; 
            public bool IsComplete; 
            public bool AbortRequested; 
            public bool IsAborted; 
            public Exception Error; 
        } 
    </script> 
     

  3. UI for ASP.NET Ajax is Ready for VS 2017
  4. Genady Sergeev
    Admin
    Genady Sergeev avatar
    1596 posts

    Posted 15 Apr 2010 Link to this post

    Hello ColinBowern,

    The code that you have posted throws JavaScript errors. They come from the following function, the last line:

    function ProgressDialog_Cancel(sender, e) {
        $.ajax({
            contentType: 'application/json; charset=utf-8',
            data: '{\'operationId\':\'' + $('<%= "#" + OperationId.ClientID %>').val() + '\'}',
            type: 'POST',
            url: 'Default.aspx/CancelOperation',
        });

    There is one extra comma on the last line, you need to remove it in order to function properly. So, the last line should look like this:

    url: 'Default.aspx/CancelOperation'
        });

    without the comma.

    Is the area still failing to appear?

    Greetings,
    Genady Sergeev
    the Telerik team

    Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items.
Back to Top