1

我有一个 MVC4 应用程序

  • 使用引导进度条(这是部分视图)和 Kendo UI 上传文件的视图,如下所示:

    @using MyApplication.Web.Resources.Views.Contact;
    <div class="row">
        <div class="span6">
    
             <form class="form-horizontal well" method="post" action="@Url.Action("ImportContact","ContactAsync")">
                  @Html.ValidationSummary(true)
    
                  <script src="@Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script>
                  <script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script>
    
    
                  <fieldset>
                      <legend>Contact</legend>
    
                      <p>
                          Some text...
                      </p>
    
                      @(Html.Kendo().Upload()
                      .Name("files"))
    
    
                       <div class="progress progress-striped">
                             <div class="bar" style="width: 0%;"></div>
                       </div>
    
                       <div class="form-actions"> 
                           <button type="submit" class="btn btn-primary" onclick="importMessage()">@Contact.ValidationButton</button>
                           <button type="submit" class="btn btn-secondary" onclick="window.location.href='@Url.Action("Index")';return false;">@Contact.CancelButton</button>
                       </div> 
               </fieldset>
            </form>
        </div>
    </div>   
    
  • 还有一个像这样的异步控制器

    public class ContactAsyncController : AsyncController
    {
        private BackgroundWorker worker = new BackgroundWorker();
    
        public ContactAsyncController(IContactService cs)
        {
            _contactService = cs;
        }
    
        //
        // POST: /Contact/ImportContactAsync
        [HttpPost]
        public void ImportContactAsync(IEnumerable<HttpPostedFileBase> files)
        {
            AsyncManager.OutstandingOperations.Increment();
    
            worker.WorkerReportsProgress = true;
            worker.ProgressChanged += new ProgressChangedEventHandler(bw_ProgressChanged);
            worker.DoWork += (o, e) => ImportContact(files, e);
            worker.RunWorkerCompleted += (o, e) =>
                {
                    AsyncManager.OutstandingOperations.Decrement();
                };
    
            worker.RunWorkerAsync();
        }
    
        private void bw_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            Debug.WriteLine(e.ProgressPercentage.ToString() + "%");
        }
    
        private void ImportContact(IEnumerable<HttpPostedFileBase> files, DoWorkEventArgs e)
        {
            try
            {
                if (files != null)
                {
                    string path = "";
                    string extension = "";
    
                    foreach (HttpPostedFileBase file in files)
                    {
                        if (file != null)
                        {
                            // New changes - first save the file on the server
                            file.SaveAs(Path.Combine(Server.MapPath("~/Temp/Import"), file.FileName));
    
                            // Now create a path to the file 
                            path = Path.Combine(Server.MapPath("~/Temp/Import"), file.FileName);
    
                            extension = Path.GetExtension(file.FileName);
                        }
                        else
                        {
                            // ...
                        }
                    }
    
                    if (extension == ".pst") // PST
                    {
                        ImportContactPst(path);
                    }
                    else
                    {
                        // ...
                    }
                }
            }
            catch
            {
                ViewBag.Error = myApplication.Web.Resources.Views.Contact.Contact.ErrorMessage;
            }
        }
    
        private void ImportContactPst(string path)
        {
             // Some code ...
    
             Session["test"] = // My percentage
        }
    
        public ActionResult ImportContactCompleted()
        {
            return RedirectToAction("Index","Contact");
        }
    }
    

我想在我的进度条上取得进展。所以为此,我想在我的视图中做一个这样的脚本:

<script>
    $(document).ready(function () {
        var progresspump = setInterval(function () {
            /* query the completion percentage from the server */
            $.ajax({
                type: "GET",
                url: "@Url.Action("GetProgressBar")",
                dataType: "json",
                cache: false,
                success: function (data) {
                    var percentComplete = parseInt(data.PercentComplete);
                    if (percentComplete == null || percentComplete == 100) {
                        $(".progress").removeClass("active"); // we're done!
                        $(".progress .bar").css("width", "100%");
                    } else { // update the progress bar
                        $(".progress").addClass("active");
                        $(".progress .bar").css("width", percentComplete + "%");
                    }
                },
                error: function (xhr, textStatus, thrownError) {
                    console.log(xhr.statusText);
                    console.log(xhr.responseText);
                    console.log(xhr.status);
                    console.log(thrownError);
                }
            });
        }, 3000);
    });
</script>

GetProgressBar 给了我想要的百分比,但它不起作用,因为这个方法等待异步方法( ImportContact )完成他的工作......只有在上传结束时才会更新进度条方法。

public ActionResult GetProgressBar()
{
    try
    {
        if (this.Session["test"] != null)
        {
            return Json(new { PercentComplete = this.Session["test"] }, JsonRequestBehavior.AllowGet);
        }
        else
            return Json(0, JsonRequestBehavior.AllowGet);
    }
    catch
    {
        ViewBag.Error = myApplication.Web.Resources.Views.Contact.Contact.ErrorMessage;
        return View();
    }

}

所以,正如你所看到的(在开头),我已经实现了 progressChanged 事件,但我不知道如何使用它来更新我的视图中的进度条......你能帮帮我吗?

感谢大家阅读并尝试理解这一点,如果您想了解更多信息,请告诉我。

4

1 回答 1

0

我不确定它是否可以那样工作。客户端和服务器之间的事件不起作用,例如它们在表单应用程序中起作用。我要做的是让 javascript 定期检查后端的进度状态并更新可视栏。

你可以用一个计时器来做到这一点,每隔几秒钟检查一次,比如

setInterval(function(){/*do the ajax call here*/},2000);

我做了一些挖掘,结果发现使用后台工作者可能不是最好的选择,因为它不太适合 MVC。我找到了一个使用辅助线程的有效解决方案。请看这里:

http://blog.janjonas.net/2012-01-02/asp_net-mvc_3-async-jquery-progress-indicator-long-running-tasks

为了完整起见,下面是关于控制器的整个部分。javascript非常自我解释。

    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);
   }
   }
于 2013-07-22T12:24:07.030 回答