我有一个带
的MVC4应用程序查看谁使用bootstrap进度条(这是部分视图)和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事件,但我不知道如何使用它来更新我的视图中的进度条...你能帮助我吗?
感谢所有人阅读并试图理解这一点,如果你想了解更多信息,请告诉我。
答案 0 :(得分:0)
我不确定它是否可以这样运作。客户端和服务器事件之间的工作不起作用,例如它们在表单应用程序中工作。我要做的是让javascript定期检查后端的状态,并更新视觉栏。
您可以使用计时器执行此操作并每隔几秒检查一次,如
setInterval(function(){/*do the ajax call here*/},2000);
我做了一些挖掘,结果发现使用backgroundworker可能不是最佳选择,因为它不适合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);
}
}