July 24, 2018 08:49 by
Peter
Today while testing we encountered a strange scenario in our Silverlight Web App. We were getting a System Win 32 error when running the deployed application. unfortunately the error was not reproducible when running the app in debug (F5) mode.
Here is a snapshot of the exception message.
When starting a new instance of Visual Studio to debug this JIT issue all we got was that there was a Stack Overflow causing this issue. But that's all; no source code or stack trace to pinpoint the exact code that was causing the trouble.
How often do you get in a scenario where you can see a bug in deployed or published code but not in debug mode giving you no option to pinpoint the exact code causing the trouble? Believe me, it happens to me all the time.
I pop-in many Message Boxes in the methods that I feel could be erroneous & keep deleting them when I am sure that the method is not the one I am looking for.
Returnng to the issue today, I have a record in my Silverlight Grid, which when double-clicked should open a child window having the details & this part of the code was the culprit. Feels great to zero-in & find the guilty.
So the problem is in the child window looking forward tells me it's a TextBox that has the ValidatesOnDataErrors property set to true.
Here was how it was layed out on the screen:
<TextBox Text="{Binding ProfileName,ElementName=RadWinEditMenuProfile, Mode=TwoWay, NotifyOnValidationError=True, ValidatesOnExceptions=True,ValidatesOnDataErrors=True, TargetNullValue=''}"
x:Name="txtBoxProfile" MaxLength="50" />
Notice the ValidatesOnDataErrors=True property. So next step was to remove it & Voila! It worked. No error this time. But wait, we have that property set for a reason. We want to force the TextBox to show an error on all data validation errors. Having that figured out I knew the next thing we need to look into was the code that was doing the data validation.
Here is the code used for it:
Public ReadOnly Property [Error] As String Implements System.ComponentModel.IDataErrorInfo.Error
Get
Return _Errors
End Get
End Property
Default Public ReadOnly Property Item(propertyName As String) As String Implements System.ComponentModel.IDataErrorInfo.Item
Get
Select Case propertyName
Case "ProfileName"
If String.IsNullOrWhiteSpace(ProfileName) = False Then
'ProfileName = ProfileName.Trim
If context.MenuProfiles.Any(Function(t) t.Id <> SelectedProfile.Id AndAlso t.ProfileName.ToLower.Trim = ProfileName.ToLower.Trim) Then
_Errors = _ErrorsText
Return "Profile Name is already in use."
ElseIf Regex.IsMatch(ProfileName.ToLower.Trim, CustomDeclaration.REG_NAME) = False Then
_Errors = _ErrorsText
Return CustomDeclaration.INVALID_NAME
End If
End If
Exit Select
End Select
Return Nothing
End Get
End Property
Private _ProfileName As String
Public Property ProfileName() As String
Get
Return SelectedProfile.ProfileName
End Get
Set(ByVal value As String)
_ProfileName = value
SelectedProfile.ProfileName = value
NotifyPropertyChanged("ProfileName")
End Set
End Property
This is a standard implementation of IDataErrorInfo, so I will not get into the gory details of it and go directly to the code that was the issue.
Note that I have commented-out the line:
'ProfileName = ProfileName.Trim
This was the exact line of code causing the issue. I was trimming the property & then assigning it back, that in turn was calling the setter of the property & that in turn was calling the validation again.
Evidently, these two caused an infinite loop L L Not a good deal. This was the reason why we were getting the Stack Overflow error. Commenting out that line & using trim wherever we were actually using the property.
For example:
Changed ProfileName.ToLower to ProfileName.ToLower.Trim fixed the issue once & for all. Nice & Cool.
So the next time you hit a stack overflow in your published code try to pin point the code & check if you are not implementing IDataErrorInfo or any other 2 properties that are dependent on each other like I was implementing it.