title: (MVC4) Send ProgressChanged event to a View
body: <p>I have a MVC4 application with</p>
  
  <ul>
  <li><p>A <strong>View</strong> who use bootstrap progress bar ( It's a partial view ) and Kendo UI for upload a file like this :</p>
  
  <pre><code>@using MyApplication.Web.Resources.Views.Contact;
  &lt;div class="row"&gt;
      &lt;div class="span6"&gt;
  
           &lt;form class="form-horizontal well" method="post" action="@Url.Action("ImportContact","ContactAsync")"&gt;
                @Html.ValidationSummary(true)
  
                &lt;script src="@Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"&gt;&lt;/script&gt;
                &lt;script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"&gt;&lt;/script&gt;
  
  
                &lt;fieldset&gt;
                    &lt;legend&gt;Contact&lt;/legend&gt;
  
                    &lt;p&gt;
                        Some text...
                    &lt;/p&gt;
  
                    @(Html.Kendo().Upload()
                    .Name("files"))
  
  
                     &lt;div class="progress progress-striped"&gt;
                           &lt;div class="bar" style="width: 0%;"&gt;&lt;/div&gt;
                     &lt;/div&gt;
  
                     &lt;div class="form-actions"&gt; 
                         &lt;button type="submit" class="btn btn-primary" onclick="importMessage()"&gt;@Contact.ValidationButton&lt;/button&gt;
                         &lt;button type="submit" class="btn btn-secondary" onclick="window.location.href='@Url.Action("Index")';return false;"&gt;@Contact.CancelButton&lt;/button&gt;
                     &lt;/div&gt; 
             &lt;/fieldset&gt;
          &lt;/form&gt;
      &lt;/div&gt;
  &lt;/div&gt;   
  </code></pre></li>
  <li><p>And a <strong>Async Controller</strong> like this :</p>
  
  <pre><code>public class ContactAsyncController : AsyncController
  {
      private BackgroundWorker worker = new BackgroundWorker();
  
      public ContactAsyncController(IContactService cs)
      {
          _contactService = cs;
      }
  
      //
      // POST: /Contact/ImportContactAsync
      [HttpPost]
      public void ImportContactAsync(IEnumerable&lt;HttpPostedFileBase&gt; files)
      {
          AsyncManager.OutstandingOperations.Increment();
  
          worker.WorkerReportsProgress = true;
          worker.ProgressChanged += new ProgressChangedEventHandler(bw_ProgressChanged);
          worker.DoWork += (o, e) =&gt; ImportContact(files, e);
          worker.RunWorkerCompleted += (o, e) =&gt;
              {
                  AsyncManager.OutstandingOperations.Decrement();
              };
  
          worker.RunWorkerAsync();
      }
  
      private void bw_ProgressChanged(object sender, ProgressChangedEventArgs e)
      {
          Debug.WriteLine(e.ProgressPercentage.ToString() + "%");
      }
  
      private void ImportContact(IEnumerable&lt;HttpPostedFileBase&gt; 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");
      }
  }
  </code></pre></li>
  </ul>
  
  <p><strong>And I want to make progress my progress bar. So for this, I thought to do a script in my view like this :</strong></p>
  
  <pre><code>&lt;script&gt;
      $(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);
      });
  &lt;/script&gt;
  </code></pre>
  
  <p>Where GetProgressBar give me the perrcentage that I want, but it doesn't work because this method wait that the asynchronous method ( ImportContact ) finishes to do his job ... There are an update of the progress bar only at the end of the upload method.</p>
  
  <pre><code>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();
      }
  
  }
  </code></pre>
  
  <p>So, as you can see ( at the beginning ), I have implemented the progressChanged event but I don't know how to use it to update my progress bar in my View... Can you help me ?</p>
  
  <p>Thank you all for reading and trying to understand this, if you want more informations please tell me.</p>