This is a migrated thread and some comments may be shown as answers.

Responding to Cancel button click on server-side

2 Answers 154 Views
Upload (Obsolete)
This is a migrated thread and some comments may be shown as answers.
ColinBowern
Top achievements
Rank 1
ColinBowern asked on 13 Apr 2010, 08:12 PM
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 Answers, 1 is accepted

Sort by
0
ColinBowern
Top achievements
Rank 1
answered on 14 Apr 2010, 05:10 PM
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> 
 

0
Genady Sergeev
Telerik team
answered on 15 Apr 2010, 03:41 PM
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.
Tags
Upload (Obsolete)
Asked by
ColinBowern
Top achievements
Rank 1
Answers by
ColinBowern
Top achievements
Rank 1
Genady Sergeev
Telerik team
Share this question
or