Welcome Guest Search | Active Topics | Sign In | Register

How to report exception from Progress Bar RunTask Event. Options
tarekahf
Posted: Monday, February 27, 2012 7:49:54 AM

Rank: Advanced Member
Groups: Member

Joined: 3/27/2010
Posts: 48
I am trying to implement Prograss Bar after I reviewed carefully the sample code of the "Server Side Task".

I notcied that when the "RunTask" even is executing, and there is an Exception which requires to be reported back to the UI (Web Form), then nothing happens. In other words, my code is writing the Error Message to the UI part, but it does not show. I think I am not doing it the right way.

See the sample code below:

Code: Visual Basic.NET
Protected Sub pbRefreshDBFlds_RunTask(ByVal sender As Object, ByVal e As EO.Web.ProgressTaskEventArgs) Handles pbRefreshDBFlds.RunTask
        Dim theRefreshDBFldsCmd As CSLAIDB.Library.SPMSForm.RefreshDBFieldsCommand
        Dim theMsg As String = String.Empty
        Try
            theRefreshDBFldsCmd = SPMSForm.RefreshDBFields(GetUserCtrlInfoPack(), False, e)
            If theRefreshDBFldsCmd.Success Then
                ConfMsg = theRefreshDBFldsCmd.Messages(0)
            Else
                theMsg = String.Empty
                For Each theMsgItem As String In theRefreshDBFldsCmd.Messages
                    theMsg &= theMsgItem & "<br/>"
                Next
                If Not String.IsNullOrEmpty(theMsg) Then
                    theMsg.Remove(theMsg.Length - 6)
                End If
                ErrMsg = theMsg
            End If
        Catch ex As Exception
            ErrMsg = ex.Message & "<br/>" & ex.StackTrace
            Response.Write("Hello<br/>")
        End Try


In the "Catch" part above, even when I try to write something to the UI, it does not show (writing "Hello" to the Response). Also, the Error Message is not showing at all.

What I am doing worng?

How I can control Exception in the "RunTask" event, and how I can report the error to the user?

Appreciate your help.

Tarek.
eo_support
Posted: Monday, February 27, 2012 10:35:38 AM
Rank: Administration
Groups: Administration

Joined: 5/27/2007
Posts: 24,194
Hi,

The only way to pass information down the the client inside RunTask is by calling e.UpdateProgress. You can pass your error message information through the second argument. You would then handle the ProgressBar's ClientSideOnValueChanged to examine whatever information you passed down from the server and act accordingly.

Thanks!
tarekahf
Posted: Monday, February 27, 2012 1:58:13 PM

Rank: Advanced Member
Groups: Member

Joined: 3/27/2010
Posts: 48
Thanks... it worked like a charm. It was very easy ... much more than I expected.

During the "RunTask" process, unexpected error might happen, and after the process, I want to pass back to the client the results like "40 out of 50 records porcessed successfully". Also, the process may generate an Array of String of error messages, such errors are expected and controlled. The user must get as much details as needed to help him correct the errors.

So, in summary, the outcome (feedback) of the update is not simple.

For example, if there are errors, then I want to show all the messages in red color. If there are no errors, I want to show the message in green color. On the server side, it is very easy to control where the message will be shown, and what is the style to be used.

What kind of Data Type I can pass back from the server to the client? Only simple text? Can I return complex structure with arrays ...etc?

If my understanding is correct, I can only pass string, then I need to format the data to be returned to the client. On the client side, I have to parse the content using JavaScript, and act accordingly.

Appreciate your feedback.

Tarek.
eo_support
Posted: Monday, February 27, 2012 4:07:59 PM
Rank: Administration
Groups: Administration

Joined: 5/27/2007
Posts: 24,194
Yes. You understood it correctly. The argument is defined a string. So "what kind of data type" is a non-question. There is no magic here.
tarekahf
Posted: Wednesday, March 14, 2012 7:51:15 AM

Rank: Advanced Member
Groups: Member

Joined: 3/27/2010
Posts: 48
This is the final version showing the approach I followed to control how to send errors/success message to the client.

Code: CSS
.tblrowErrMsg td img
{
    margin-right:5px; 
}

.lblErrMsg 
{
    color:Red;
    display:inline;
    padding-top:10px;
}

.tblrowConfMsg img 
{
    vertical-align:middle;
}

.lblConfMsg 
{
    color:Green;
    display:inline;
    padding-top:10px;
}


Following is part of the HTML Table where it will display the error/confirmation:

Code: HTML/ASPX
<tr runat=server  id="tblrowErrMsg" style="display:none" class="tblrowErrMsg">
<td colspan=3 style="text-align:center;"><img src="Images/exclamation.png" /><asp:Label ID="lblErrMsg" CssClass="lblErrMsg" runat="server">This is an error</asp:Label></td>
</tr>
<tr runat=server  id="tblrowConfMsg" class="tblrowConfMsg" style="display:none" >
<td colspan=3 style="text-align:center;"><img src="http://img2.b8cdn.com/images/icons/status-success.png"/><asp:Label ID="lblConfMsg" CssClass="lblConfMsg" runat="server"></asp:Label></td>
</tr>


