2016-08-11 11 views
2

Web APIメソッドから断続的なステータス応答をjquery ajax呼び出しに送信し、UIの進捗状況を表示する必要があるタスクに取り組んでいます。ASP.NET Web APIメソッドからjquery ajaxへの断続的な応答を送信

enter image description here

当初、jqueryのAJAXは、いくつかのパラメータを渡すウェブAPIメソッドを呼び出しますし、Web APIメソッドは、長時間実行されているアクションを実行するために開始します。各アクションが完了すると、私は、

私がこれまで試してみました何

HTMLを呼び出しjqueryのAjaxの方法に戻って(、手動でいくつかの番号)の割合を送りたいとUIの進歩を示しています。

<div class="row"> 
     <div class="col-xs-12"> 
      <div class="col-xs-3"> 
       <input type="file" id="FileInput" /> 
      </div> 
      <div class="col-xs-1"> 
       <button type="button" class="btn btn-default btn-xs" id="UploadFileBtn">Upload</button> 
      </div> 
     </div> 
    </div> 

活字体:

 instance.importFile.on('change', function() { 
      instance.selectedFile = this.files[0]; 
      // This code is only for demo ... (usage of FileAPI) 
      console.log("name : " + instance.selectedFile.name); 
      console.log("size : " + instance.selectedFile.size); 
      console.log("type : " + instance.selectedFile.type); 
      console.log("date : " + instance.selectedFile.lastModifiedDate); 
     }); 

     $('#UploadFileBtn').on('click', function() { 
      var formData = new FormData(); 
      formData.append('file', instance.selectedFile); 

      $.when(FileUploadService.ProcessData(formData)).done(function() { 
      }).fail(function() { 
       }).progress(function() { 
        console.log("progressing..."); 
      }); 
     }); 

ウェブAPI:

public class FileUploadController : ApiController 
    { 
    [HttpPost] 
    public HttpResponseMessage Upload() 
    { 

     if (HttpContext.Current.Request.Files.Count > 0) 
     { 
      var postedFile = HttpContext.Current.Request.Files[0]; 

      var fileNameParts = postedFile.FileName.Split('\\'); 
      var fileName = fileNameParts[fileNameParts.Length - 1]; 

      fileName = string.Format("{0}_{1}", DateTime.Now.Ticks.ToString(), fileName); 
      string filePath = Path.Combine("c:\\temp", fileName); 
      postedFile.SaveAs(filePath); 
     } 

     var response = new HttpResponseMessage(HttpStatusCode.OK); 
     response.Content = new StringContent("UPLOADED"); 

     System.Threading.Thread.Sleep(5000); 

     return response; 
    } 
} 

が質問今

、私は、Web APIメソッドを持っていますが、私は戻ってUIへの断続的な応答を送信するかどうかはわかりません。私は簡単な解決策を探しています。どんな提案/例もありがとうございます。

+4

新しいスレッドに処理をオフロードし、更新のためのJavaScriptポーリングを有する、またはSignalRを使用サーバーからクライアントに更新をプッシュします。 –

+0

@JasonP、更新のためのjavascriptポーリング用のコードサンプル/リファレンスはありますか? –

+2

私はちょうど 'setTimeout'か' setInterval'を使用します。もう1つのオプションが「永遠のフレーム」https://www.google.com/?q=forever%20frame%20iframe –

答えて

0

私はJasonのコメントに続き、別のajax呼び出しを使用してポーリングを行い、断続的な応答を得ることができました。

以下のコードでは、サーバーにjquery.formプラグインを使用してファイルをアップロードし、コントローラレベルで長時間実行されるタスクを実行しようとしています。進行状況をユーザーに示すために、ポーリングの概念を使用して長時間実行されているタスクの状態を確認します。ここで

は、

ASPコードです。NET HTML:

