Как использовать AsyncPostBackTrigger для запуска функций из серверной части, чтобы показать индикатор выполнения на интерфейсе? - PullRequest
0 голосов
/ 13 января 2019

Я использую UpdatePanel для заполнения индикатора выполнения всякий раз, когда выполняется функция на сервере. Пользователь сначала должен загрузить CSV-файл. Как только CSV-файл загружен и временно сохранен, пользователь нажимает другую кнопку (назовем ее «обновить и просматривать»), которая запускает ряд функций для очистки CSV-файла и преобразования его в JSON-файл. Некоторые CSV-файлы имеют большой размер, и трудно сказать, какую функцию выполняет CSV при запуске.

Однако проблема в том, что каждый раз, когда пользователь нажимает кнопку «обновить и просматривать», ничего не происходит. Я получаю сообщение об ошибке из консоли, что ссылка на объект не установлена ​​на экземпляр объекта.

Так как моя кнопка находится за пределами UpdatePanel, я удостоверился, что установил в UpdatePanel. Я убедился, что EventName = "click". Для UpdatePanel я удостоверился, что мой UpdateMode = "Условный", так как я хочу, чтобы индикатор выполнения заполнялся только после завершения работы функции. Я установил свой ChildrenAsTriggers = "true" - не имеет значения, изменил ли я этот параметр на "false". Кнопка все еще не выполняла функции, которые я сделал. Кроме того, на своей странице aspx я убедился, что Async = "true". Я использую asp: AsyncPostBackTriggers, а не asp: PostBackTriggers. Интересно, была ли это проблема, но я не верю, что это потому, что я пытаюсь запустить бэкэнд в то же время, обновляя индикатор выполнения моего интерфейса. Ниже приведен пример кода из серверной части (vb) и пример кода из внешнего интерфейса.

 Protected Sub BtnUpload_Click(sender As Object, e As EventArgs)

    statusLabel.Text = ""

    While statusLabel.Text = ""
        statusLabel.Text = Test_CSV()
        Try
            loadbar.Style("width") = "10%"
            updateP.Update()
        Catch ex As Exception
            MsgBox(ex.ToString)
        End Try
        statusLabel.Text = Save_CSV()

        statusLabel.Text = Create_tables("fileOne")


        statusLabel.Text = Transfer_Tables("fileOne")


        statusLabel.Text = Update_Tables("fileOne")

        statusLabel.Text = Query_JSON()



    End While

    FileUploadControl.Enabled = False
    BtnUpload.Enabled = False
    FileUploadControl.Visible = False
    BtnUpload.Visible = False


    Response.Redirect("/summary/filesummary.aspx")


End Sub
  <div class="row" style="padding-left: 0; padding-top: .5em;">
    <div class="col-md-12">
        <label class="file-upload">
            <span id="selectcsv" runat="server">Select CSV File                   
                 <asp:FileUpload ID="FileUploadControl" runat="server"                        
       onchange="document.getElementById('uploadText').style.display =            
    'block';showFile();document.getElementById('instruction').style.display = 
   'none';" CssClass="hidden" /></span>
        </label>
    </div>
</div>

<div class="row" style="margin-bottom: 1em;">
    <div class="col-md-12">
        <label class="file-upload" id="uploadText" style="display: none;">
            <span>Update and view results</span>
            <asp:Button runat="server" ID="BtnUpload" OnClick="BtnUpload_Click" CssClass="hidden"/>
        </label>
        <asp:Label CssClass="label" runat="server" ID="statusLabel"></asp:Label>
    </div>
</div>


    <asp:UpdatePanel id="updateP" runat="server" UpdateMode="Conditional" 
               ChildrenAsTriggers="false">
        <ContentTemplate>
            <div role="progressbar" class="progress-bar" id="loadbar" 
            style="width: 0%" aria-valuemin="0" aria-valuemax="100" 
             runat="server"></div>
        </ContentTemplate>
        <Triggers>
            <asp:AsyncPostBackTrigger ControlID="BtnUpload" 
             EventName="click" runat="server"/>
        </Triggers>
    </asp:UpdatePanel>

Я поместил оператор try / catch, чтобы посмотреть, смогу ли я получить более подробное окно с ошибкой, но ничего не появилось. Я, по крайней мере, ожидал, что индикатор выполнения заполнит 10% (он основан на атрибуте style ширины. Я не показывал подробно ни один из классов css, но идея индикатора будет меняться при изменении ширины). Но опять ничего не произошло, у меня была ошибка, где

ссылка на объект не установлена ​​для экземпляра объекта.

Ошибка возникает в строке 1 MAjax. Я не был уверен, что это значит.

1 Ответ

