问题描述
我有一个MVC4应用
-
A 查看谁使用的引导进度条(这是一个局部视图)和剑道UI上传这样的文件:
@using MyApplication.Web.Resources.Views.Contact;
< DIV CLASS =行>
< DIV CLASS =span6> <窗体类=的形式,水平井的方法=邮报行动=@ Url.Action(ImportContact,ContactAsync)>
@ Html.ValidationSummary(真) <脚本的src =@ Url.Content(〜/脚本/ jquery.validate.min.js)TYPE =文/ JavaScript的>< / SCRIPT>
<脚本的src =@ Url.Content(〜/脚本/ jquery.validate.unobtrusive.min.js)TYPE =文/ JavaScript的>< / SCRIPT>
<&字段集GT;
<传奇>联系与LT; /传说> &所述p为H.;
有些文字...
&所述; / P> @(Html.Kendo()。上传()
。名称(文件))
< DIV CLASS =进步进步条纹>
< DIV CLASS =酒吧的风格=宽度:100%;>< / DIV>
< / DIV> < DIV CLASS =表单行动>
<按钮式=提交级=BTN BTN-小学的onclick =importMessage()> @ Contact.ValidationButton< /按钮>
<按钮式=提交级=BTN BTN-次要的onclick =window.location.href ='@ Url.Action(「指数」)';返回false;> @ Contact.CancelButton< /按钮&GT ;
< / DIV>
< /字段集>
< /表及GT;
< / DIV>
< / DIV> -
和一个异步控制器是这样的:
公共类ContactAsyncController:AsyncController
{
私人BackgroundWorker的工人=新的BackgroundWorker(); 公共ContactAsyncController(IContactService CS)
{
_contactService = CS;
} //
// POST:/联系人/ ImportContactAsync
[HttpPost]
公共无效ImportContactAsync(IEnumerable的< HttpPostedFileBase>文件)
{
AsyncManager.OutstandingOperations.Increment(); worker.WorkerReportsProgress = TRUE;
worker.ProgressChanged + =新ProgressChangedEventHandler(bw_ProgressChanged);
worker.DoWork + =(O,E)=> ImportContact(文件,E);
worker.RunWorkerCompleted + =(O,E)=>
{
AsyncManager.OutstandingOperations.Decrement();
}; worker.RunWorkerAsync();
} 私人无效bw_ProgressChanged(对象发件人,ProgressChangedEventArgs E)
{
的Debug.WriteLine(e.ProgressPercentage.ToString()+%);
} 私人无效ImportContact(IEnumerable的< HttpPostedFileBase>文件,DoWorkEventArgs E)
{
尝试
{
如果(文件!= NULL)
{
字符串路径=;
字符串扩展=; 的foreach(HttpPostedFileBase文件中的文件)
{
如果(文件!= NULL)
{
//新变化 - 首先将文件保存在服务器上
file.SaveAs(Path.Combine(使用Server.Mappath(〜/温度/导入),file.FileName)); //现在创建该文件的路径
PATH = Path.Combine(使用Server.Mappath(〜/温度/导入),file.FileName); 延长= Path.GetExtension(file.FileName);
}
其他
{
// ...
}
} 如果(扩展名==的.pst)// PST
{
ImportContactPst(路径);
}
其他
{
// ...
}
}
}
抓住
{
ViewBag.Error = myApplication.Web.Resources.Views.Contact.Contact.ErrorMessage;
}
} 私人无效ImportContactPst(字符串路径)
{
//有些code ... 会话[测试] = //我的百分比
} 公众的ActionResult ImportContactCompleted()
{
返回RedirectToAction(指数,联系方式);
}
}
我想进步我的进度条。因此,对于这个,我觉得做一个脚本,在我看来是这样的:
<脚本>
$(文件)。就绪(函数(){
VAR progresspump =的setInterval(函数(){
/ *从服务器查询完工百分比* /
$阿贾克斯({
键入:GET,
网址:@ Url.Action(GetProgressBar),
数据类型:JSON
缓存:假的,
成功:功能(数据){
VAR PERCENTCOMPLETE = parseInt函数(data.PercentComplete);
如果(PERCENTCOMPLETE == NULL || PERCENTCOMPLETE == 100){
$(进步)removeClass移除(活动)。 //我们就大功告成了!
$(进步的.bar),CSS(宽度,100%)。
}其他{//更新进度条
$(进步)addClass(活动)。
$(进步的.bar),CSS(宽度,PERCENTCOMPLETE +%)。
}
},
错误:功能(XHR,textStatus,thrownError){
的console.log(xhr.statusText);
的console.log(xhr.responseText);
的console.log(xhr.status);
的console.log(thrownError);
}
});
},3000);
});
< / SCRIPT>
在哪里GetProgressBar给我我想要的perrcentage,但它不工作,因为这种方法等待该异步方法(ImportContact)完成做他的工作......有进度条的更新只在最后的上传方式。
公众的ActionResult GetProgressBar()
{
尝试
{
如果(this.Session [测试]!= NULL)
{
返回JSON(新{PERCENTCOMPLETE = this.Session [测试]},JsonRequestBehavior.AllowGet);
}
其他
返回JSON(0,JsonRequestBehavior.AllowGet);
}
抓住
{
ViewBag.Error = myApplication.Web.Resources.Views.Contact.Contact.ErrorMessage;
返回查看();
}}
所以,你可以看到(开头),我已经实现了progressChanged事件,但我不知道如何使用它,我认为更新我的进度条...你能帮我吗?
感谢大家的阅读,并试图理解这一点,如果你想了解更多信息,请告诉我。
我不知道它可以工作的方式。因为他们在例如表单应用程序工作之间的客户端和服务器事件不起作用。我会做的是有JavaScript的定期检查取得的进展状态的后端和更新的视觉吧。
您可以做到这一点与一个计时器,检查每两秒钟像
的setInterval(函数(){/ *在这里做Ajax调用* /},2000);
我做了一些挖掘和事实证明,使用BackgroundWorker的未必是最好的选择,因为它是不适合于MVC。我发现工程它使用辅助线程的解决方案。请看看这里:
<$p$p><$c$c>http://blog.janjonas.net/2012-01-02/asp_net-mvc_3-async-jquery-progress-indicator-long-running-tasks有关完整性的抖动的整个部分是以下关于控制器。该JavaScript是pretty自我解释。
公众的ActionResult开始()
{
变种的TaskID = Guid.NewGuid();
tasks.Add(的TaskID,0); Task.Factory.StartNew(()=&GT;
{
对于(VAR I = 0;我LT&= 100;我++)
{
任务[TASKID] =我; //更新任务进度
Thread.sleep代码(50); //模拟长时间运行的操作
}
tasks.Remove(TASKID);
}); 返回JSON(TASKID);
} 公众的ActionResult进展(GUID ID)
{
返回JSON(?tasks.Keys.Contains(ID)的任务[ID]:100);
}
}
I have a MVC4 application with
A View who use bootstrap progress bar ( It's a partial view ) and Kendo UI for upload a file like this :
@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>
And a Async Controller like this :
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"); } }
And I want to make progress my progress bar. So for this, I thought to do a script in my view like this :
<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>
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.
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();
}
}
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 ?
Thank you all for reading and trying to understand this, if you want more informations please tell me.
I am not sure it can work that way. Between client and server events do not work as they work in a Form Application for example. What I would do is to have javascript periodically check the backend for the state of progress made and update the visual bar.
You could do that with a timer and check every couple of seconds like
setInterval(function(){/*do the ajax call here*/},2000);
I did some digging and it turns out that using a backgroundworker might not be the best option as it is not well suited for MVC. I found out a solution that works which uses a secondary thread. Please have a look here:
http://blog.janjonas.net/2012-01-02/asp_net-mvc_3-async-jquery-progress-indicator-long-running-tasks
For the shake of completeness the whole part is below regarding the controller. The javascript is pretty self explaining.
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);
}
}
这篇关于(MVC4)发送ProgressChanged事件视图的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!