<asp:Content ID="Content2" ContentPlaceHolderID="ContentPlaceHolder1" runat="server"> 
    <div class="row"> 
     <div class="col-xs-12"> 
      <div class="alert alert-warning">This page uses jquery.form plugin to upload</div> 
     </div> 
    </div> 
</asp:Content> 
<asp:Content ID="Content3" ContentPlaceHolderID="NoFormContentPlaceHolder" runat="server"> 

    <div class="row"> 
     <div class="col-xs-12"> 
      <form id="ImportFileForm" method="post" action="api/FileUpload/Upload" enctype="multipart/form-data"> 
       <div class="col-xs-3"> 
        <input type="file" id="ImportFile" name="ImportFile" accept="*.xlsx" class="col-xs-12 file-selector" /> 
       </div> 
       <div class="col-xs-1"> 
        <button class="btn btn-danger btn-xs" id="ImportFileBtn" type="submit" title="Import"><span class="glyphicon glyphicon-import"></span>Import</button> 
       </div> 
      </form> 
     </div> 
    </div> 
    <div class="row row-margin"> 
     <div class="col-xs-12"> 
      <div class="col-xs-3"> 
       <div id="UploadStatusMessage"></div> 
       <div class="progress"> 
        <div class="progress-bar" role="progressbar" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100" style="width: 0%"> 
         0% 
        </div> 
       </div> 
      </div> 
     </div> 
     <div class="col-xs-12"> 
      <div class="alert alert-default" id="PollingStatusMessage"></div> 
     </div> 
    </div> 
</asp:Content> 
<asp:Content ID="Content1" ContentPlaceHolderID="head" runat="server"> 
    <%:Scripts.Render("~/Scripts/jQueryForm") %> 
</asp:Content> 

ファイルアップロードコントローラCS

public class FileUploadController : ApiController 
    { 
     [HttpPost] //this is demo, lets assume that user is uploading a file and in the same method, some long running operation is happening. 
     public HttpResponseMessage Upload() 
     { 
      var requestId = HttpContext.Current.Request.Form["RequestTracker"]; 

      if (HttpContext.Current.Request.Files.Count > 0) 
      { 
       var postedFile = HttpContext.Current.Request.Files[0]; 

       var fileNameParts = postedFile.FileName.Split('\\'); 
       var fileName = fileNameParts[fileNameParts.Length - 1]; 

       fileName = string.Format("{0}_{1}", DateTime.Now.Ticks.ToString(), fileName); 
       string filePath = Path.Combine("c:\\temp", fileName); 
       postedFile.SaveAs(filePath); 
      } 

      //Note: usually, this will be some other operation (database insert/update, data validation etc) 
      //Inorder to show the exact status/progress, the backend should store some indication which can be retrieved using another ajax call by polling 

      ObjectCache cache = MemoryCache.Default; 
      cache.Remove(requestId);//remove any previous for demo purpose 

      CacheItemPolicy policy = new CacheItemPolicy(); 
      policy.AbsoluteExpiration = DateTime.Now.AddMinutes(10); 

      List<int> taskStatus = new List<int>(); 

      //long running task 1 

      for (int i = 0; i < 100; i++) 
      { 
       System.Threading.Thread.Sleep(100); 
       taskStatus.Add(i);     
      } 

      cache.Set(requestId, taskStatus, policy); 

      //long running task 2 

      for (int i = 0; i < 100; i++) 
      { 
       System.Threading.Thread.Sleep(100); 
       taskStatus.Add(i); 
      } 

      cache.Set(requestId, taskStatus, policy); 

      //long running task 3 

      for (int i = 0; i < 100; i++) 
      { 
       System.Threading.Thread.Sleep(100); 
       taskStatus.Add(i); 
      } 

      cache.Set(requestId, taskStatus, policy); 

      //long running task 4 

      for (int i = 0; i < 100; i++) 
      { 
       System.Threading.Thread.Sleep(100); 
       taskStatus.Add(i); 
      } 

      cache.Set(requestId, taskStatus, policy); 


      return Request.CreateResponse(HttpStatusCode.OK, "All Operations Completed"); 
     } 
    } 

