web-dev-qa-db-fra.com

Barre de progression pour les appels de longue durée au serveur dans ASP.Net MVC

Je veux juste créer une barre de progression lors de longs appels au serveur. Je ne pouvais pas créer de demande de message ajax auprès du contrôleur alors que celui-ci effectuait un travail long. 

Je souhaite créer une action supplémentaire pour obtenir l'état réel de la tâche longue et courante en cours. J'ai essayé de créer un sondage dans une requête ajax, puis je peux renvoyer l’état du côté serveur et l’afficher dans une barre de progression côté client. Des idées ? 

Le moyen le plus simple et le plus simple de procéder consiste à utiliser SignalR. Téléchargez Microsoft SignalR dans https://www.nuget.org/packages/Microsoft.AspNet.SignalR/2.1.2

Créez une classe hub dans un dossier distinct du chemin du projet appelé hubs, ajoutez deux fichiers de classe dans le dossier hubs.

Startup.cs

using Owin;
using Microsoft.Owin;
[Assembly: OwinStartup(typeof(SignalRChat.Startup))]
namespace SignalRChat
{
    public class Startup
    {
        public void Configuration(IAppBuilder app)
        {
            // Any connection or hub wire up and configuration should go here
            app.MapSignalR();
        }
    }
}

ProgressHub.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Web;
using Microsoft.AspNet.SignalR;

namespace RealTimeProgressBar
{
    public class ProgressHub : Hub
    {

        public string msg = "Initializing and Preparing...";
        public int count = 1;

        public static void SendMessage(string msg , int count)
        {
            var message = "Process completed for " + msg;
            var hubContext = GlobalHost.ConnectionManager.GetHubContext<ProgressHub>();
            hubContext.Clients.All.sendMessage(string.Format(message), count);
        }

        public void GetCountAndMessage()
        {
            Clients.Caller.sendMessage(string.Format(msg), count);
        }
    }
}

Dans le contrôleur,

// assemblies
using Microsoft.AspNet.SignalR;
using RealTimeProgressBar;   


//call this method inside your working action
ProgressHub.SendMessage("initializing and preparing",  2);

En vue,

<!--The jQuery library is required and is referenced by default in _Layout.cshtml. -->
<!--Reference the SignalR library. -->
<script src="~/Scripts/jquery.signalR-2.1.2.min.js"></script>
<!--Reference the autogenerated SignalR hub script. -->
<script src="~/signalr/hubs"></script>
<!--SignalR script to update the chat page and send messages.--> 
<script type="text/javascript">
  $(document).ready(function () {

    $("#progressBar").kendoProgressBar({
        min: 0,
        max: 100,
        type: "percent",
    });
});

function StartInvoicing()
{
    var progressNotifier = $.connection.progressHub;

    // client-side sendMessage function that will be called from the server-side
    progressNotifier.client.sendMessage = function (message, count) {
        // update progress
        UpdateProgress(message, count);
        //alert(message);
    };

    // establish the connection to the server and start server-side operation
    $.connection.hub.start().done(function () {
        // call the method CallLongOperation defined in the Hub
        progressNotifier.server.getCountAndMessage();
    });
}

// Update the progress bar 
function UpdateProgress(message, count) {
    var result = $("#result");
    result.html(message);
    $("#progressBar").data("kendoProgressBar").value(count);
}
</script>

Pour plus de détails, consultez certains articles existants à l'aide de Google.

J'ai eu un service de longue date pour cela, j'ai donné une idée de base ci-dessous. Utilisez-le selon vos besoins. 

  1. J'ai structuré les arguments de progression ProgressArgs
  2. Dans le service long LongRunningProcess (), mis à jour les valeurs de progression à intervalle régulier et enregistré au format JSON dans la base de données
  3. Création d'une méthode d'action getProgress() qui renverra une progression de chaîne JSON par ajax.
  4. Création d'une fonction Javascript getProgress() qui, une fois démarrée, appelle le serveur à intervalles réguliers pour continuer jusqu'à la fin du processus.

J'ai donné un exemple approximatif pour le mettre en œuvre. J'espère que cela peut vous aider.

La classe des arguments de progression

public class ProgressArgs
{
    public int Completed { get; set; }
    public int Total { get; set; }
    public int Percentage { get; set; }
    public string Status { get; set; }
}

Dans le processus, j'ai continué à mettre à jour les statistiques dans la base de données

    public void LongRunningProcess()
    {

        ProgressArgs result = new ProgressArgs();
        result.Completed = 0;
        result.Total = userList.Count;
        foreach (var item in itemList)
        {
           //Do Some processing which u want to do

            result.Total++;
            result.Percentage = (result.Completed * 100) / result.Total;
            result.Status = "Processing";
            string strToSave = Newtonsoft.Json.JsonConvert.SerializeObject(result);
            //update the strToSave to the database somewhere.
        }

        //after completing of processing
        result.Total++;
        result.Percentage = (result.Completed * 100) / result.Total;
        result.Status = "Completed";
        string strToSave = Newtonsoft.Json.JsonConvert.SerializeObject(result);
        //update the strToSave to the database somewhere.

    }

L'action C # pour obtenir le progrès par ajax 

    public string getProgress()
    {    
        string strJSON = config.GetValue("progress");  //Get stats from the database which is saved in json
        return strJSON;
    }

Le code Javascript

//Ajax Get Progress function
    function getProgress() {
        var dataToSend = '';
        $.ajax({
            url: '@Url.Action("getProgress")', //Link to the action method
            type: 'POST',
            contentType: 'application/json; charset=utf-8',
            data: dataToSend,
            success: function (response) {
                console.log(response);
                if (response != null) {
                    data = JSON.parse(response);
                    console.log(data);
                    //update the progressbar
                    progressbar.progressbar("value", data.Percentage);
                    //When the jobalert status is completed clear the interval
                    if (data.Status == 0) {
                        setTimeout(getProgress, 800); //TImout function to call the respective function at that time
                    }
                    serviceCompleted(data); function to call after completing service
                }
            },
            error: function (xhr) {
                alert('Error: There was some error while posting question. Please try again later.');
            }
        });
    }
1
Pratik Bhoir