Following is the script that will pass the error back to the client:

Code: JavaScript
function OnProgress(progressBar)
{
	var extraData = progressBar.getExtraData();
	if (extraData)
	{
		//The following code demonstrates how to update
		//client side DHTML element based on the value
		//RunTask passed to us with e.UpdateProgress
		var elmMsg;   // Message Element
		var elmCont;  // Message Container Element
		var theMsg='';
		// Look for Indicator in the beginning of the extraData
		if (extraData.substr(0,5) == '*err*') {
		    // Error ..
		    theMsg = extraData.substr(5);
		    elmCont = document.getElementById('<%=ErrMsgContElmID()%>');
		    elmMsg = elmCont.getElementsByTagName('span').item(0);
		} else if (extraData.substr(0,6) == '*conf*') {
		    // Confirmation
		    theMsg = extraData.substr(6);
		    elmCont = document.getElementById('<%=ConfMsgContElmID()%>');
		    elmMsg = elmCont.getElementsByTagName('span').item(0);
		} else {
		    // If no indicator, then assume it is error !!
		    theMsg = extraData.substr(0);
		    elmCont = document.getElementById('<%=ErrMsgContElmID()%>');
		    elmMsg = elmCont.getElementsByTagName('span').item(0);
		}
		if (theMsg != '') {
		    elmCont.style.display = 'block'
		} else {
		    elmCont.style.display = 'none'
		}
	    elmMsg.innerHTML = theMsg;
	}
}


Following is the code behind that will execut the Business Logic via the Progress Bar Run Task:
Code: Visual Basic.NET
Protected Sub pbRefreshDBFlds_RunTask(ByVal sender As Object, ByVal e As EO.Web.ProgressTaskEventArgs) Handles pbRefreshDBFlds.RunTask
        Dim theRefreshDBFldsCmd As CSLAIDB.Library.SPMSForm.RefreshDBFieldsCommand
        Dim theMsg As String = String.Empty
        Try
            theRefreshDBFldsCmd = SPMSForm.RefreshDBFields(GetUserCtrlInfoPack(), False, e)
            If theRefreshDBFldsCmd.Success Then
                e.UpdateProgress(100, "*conf*" & theRefreshDBFldsCmd.Messages(0))
            Else
                theMsg = String.Empty
                For Each theMsgItem As String In theRefreshDBFldsCmd.Messages
                    theMsg &= theMsgItem & "<br/>"
                Next
                If Not String.IsNullOrEmpty(theMsg) Then
                    theMsg.Remove(theMsg.Length - 6)
                End If
                e.UpdateProgress(0, "*err*" & theMsg)
            End If
        Catch ex As Exception
            'ErrMsg = ex.Message & "<br/>" & ex.StackTrace
            e.UpdateProgress(0, "*err*" & ex.Message)
            'Response.Write("Hello<br/>")
        End Try

    End Sub


Following is the actual business logic:

