2

Web API 메서드에서 간헐적 인 상태 응답을 jquery ajax 호출로 다시 보내고 UI의 진행 상황을 표시해야하는 작업을하고 있습니다.ASP.NET 웹 API 메서드에서 jquery ajax로 간헐적 인 응답 보내기

enter image description here

처음에는 일부 매개 변수 및 웹 API 메서드를 통과하는 웹 API 메서드를 호출 JQuery와 아약스는 장기 실행 작업을 수행하기 시작합니다. 각 작업이 완료되면, 나는

내가 지금까지 시도 무엇

,

HTML을 호출 JQuery와 아약스 방법 다시 (수동으로 일부 번호) 비율을 보낼 및 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; 
    } 
} 

질문

지금, 나는 UI로 다시 간헐적 인 응답을 보내는 방법을하지 확신, 웹 API를 방법을 가지고 있지만. 나는 간단한 해결책을 찾고있다. 모든 제안/예를 들어 주시면 감사하겠습니다.

+4

오프로드 새로운 스레드의 처리 및 업데이트는 JavaScript 폴링을하거나 SignalR을 사용 서버에서 클라이언트로 업데이트를 푸시합니다. –

+0

@JasonP, 업데이트를 위해 javascript 폴링에 대한 코드 샘플/참조가 있습니까? –

+2

그냥'setTimeout' 또는'setInterval'을 사용할 것입니다. 다른 옵션이 "영원한 프레임"이라고 가정합니다. 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..."); 
     } 
    } 

타이프 스크립트 파일 :

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