0 голосов
/ 14 января 2019
  1. Я не вижу FileUploadControl в вашем файле дизайна.

  2. updateP. Обновление не отправляйте измененный HTML на ваш веб-интерфейс немедленно. Он будет отправлен только в конце обработки страницы. Вам нужно использовать таймер, который будет отправлять асинхронный запрос на сервер и получать текущий статус загрузки. Я запускаю файл загрузки в отдельном потоке. Благодаря этому таймер включается и запускается на сервере без дополнительного клиентского кода. И я использовал кэш времени выполнения для хранения рабочего статуса.


<div class="row" style="margin-bottom: 1em;">
        <div class="col-md-12">
            <label class="file-upload" id="uploadText">
                <span>Update and view results</span>
                <asp:Button runat="server" ID="btnConvert" OnClick="btnConvert_Click" CssClass="hidden" />
            </label>
            <asp:Label CssClass="label" runat="server" ID="statusLabel"></asp:Label>
        </div>
    </div>

    <div class="row" style="margin-bottom: 1em;">
        <div class="col-md-3">
            <asp:FileUpload ID="fileUpload1" runat="server" />            
        </div>
        <div class="col-md-9">
            <asp:Button ID="btnUploadFile" Text="Upload file" runat="server" OnClick="btnUploadFile_Click" />
        </div>
    </div>

    <asp:Timer ID="timerGetStatus" runat="server" Interval="1000" OnTick="timerGetStatus_Tick" Enabled="false"></asp:Timer>

    <asp:UpdatePanel ID="updateP" runat="server" UpdateMode="Conditional" ChildrenAsTriggers="false">
        <ContentTemplate>
            <div class="row">
                <div class="progress">
                    <div id="loadbar" runat="server" class="progress-bar" role="progressbar" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100"></div>
                </div>
            </div>
        </ContentTemplate>
        <Triggers>
            <asp:AsyncPostBackTrigger ControlID="timerGetStatus" EventName="Tick" runat="server" />
        </Triggers>
    </asp:UpdatePanel>


Imports System.Threading
Imports System.Threading.Tasks

Public Class _Default
    Inherits Page

    Public Property FileId As Guid?
        Get
            Return CType(ViewState("FileId"), Guid?)
        End Get
        Set(ByVal value As Guid?)
            ViewState("FileId") = value
        End Set
    End Property

    Protected Sub Page_Load(ByVal sender As Object, ByVal e As EventArgs)
    End Sub

    Protected Sub btnConvert_Click(ByVal sender As Object, ByVal e As EventArgs)
        Task.Run(
            Sub()
                ConvertFile(FileId.Value)
            End Sub)
        timerGetStatus.Enabled = True
    End Sub

    Private Sub ConvertFile(ByVal workId As Guid)
        Save_CSV()
        Create_tables()
        Transfer_Tables()
        Update_Tables()
        Query_JSON()
    End Sub

    Private Sub Save_CSV()
        Dim text As String = GetFile()
        Thread.Sleep(1000)
        ChangeProgress(20)
    End Sub

    Private Sub Create_tables()
        Dim text As String = GetFile()
        Thread.Sleep(3000)
        ChangeProgress(30)
    End Sub

    Private Sub Transfer_Tables()
        Dim text As String = GetFile()
        Thread.Sleep(2000)
        ChangeProgress(50)
    End Sub

    Private Sub Update_Tables()
        Dim text As String = GetFile()
        Thread.Sleep(6000)
        ChangeProgress(80)
    End Sub

    Private Sub Query_JSON()
        Dim text As String = GetFile()
        Thread.Sleep(4000)
        ChangeProgress(100)
    End Sub

    Protected Sub timerGetStatus_Tick(ByVal sender As Object, ByVal e As EventArgs)
        ShowProgress()
        If GetProgress() = 100 Then
            timerGetStatus.Enabled = False
        End If
    End Sub

    Protected Sub btnUploadFile_Click(sender As Object, e As EventArgs)
        FileId = Guid.NewGuid()
        Cache($"File_{FileId}") = fileUpload1.FileBytes
        ChangeProgress(10)
        ShowProgress()
    End Sub

    Private Function GetFile() As String
        Return Encoding.UTF8.GetString(Cache($"File_{FileId}"))
    End Function

    Private Sub ChangeProgress(progress As Integer)
        Cache($"Progress_{FileId.Value}") = progress
    End Sub

    Private Function GetProgress() As Integer
        Return Cache($"Progress_{FileId.Value}")
    End Function

    Private Sub ShowProgress()
        If FileId.HasValue Then
            loadbar.Style.Add("Width", $"{GetProgress()}%")
        End If
    End Sub
End Class

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...