|
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.
|
|
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!
|
|
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.
|
|
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.
|
|
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
|
|
Rank: Administration Groups: Administration
Joined: 5/27/2007 Posts: 24,194
|
Excellent. Thanks for sharing!
|
|
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/2TN8Just 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.
|
|
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!
|
|