Call back from server to client

2020-07-31 05:38发布

问题:

I am using ASP.NET MVC 4 application, I need to Display messages in the Client, by sending messages from Controller to Client.

My requirement is user click a button in UI and i will process the files on the server and Display message in UI on end of each foreach file i process. i need to show the File names in the Client Using ASP.NET MVC.

Can any one Help how to show the messages in the Client by calling client method from server on for-each loop each time.

I am able to call the controller and end of each controller I am sending final message to UI, but how to send on each foreach loop iteration?

回答1:

You have to write an ActionResult that progressively write result to the response. so you can show the user some data in every foreach loop iteration. I have written a simple ActionResult that writes a number every 2 seconds:

public class ProgressiveResult : ActionResult
{
    public override void ExecuteResult(ControllerContext context)
    {
        for (int i = 0; i < 20; i++)
        {
            context.HttpContext.Response.Write(i.ToString());
            Thread.Sleep(2000);
            context.HttpContext.Response.Flush();
        }
        context.HttpContext.Response.End();
    }
}

and this is an action that returns this result:

public ActionResult LongProcess()
{
   return new ProgressiveResult();
}

So you can write an ActionResult and write your foreach code in ExecuteResult method.

UPDATE:

You can make this call with an Ajax request and return result with a simple code like the following code:

var result = "";
function showResult() {
    if (result !== oReq.responseText) {
        result = oReq.responseText;
        console.log(result);
    }
}
var oReq = new XMLHttpRequest();
oReq.open("get", "/Home/LongProcess", true);
oReq.send();
setInterval(showResult, 1000);


回答2:

Try this: Script method to update progress based on predefined interval you want

Controller:

public class HomeController : Controller
{
    private static IDictionary<Guid, int> tasks = new Dictionary<Guid, int>();

    public ActionResult Index()
    {
        return View();
    }

    public ActionResult Start()
    {
        var taskId = Guid.NewGuid();
        tasks.Add(taskId, 0);

        Task.Factory.StartNew(() =>
        {
            for (var i = 0; i <= 100; i++)
            {
                tasks[taskId] = i; // update task progress
                Thread.Sleep(50); // simulate long running operation
            }
            tasks.Remove(taskId);
        });

        return Json(taskId);
    }

    public ActionResult Progress(Guid id)
    {
        return Json(tasks.Keys.Contains(id) ? tasks[id] : 100);
    }
}

View:

<script type="text/javascript">

function updateMonitor(taskId, status) {
    $("#" + taskId).html("Task [" + taskId + "]: " + status);
}

$(function () {

    $("#start").click(function (e) {
        e.preventDefault();

        $.post("Home/Start", {}, function (taskId) {

            // Init monitors
            $("#monitors").append($("<p id='" + taskId + "'/>"));
            updateMonitor(taskId, "Started");

            // Periodically update monitors
            var intervalId = setInterval(function () {

                $.post("Home/Progress", { id: taskId }, function (progress) {
                    if (progress >= 100) {
                        updateMonitor(taskId, "Completed");
                        clearInterval(intervalId);
                    } else {
                        updateMonitor(taskId, progress + "%");
                    }
                });

            }, 100);

        });
    });

});

Start new task …