Code: Visual Basic.NET
<Serializable()> _
    Public Class RefreshDBFieldsCommand
        Inherits CommandBase

        Private mRecordsToBeRefreshedCnt As Integer
        Private mRecordsRefreshedCnt As Integer
        Private mDoGetCountOnly As Boolean
        Private mUserCtrlInfoPack As UserCtrlInfoPack
        Private mEOTaskArgs As EO.Web.ProgressTaskEventArgs
        Private mMessages As New List(Of String)
        Private mSuccess As Boolean

        Public ReadOnly Property RecordsToBeRefreshedCnt() As Integer
            Get
                Return mRecordsToBeRefreshedCnt
            End Get
        End Property

        Public ReadOnly Property RecordsRefreshedCnt() As Integer
            Get
                Return mRecordsRefreshedCnt
            End Get
        End Property

        Public ReadOnly Property PercentCompleted() As Integer
            Get
                Return (mRecordsRefreshedCnt / mRecordsToBeRefreshedCnt * 100)
            End Get
        End Property

        Public ReadOnly Property Messages() As String()
            Get
                Return mMessages.ToArray()
            End Get
        End Property

        Public ReadOnly Property Success() As Boolean
            Get
                Return mSuccess
            End Get
        End Property

        Public Sub New(ByVal theUserCtrlInfoPack As UserCtrlInfoPack, ByVal DoGetCountOnly As Boolean, Optional ByVal theEOTaskArgs As EO.Web.ProgressTaskEventArgs = Nothing)
            mUserCtrlInfoPack = theUserCtrlInfoPack
            mDoGetCountOnly = DoGetCountOnly
            mEOTaskArgs = theEOTaskArgs
            mSuccess = True
        End Sub

        Protected Overrides Sub DataPortal_Execute()
            Dim theSPMSForm As SPMSForm = Nothing
            Dim theStaffID As String
            Dim theReviewFrom As String
            Dim theMsg As String
            Using cn As New SqlConnection(Database.SPMSFormDB)
                cn.Open()
                Using cm As SqlCommand = cn.CreateCommand
                    cm.CommandType = CommandType.StoredProcedure
                    cm.CommandText = "uspSPMSFormListGetRecVer"
                    cm.Parameters.AddWithValue("@RecVer", SPMSForm.GetSPMSFormInits.LatestRecordVersion)
                    mRecordsToBeRefreshedCnt = 0
                    mRecordsRefreshedCnt = 0
                    Using da As New SqlDataAdapter(cm)
                        Using ds As New DataSet
                            da.Fill(ds)
                            mRecordsToBeRefreshedCnt = ds.Tables(0).Rows.Count
                            If Not mDoGetCountOnly Then
                                If Not mEOTaskArgs Is Nothing Then
                                    mEOTaskArgs.UpdateProgress(0)
                                End If
                                For Each theRow As DataRow In ds.Tables(0).Rows
                                    theStaffID = theRow.Item("StaffID")
                                    theReviewFrom = theRow.Item("ReviewFrom")
                                    mUserCtrlInfoPack.SetQueryUser(theStaffID)
                                    Try
                                        theSPMSForm = SPMSForm.GetSPMSForm(cn, mUserCtrlInfoPack, theReviewFrom)
                                        theSPMSForm.SetSubmitActionRefreshDBFlds()
                                        theSPMSForm.SaveForm()
                                    Catch ex As Csla.Validation.ValidationException
                                        mSuccess = False
                                        mMessages.AddRange(theSPMSForm.BrokenRulesCollection.ToArray())
                                    Catch ex As Exception
                                        mSuccess = False
                                        theMsg = _
                                            String.Format(My.Resources.ErrRefreshDBFlds, _
                                                        ex.Message, theSPMSForm.GetObjectName(), theSPMSForm.IDStr, _
                                                        mUserCtrlInfoPack.AuthUserID)
                                        mMessages.Add(theMsg)
                                    End Try
                                    mRecordsRefreshedCnt += 1
                                    theSPMSForm = Nothing
                                    If Not mEOTaskArgs Is Nothing Then
                                        mEOTaskArgs.UpdateProgress(PercentCompleted)
                                    End If
                                Next
                                If mSuccess Then
                                    theMsg = _
                                        String.Format( _
                                            My.Resources.RefreshDBFldsConf, _
                                            SPMSForm.GetSPMSFormInits.GetObjectName(), mRecordsRefreshedCnt.ToString, _
                                            mRecordsToBeRefreshedCnt.ToString)
                                    mMessages.Add(theMsg)
                                End If
                                If Not mEOTaskArgs Is Nothing Then
                                    mEOTaskArgs.UpdateProgress(100)
                                End If
                            End If
                        End Using
                    End Using
                End Using
            End Using

        End Sub
    End Class


Now, it is working as it should.

I hope this is the best way to implement Progress Bar with support for passing Error/Confirmation Message to the client.

Tarek
eo_support
Posted: Wednesday, March 14, 2012 9:05:35 AM
Rank: Administration
Groups: Administration

Joined: 5/27/2007
Posts: 24,194
Excellent. Thanks for sharing!
tarekahf
Posted: Wednesday, March 14, 2012 10:18:46 AM

Rank: Advanced Member
Groups: Member

Joined: 3/27/2010
Posts: 48
Thanks for comment.

Kindly see a short demo of the progress bar here:

http://www.screenr.com/2TN8

Just allow me to report very minor issues:

1. Why when it reaches 100% there is still small part of the bar at the end (right-side) which is not colored?

2. How I can show the precentage completed text in clear colors, as when it is covered with progress, it is not very clear.

But the above is not very important, if there is no solution, no problem!

Tarek.
eo_support
Posted: Wednesday, March 14, 2012 3:45:39 PM
Rank: Administration
Groups: Administration

Joined: 5/27/2007
Posts: 24,194
Hi,

I am not sure why there is a small part that is not colored. If you can provide a test page we will be happy to take a look.

You can not use clear colors for both sides of the ProgressBar text. Currently the ProgressBar uses control's ForeColor to render text when it is not overlapping with the background, and uses the corresponding negative color when it is overlapping with the background. Unfortunately this logic is hardcoded so there is no option to change it anyway.

Thanks!


You cannot post new topics in this forum.
You cannot reply to topics in this forum.
You cannot delete your posts in this forum.
You cannot edit your posts in this forum.
You cannot create polls in this forum.
You cannot vote in polls in this forum.