【发布时间】:2015-06-08 13:56:32
【问题描述】:
在this tutorial 之后,我正在尝试显示长时间操作中各个步骤的进度。我能够根据示例成功模拟集线器内的长时间操作,并在每个步骤中向客户端报告更新。
更进一步,我现在想显示一个实时、长时间运行的进程的状态,该进程发生在具有[HttpPost] 属性的 MVC 操作方法中。
问题是我似乎无法从集线器上下文更新客户端。我意识到我必须创建一个集线器上下文才能使用集线器进行通信。我知道的一个区别是我必须使用hubContext.Clients.All.sendMessage(); VS。 hubContext.Clients.Caller.sendMessage(); 列在示例中。基于我在ASP.NET SignalR Hubs API Guide - Server 中的发现
如示例中所述,我应该能够使用Clients.Caller,但我仅限于在集线器类中使用它。主要是想明白为什么我不能从action方法中得到信号。
提前感谢您的帮助。
我已经像这样创建了我的 OWIN Startup() 类...
using System;
using System.Threading.Tasks;
using Microsoft.Owin;
using Owin;
[assembly: OwinStartup(typeof(HL7works.Startup))]
namespace HL7works
{
public class Startup
{
public void Configuration(IAppBuilder app)
{
app.MapSignalR();
}
}
}
我的中心是这样写的...
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using Microsoft.AspNet.SignalR;
namespace HL7works
{
public class ProgressHub : Hub
{
public string msg = string.Empty;
public int count = 0;
public void CallLongOperation()
{
Clients.Caller.sendMessage(msg, count);
}
}
}
我的控制器...
// POST: /Task/ParseToExcel/
[HttpPost]
public ActionResult ParseToExcel(HttpPostedFileBase[] filesUpload)
{
// Initialize Hub context
var hubContext = GlobalHost.ConnectionManager.GetHubContext<ProgressHub>();
hubContext.Clients.All.sendMessage("Initalizing...", 0);
double fileProgressMax = 100.0;
int currentFile = 1;
int fileProgress = Convert.ToInt32(Math.Round(currentFile / fileProgressMax * 100, 0));
try
{
// Map server path for temporary file placement (Generate new serialized path for each instance)
var tempGenFolderName = SubstringExtensions.GenerateRandomString(10, false);
var tempPath = Server.MapPath("~/" + tempGenFolderName + "/");
// Create Temporary Serialized Sub-Directory
System.IO.FileInfo thisFilePath = new System.IO.FileInfo(tempPath + tempGenFolderName);
thisFilePath.Directory.Create();
// Iterate through PostedFileBase collection
foreach (HttpPostedFileBase file in filesUpload)
{
// Does this iteration of file have content?
if (file.ContentLength > 0)
{
// Indicate file is being uploaded
hubContext.Clients.All.sendMessage("Uploading " + Path.GetFileName(file.FileName), fileProgress);
file.SaveAs(thisFilePath + file.FileName);
currentFile++;
}
}
// Initialize new ClosedXML/Excel workbook
var hl7Workbook = new XLWorkbook();
// Start current file count at 1
currentFile = 1;
// Iterate through the files saved in the Temporary File Path
foreach (var file in Directory.EnumerateFiles(tempPath))
{
var fileNameTmp = Path.GetFileName(file);
// Update status
hubContext.Clients.All.sendMessage("Parsing " + Path.GetFileName(file), fileProgress);
// Initialize string to capture text from file
string fileDataString = string.Empty;
// Use new Streamreader instance to read text
using (StreamReader sr = new StreamReader(file))
{
fileDataString = sr.ReadToEnd();
}
// Do more work with the file, adding file contents to a spreadsheet...
currentFile++;
}
// Delete temporary file
thisFilePath.Directory.Delete();
// Prepare Http response for downloading the Excel workbook
Response.Clear();
Response.ContentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
Response.AddHeader("content-disposition", "attachment;filename=\"hl7Parse_" + DateTime.Now.ToString("MM-dd-yyyy") + ".xlsx\"");
// Flush the workbook to the Response.OutputStream
using (MemoryStream memoryStream = new MemoryStream())
{
hl7Workbook.SaveAs(memoryStream);
memoryStream.WriteTo(Response.OutputStream);
memoryStream.Close();
}
Response.End();
}
catch (Exception ex)
{
ViewBag.TaskMessage =
"<div style=\"margin-left:15px;margin-right:15px\" class=\"alert alert-danger\">"
+ "<i class=\"fa fa-exclamation-circle\"></i> "
+ "An error occurred during the process...<br />"
+ "-" + ex.Message.ToString()
+ "</div>"
;
}
return View();
}
在我看来(已更新以反映 Detail 的回答)...
@using (Html.BeginForm("ParseToExcel", "Task", FormMethod.Post, new { enctype = "multipart/form-data", id = "parseFrm" }))
{
<!-- File Upload Row -->
<div class="row">
<!-- Select Files -->
<div class="col-lg-6">
<input type="file" multiple="multiple" accept=".adt" name="filesUpload" id="filesUpload" />
</div>
<!-- Upload/Begin Parse -->
<div class="col-lg-6 text-right">
<button id="beginParse" class="btn btn-success"><i class="fa fa-download"></i> Parse and Download Spreadsheet</button>
</div>
</div>
}
<!-- Task Progress Row -->
<div class="row">
<!-- Space Column -->
<div class="col-lg-12">
</div>
<!-- Progress Indicator Column -->
<script type="text/javascript" language="javascript">
$(document).ready(function () {
$('.progress').hide();
$('#beginParse').on('click', function () {
$('#parseFrm').submit();
})
$('#parseFrm').on('submit', function (e) {
e.preventDefault();
$.ajax({
url: '/Task/ParseToExcel',
type: "POST",
//success: function () {
// console.log("done");
//}
});
// initialize the connection to the server
var progressNotifier = $.connection.progressHub;
// client-side sendMessage function that will be called from the server-side
progressNotifier.client.sendMessage = function (message, count) {
// update progress
UpdateProgress(message, count);
};
// establish the connection to the server and start server-side operation
$.connection.hub.start().done(function () {
// call the method CallLongOperation defined in the Hub
progressNotifier.server.callLongOperation();
});
});
});
function UpdateProgress(message, count) {
// get status div
var status = $("#status");
// set message
status.html(message);
// get progress bar
if (count > 0) {
$('.progress').show();
}
$('.progress-bar').css('width', count + '%').attr('aria-valuenow', count);
$('.progress-bar').html(count + '%');
}
</script>
<div class="col-lg-12">
<div id="status">Ready</div>
</div>
<div class="col-lg-12">
<div class="progress">
<div class="progress-bar" role="progressbar" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100" style="min-width:20px;">
0%
</div>
</div>
</div>
</div>
<!-- Task Message Row -->
<div class="row">
<div clss="col-lg-12">
@Html.Raw(ViewBag.TaskMessage)
</div>
</div>
更新:我的问题的解决方案最终成为 Detail 的答案,但 AJAX 发布方法稍作修改以将文件传递给我的操作方法..
e.preventDefault();
$.ajax({
url: '/Task/ParseToExcel',
type: "POST",
data: new FormData( this ),
processData: false,
contentType: false,
//success: function () {
// console.log("done");
//}
});
参考..http://portfolio.planetjon.ca/2014/01/26/submit-file-input-via-ajax-jquery-easy-way/
【问题讨论】:
-
最好不要包含unnecessary tags
-
@lloyd,谢谢。下次我会记住这一点的。
-
没问题,这是solution relevant
-
@lloyd,我对集线器类的引用和集线器方法的调用正是他们在您引用的解决方案中所做的。然而,我担心我可能会错过另一块拼图。我只是不确定那可能是什么。
-
我认为您不需要向所有客户发送消息......只是连接的那个人
标签: c# asp.net-mvc signalr