ポーリングコントローラCS

public class PollingController : ApiController 
    { 
     [HttpPost] 
     public HttpResponseMessage GetStatus(UploadStatusRequest request) 
     { 
      ObjectCache cache = MemoryCache.Default; 
      var fileUploadStatus = cache.Get(request.RequestId) as List<int>; 

      var count = 0; 

      if (fileUploadStatus != null) 
      { 
       count = fileUploadStatus.Count; 
      } 

      return Request.CreateResponse(HttpStatusCode.OK, "Processed data : " + count + ". Please wait..."); 
     } 
    } 

typescriptファイル:

namespace jQueryForm { 

    export class FileUploadComponent { 

     progressBar: JQuery = $('.progress-bar'); 
     importFile: JQuery = $('#ImportFile'); 
     uploadStatusMessage: JQuery = $('#UploadStatusMessage'); 
     pollingStatusMessage: JQuery = $('#PollingStatusMessage'); 
     pollingInstance: any = null; 

     public RegisterEvents() { 

      var instance: FileUploadComponent = this; 

      instance.importFile.on('change', function() { 
       instance.ResetProgressBar(); 
      }); 

      var requestStatusTracker = null; 

      $('#ImportFileForm').ajaxForm({ 
       beforeSubmit: function (arr, $form, options) { 

        requestStatusTracker = new Date().getMilliseconds(); 

        arr.push({ name: 'RequestTracker', value: requestStatusTracker }); 

        return true; 
       }, 
       beforeSend: function (xhr, options) {    

        instance.ResetProgressBar(); 
        instance.uploadStatusMessage.text('Uploading...'); 
       },     
       //Note: The uploadProgress method displays the status of file transfer progress to web api method. Once the file is completely transferred to Web API method, 
       //  the percentage will become 100. But, there could be other operations once the file is reached Web API and those are not counted. 
       uploadProgress: function (event, position, total, percentComplete) { 
        var percentVal = percentComplete + '%'; 

        instance.progressBar.css("width", percentVal).attr("aria-valuenow", percentComplete).text(percentVal); 

        if (percentComplete == 100) { 

         var uploadStatusRequest = new Entities.UploadStatusRequest(); 
         uploadStatusRequest.RequestId = requestStatusTracker; 

         instance.Poll(uploadStatusRequest); 
         instance.uploadStatusMessage.text('File Upload Complete.'); 
        } 
       }, 
       success: function (data) { 
        //instance.ResetProgressBar(); 

        //Note: all operations completed in the web api method and the success response is received from the controller 
        clearTimeout(instance.pollingInstance); 
        instance.pollingStatusMessage.html(data); 

       }, 
       error: function (xhr) { 

       }, 
       complete: function (xhr) {//controller has completed all the action 

       } 
      }); 
     } 

     private ResetProgressBar() { 
      this.progressBar.css("width", '0%').attr("aria-valuenow", 0).text('0%'); 
      this.uploadStatusMessage.empty(); 
     } 

     private Poll(uploadStatusRequest) { 

      var instance: FileUploadComponent = this; 

      instance.pollingInstance = setTimeout(function() { 
       $.ajax({ 
        url: "api/Polling/GetStatus", data: uploadStatusRequest, dataType: "json", type: 'POST', success: function (data) { 
         //Update your status 
         instance.pollingStatusMessage.html(data); 

         //Setup the next poll recursively 
         instance.Poll(uploadStatusRequest); 

        }, error: function (xhr) { 
         instance.pollingStatusMessage.html(xhr.responseText); 
        } 
       }); 
      }, 2000); 
     } 
    } 
} 
$(function() { 

    var fileUploadComponent = new jQueryForm.FileUploadComponent(); 

    fileUploadComponent.RegisterEvents(); 
}); 

出力:以下に示すように進捗がユーザに表示される

enter image description here

関連する問題