如何取消当前从另一个ActionResult方法运行的ActionResult方法?

时间:2017-09-08 03:52:31

标签: javascript c# jquery asp.net-mvc ajax-request

在我的MVC网站上有显示流程数据的按钮。此按钮调用ActionResult方法“ProcessData”。

public ActionResult ProcessData()
    {
        bool isComplete = false;
        string errMessage = "";
        try
        {
            //Calculate something that take long time.


            isComplete = true;
        }
        catch (Exception e)
        {
            errMessage = e.Message;
        }


        return Json(new { IsComplete = isComplete, ErrorMessage = errMessage });
    }

取消过程的第二个按钮。此按钮调用ActionResult方法“CancelProcessData”。

public ActionResult CancelProcessData()
    {
        bool isCancelComplete = false;
        string errMessage = "";
        try
        {
            //Cancel Process Data


            isCancelComplete = true;
        }
        catch (Exception e)
        {
            errMessage = e.Message;
        }


        return Json(new { IsCancelComplete = isCancelComplete , ErrorMessage = errMessage });
    }
  1. 当用户点击进程按钮时,数据正在处理并需要很长时间。
  2. 我希望用户能够通过点击取消按钮来取消流程。
  3. 如何取消当前从另一个ActionResult方法运行的ActionResult方法?请介绍一下。

    P.S。抱歉英语技能不好。

    编辑1:这是ProcessData.cshtml中的代码

    <script>
        function ProcessData() {
            var actionUrl = '@Url.Action("ProcessData", "Home")';
            $.ajax({
                type: "POST",
                url: actionUrl,
                contentType: "application/Json",
                success: function (result) {
                    if (result.IsComplete) {
                        var reUrl = '@Url.Action("Index", "Home")';
                        window.location = reUrl;
                    }
                },
                error: function () {
                    alert("Error");
                }
            });
        }
    
        function CancelProcessData() {
            var actionUrl = '@Url.Action("CancelProcessData", "Home")';
            $.ajax({
                type: "POST",
                url: actionUrl,
                contentType: "application/Json",
                success: function (result) {
                    if (result.IsComplete) {
                        alert("Cancel Complete");
                    }
                },
                error: function () {
                    alert("Error");
                }
            });
        }
    </script>
    
    <button onclick="ProcessData();">Process Data</button>
    <button onclick="CancelProcessData();">Cancel Process Data</button>
    

    结束编辑1

    编辑2:我搜索了很长时间。我找到了取消过程的解决方案。此代码显示

    public async System.Threading.Tasks.Task<ActionResult> ProcessData()
        {
            bool isComplete = false;
            bool isCancel = false;
            string errMessage = ""; 
            try
            {
                await System.Threading.Tasks.Task.Run(() => {
                    for (int i = 0;i< Int32.MaxValue; i++)
                    {
                        if (HttpContext.Response.ClientDisconnectedToken.IsCancellationRequested)
                        {
                            isCancel = true;
                            break;
                        }
                    }
                });
    
                isComplete = true;
            }
            catch (Exception e)
            {
                errMessage = e.Message;
            }
    
    
            return Json(new { IsComplete = isComplete, ErrorMessage = errMessage, IsCancel = isCancel });
        }
    

    以下是脚本功能

    <script>
        var ajaxProcessDatarequest;
        function ProcessData() {
            var actionUrl = '@Url.Action("ProcessData", "Home")';
            ajaxProcessDatarequest = $.ajax({
                type: "POST",
                url: actionUrl,
                contentType: "application/Json",
                success: function (result) {
                    if (result.IsComplete) {
                        if (!result.IsCancel) {
                            var reUrl = '@Url.Action("Index", "Home")';
                            window.location = reUrl;
                        }
                    }
                },
                error: function () {
                    alert("Error");
                }
            });
        }
    
        function CancelProcessData() {
            ajaxProcessDatarequest.abort();
        }
    </script>
    

    结束编辑2

1 个答案:

答案 0 :(得分:0)

(现在,我不确定会话值是否在Http请求中保持不变或更新)

这取决于您正在运行的流程类型。它不会停止任何正在运行的进程,但它可以撤消并停止进一步处理。

在您的javascript中创建一个名为processTimeStamp的变量。注意,它的声明必须在这两个函数之外。在调用流程数据之前,请分配processTimeStamp,这将是ProcessDataCancelProcessData方法的参数。由于变量在全局范围内,因此将向这两种方法发送相同的值。

<script>
    var processTimeStamp;
    function ProcessData() {
        var actionUrl = '@Url.Action("ProcessData", "Home")';
        processTimeStamp = new Date().getTime().toString();

        $.ajax({
            type: "POST",
            url: actionUrl,
            data: {
              processTimeStamp: processTimeStamp 
            },
            contentType: "application/Json",
            success: function (result) {
                if (result.IsComplete) {
                    var reUrl = '@Url.Action("Index", "Home")';
                    window.location = reUrl;
                } else if (result.IsCancelComplete) {
                     alert("process was cancelled");
                }
            },
            error: function () {
                alert("Error");
            }
        });
    }

    function CancelProcessData() {
        var actionUrl = '@Url.Action("CancelProcessData", "Home")';
        $.ajax({
            type: "POST",
            url: actionUrl,
            data: {
              processTimeStamp: processTimeStamp 
            },
            contentType: "application/Json",
            success: function (result) {
            },
            error: function () {
                alert("Error");
            }
        });
    }
</script>

<强>控制器

CancelProcessData方法中,将processTimeStamp的值指定给Session["CancelProcessTimestamp"]。你根本无法知道这个过程是否被取消。

ProcessData方法中,检查processTimeStamp是否通过,是否与每个进程前的Session["CancelProcessTimestamp"]相同。我的意思是你没有任何选择。 (有点像你在任务并行库中处理CancellationToken的方式)

public ActionResult ProcessData(string processTimeStamp)
{
    bool isComplete = false;
    bool isCancelComplete = false;
    string errMessage = "";

    try
    {

        // process 1 <-- this starts immediately. So you can't stop that.

        if( Convert.ToString(Session["CancelProcessTimestamp"]) != processTimeStamp)
        {
           // process 2
        }
        else
        {
           isCancelComplete = true;
        }

        // OTHER PROCESSES

        if(Convert.ToString(Session["CancelProcessTimestamp"]) != processTimeStamp)
        {
           // update to database
           isComplete = true; // only if it completes the last process
        }
        else
        {
           // you can undo the work done in process 1, 2 etc. 
           // Like deleting an uploaded file. Or if any primary key is returned from Process 1, then delete the corresponding entry in Data base
           isCancelComplete = true;
        }
    }
    catch (Exception e)
    {
        errMessage = e.Message;
    }

    return Json(new { IsComplete = isComplete, IsCancelComplete = isCancelComplete , ErrorMessage = errMessage });
}


public ActionResult CancelProcessData(string processTimeStamp)
{
    Session["CancelProcessTimestamp"] = processTimeStamp;
    return Json(true);
}