我有一个应用程序,有一个过程上传excel文件和更新我的数据库的内容,但有时文件是如此之大,过程需要超过230秒,并且azure返回500服务器错误。我打算解决这个问题的方法是让应用程序在上传时打开signalR连接,然后在进度条通过文件时提供更新。问题是,我似乎无法启动和运行基本的signalR功能。当我尝试从Context获取connectionId时,我得到一个null值,因为Context为null。我已经尝试了在论坛和教程中找到的所有内容,但是没有运气。
以下是我的StartUp.cs中的代码:
using Microsoft.Owin;
using Owin;
[assembly: OwinStartup(typeof(LIMS.Startup))] //maybe this is needed
//[assembly: OwinStartupAttribute(typeof(LIMS.Startup))]
namespace LIMS
{
public partial class Startup
{
public void Configuration(IAppBuilder app)
{
ConfigureAuth(app);
ConfigureSignalR(app);
}
}
}
然后我在App_Start文件夹中有一个Startup.SignalR.cs文件,其中包含以下代码:
using Owin;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace LIMS
{
public partial class Startup
{
public void ConfigureSignalR(IAppBuilder app)
{
app.MapSignalR();
}
}
}
我的cshtml文件如下所示:
@{
ViewBag.Title = "LabSampleImport";
}
<h2>Lab Sample Import</h2>
<h3 class="text-warning">@ViewBag.Message @TempData["Message"]</h3>
@using (Html.BeginForm("LabSampleImport", "LabData", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
@Html.AntiForgeryToken()
<span><input type="file" name="file" style="display:inline" /></span>
<p>
Use the Button above to select the Excel file on your hard drive with the lab sample information you wish to add and/or edit.
Once you have selected the correct file, click the "Upload Selected File" button below to initiate the import. When the import is complete,
a file with the same name will download back to your device through your browser. There will be a comment column in the file to indicate the result of each lab sample/row.
</p>
<span><input type="submit" name="submitButton" value="Upload Selected File" class="btn btn-default" /></span>
<hr />
<input type="submit" name="submitButton" value="Download a Template" class="btn btn-default" />
}
<script src="Scripts/jquery.signalR-2.2.2.js"></script>
<script src="/signalr/hubs"></script>
<script language="javascript">
theHub.client.initProgressBar = function () {
alert("The server has just informed this webpage that a progress bar should be displayed.");
}
theHub.client.updateProgressBar = function (percentage) {
alert("The server has just informed this webpage that a progress bar should be updated.");
}
theHub.client.clearProgressBar = function (percentage) {
alert("The server has just informed this webpage that a progress bar should be cleared.");
}
</script>
我的ProgressHub.cs文件如下所示:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using Microsoft.AspNet.SignalR;
namespace LIMS.Hubs
{
public class ProgressHub : Hub
{
public void NotifyStart(string connectionId)
{
var hubContext = GlobalHost.ConnectionManager.GetHubContext<ProgressHub>();
hubContext.Clients.Client(connectionId).initProgressBar();
}
public void NotifyProgress(string connectionId, int percentage)
{
var hubContext = GlobalHost.ConnectionManager.GetHubContext<ProgressHub>();
hubContext.Clients.Client(connectionId).updateProgressBar(percentage);
}
public void NotifyEnd(string connectionId)
{
var hubContext = GlobalHost.ConnectionManager.GetHubContext<ProgressHub>();
hubContext.Clients.Client(connectionId).clearProgressBar();
}
}
}
由于Context为null而给出错误的控制器方法如下所示:
// POST: LabData/LabSampleImport
[HttpPost, ActionName("LabSampleImport")]
[ValidateAntiForgeryToken]
[Authorize(Roles = "canAddSamples")]
public async Task<ActionResult> LabSampleImportOption(HttpPostedFileBase file, string submitButton)
{
if (submitButton == "Upload Selected File")
{
//upload file
if (file != null && file.ContentLength > 0)
{
ProgressHub hub1 = new ProgressHub();
//This is where Context is inexplicably null
var connectionId = hub1.Context.ConnectionId;
//and this is where app goes kaplooey due to a null reference exception
hub1.NotifyStart(connectionId);
// A bit of placeholder work
Thread.Sleep(5000);
hub1.NotifyProgress(connectionId, 20);
}
}
}
我发现的其他类似问题的帖子似乎都集中在启动文件执行ConfigureAuth(app)和app.MapSignalR()的顺序。我相信这不是问题,但仍然不知道为什么Context是null。我已经考虑过在客户端获取connectionID并将其传递给方法,但由于从表单帖子中的按钮调用控制器方法,我没有看到让razor在帖子中设置connectionID参数的方法直到游戏后期才能确定连接ID的说明。那我错过了什么?
答案 0 :(得分:0)
以简单的方式,您可以将当前连接ID($.connection.hub.id
)存储在隐藏的输入中,并利用jQuery Form使用AJAX提交表单,而无需刷新当前页面,这将返回您的新的连接ID。您需要按如下方式修改视图页面:
@using (Html.BeginForm("UploadFile", "Home", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
<span><input type="file" name="file" style="display:inline" /></span>
<!--add the hidden input for storing the current connection Id-->
<input type="hidden" name="connectionId" id="connectionId"/>
<span><input type="submit" name="submitButton" value="Upload Selected File" class="btn btn-default" /></span>
<hr />
<input type="submit" name="submitButton" value="Download a Template" class="btn btn-default" />
}
<强>的javascript:强>
$(function () {
// Reference the auto-generated proxy for the hub.
var chat = $.connection.progressHub;
chat.client.initProgressBar = function () {
console.log("The server has just informed this webpage that a progress bar should be displayed.");
}
chat.client.updateProgressBar = function (percentage) {
console.log("current uploading process:" + percentage + "%");
}
chat.client.clearProgressBar = function (percentage) {
console.log("The server has just informed this webpage that a progress bar should be cleared.");
}
// Start the connection.
$.connection.hub.start().done(function () {
var cid = $.connection.hub.id;
$("#connectionId").val(cid);
console.log("connection Id:" + cid);
});
$('form').ajaxForm({
complete: function (xhr) {
alert(xhr.responseText);
}
});
});
上传文件的操作:
public ActionResult UploadFile(HttpPostedFileBase file, string submitButton, string connectionId)
{
ProgressHub.NotifyStart(connectionId);
Thread.Sleep(2000);
ProgressHub.NotifyProgress(connectionId, 20);
Thread.Sleep(2000);
ProgressHub.NotifyProgress(connectionId, 50);
Thread.Sleep(2000);
ProgressHub.NotifyProgress(connectionId, 100);
return Json("Done", JsonRequestBehavior.AllowGet);
}
<强> TEST:强>