Hey, Watch this! October 28, 2009
Posted by markegilbert in Visual Studio/.NET.add a comment
I’m sure I am the second-to-last person* to realize this about the Visual Studio Watch window, but not only can you have it monitor public properties of an object, it can monitor private ones as well.
I think the barrier to me realizing that it could see the values for the public methods is that over half the time I’m relying on IntelliSense to drop something in. IntelliSense, of course, will only show the public properties of an object, or in the very least it won’t show private ones. The other day, I tried pasting in something like MyObject._MyPrivateVariable, and sure enough it worked. I didn’t realize what I had done until a few seconds after I hit Ctrl-V. When I had, I deleted it and manually typed the full variable reference out, just to confirm what I had done. Sure enough, IntelliSense stopped providing any information once I had "MyObject._" entered, but completing the private member name worked. The current value appeared immediately, and updated as the execution progressed.
This really shouldn’t have come as a surprise to me. Had I put a watch on just "MyObject" and then expanded the + sign next to it, the private members would have shown up then. These values also appear in the QuickWatch (available when you right-click on an object in code while you are in Debug mode) as well as in the Command Window.
It’s really cool when I get lucky and stumble onto something like this. Then again, even a stopped watch is right twice a day.
* The last person will be my 9-month-old daughter when she starts programming next month.
Unit testing with DBNull October 13, 2009
Posted by markegilbert in Agile, Visual Studio/.NET.add a comment
Recently, I was writing a class that would parse a DataRow (returned by a stored procedure) and construct a strongly-typed object from it. I wanted to test the case where the stored procedure returned DBNull for one of the fields. My first attempt at the unit test setup started out like this:
Dim DPTable As DataTable
Dim DataRowValues() As Object = {Value1, Value2, Value3, System.DBNull.Value, Value4}DPTable = New DataTable
DPTable.Columns.Add(New DataColumn(“Col1Name”, GetType(Long))
DPTable.Columns.Add(New DataColumn(“Col2Name”, GetType(String))
DPTable.Columns.Add(New DataColumn(“Col3Name”, GetType(Long))
DPTable.Columns.Add(New DataColumn(“Col4Name”, GetType(String))
DPTable.Columns.Add(New DataColumn(“Col5Name”, GetType(String))DPTable.Rows.Add(DataRowValues)
MyTestObject = New MyClass(DPTable.Rows(0))
Mock up a table and add a test row to it. Simple. The problem was the compiler complained about trying to directly assign System.DBNull.Value in the Object() array: "Value of type ‘System.DBNull’ cannot be converted to ‘String’."
Ok, so DBNull isn’t a value you can assign to a .NET object. What you CAN do, however, is use a valid value in the Object() array and then assign DBNull to that cell in the DataRow, but after you’ve added it to the DataTable:
Dim DataRowValues() As Object = {Value1, Value2, Value3, SomeValidValue, Value4}
…
DPTable.Rows.Add(DataRowValues)
DPTable.Rows(0).Item(“Col4Name”) = System.DBNull.Value
MyTestObject = New MyClass(DPTable.Rows(0))
That worked like a charm.
Cassini Web Server Silliness October 9, 2009
Posted by markegilbert in Visual Studio/.NET.add a comment
Recently I glanced down at my system tray to see this:
Yes, you’re actually seeing no less than six instances of the Cassini web server running on my machine (and yes, I do keep the Windows Task Bar on the left side of my screen). Visual Studio fires up one instance for every web application in a solution, so when you put it into debug mode, they all start up. It’s common for me to have more than one web app in a VS solution – main web site, admin tools, web service, web service test rig, etc. – but I definitely set a new personal record with this one.
Raising base class events September 28, 2009
Posted by markegilbert in Visual Studio/.NET.1 comment so far
On one of the forms of my side project, I grouped like controls into a series of custom user controls. Those user controls all shared a bit of functionality, so I decided to create a user control base class that all of the others inherited from. All of the common functionality lives in the base class where all of the deriving controls can use it.
One piece of that common functionality was an event called MessageGenerated. Something would happen in one of the user controls that would generate a message that the user needed to see. The main form (which contains all of these user controls) has an area where messages are displayed, so I wanted the user controls to raise the event and the main form to handle it. Seems simple enough.
I put the MessageGenerated declaration in the base class:
Public Event MessageGenerated(ByVal sender As Object, ByVal e As MessageEventArgs)
And then I tried raising the event from one of my user controls:
RaiseEvent MyBase.MessageGenerated(NewSender, New MyBase.MessageEventArgs(NewMessage))
That unfortunately resulted in a compile error:
Derived classes cannot raise base class events.
Yay. I found another specifically-disallowed feature of .NET. Yay.
After a bit of research, I came across this article that described why this was not allowed and how to get around it: http://msdn.microsoft.com/en-us/library/hy3sefw3(VS.80).aspx. The key sentence is here:
When you create a class that can be used as a base class for other classes, you must account for the fact that events are a special type of delegate that can only be invoked from within the class that declared them.
So, the solution (as this article describes) is to provide a Protected method in the base class that wraps RaiseEvent, which allows the derived classes to invoke the event indirectly. In particular, the methods needs to be “protected virtual void” in C#-ese, or “Protected Overridable Sub” in VB-ese:
Protected Overridable Sub OnMessageGenerated(ByVal NewSender As Object, ByVal NewMessage As String)
RaiseEvent MessageGenerated(NewSender, New MessageEventArgs(NewMessage))
End Sub
My derived classes can then call MyBase.OnMessageGenerated in place of RaiseEvent. The main form, then, handles this base class event for each of the controls, allowing me to address each control differently if I needed to:
AddHandler Me.BookFieldGeneralControl.MessageGenerated, AddressOf Me.MessageGeneratedHandler
AddHandler Me.BookFieldNotesCategoriesControl.MessageGenerated, AddressOf Me.MessageGeneratedHandler
AddHandler Me.BookFieldImagesControl.MessageGenerated, AddressOf Me.MessageGeneratedHandler
My buffer runneth over September 7, 2009
Posted by markegilbert in Tools and Toys, Visual Studio/.NET.add a comment
In the new release of NAntRunner, one of the new features is a checkbox to add the -verbose switch to the NAnt call. In the course of testing it, I found that NAnt would hang when I ran a non-trivial build and deploy script. When NAnt.exe hung, it locked up NAntRunner, too. If I ran that same script from the command line using NAnt (bypassing NAntRunner), it completed fine.
Through some tinkering I found that once NAnt.exe hung, I could kill it off using Task Manager and then NAntRunner would give me control back. I started doing some searching for “process.start hung” and “process.start doesn’t exit”, and eventually came to a couple of articles that talked about the output buffers filling up:
Both of these discuss redirecting the buffers for a spawned process. As it turns out, the buffers have a 2K limit and if they fill up, the process hangs. That sounded awfully familiar.
All versions of NAntRunner have redirected the standard output and error buffers for the spawned process so I could display the contents of those buffers in the NAntRunner interface. Before 0.4, I would wait until the process finished and then get the entire contents of the buffer:
Class NAntProcess
…
Public ReadOnly Property StandardError() As String
Get
Return Me._SystemProcess.StandardOutput.ReadToEnd
End Get
End Property
Public ReadOnly Property StandardError() As String
Get
Return Me._SystemProcess.StandardOutput.ReadToEnd
End Get
End Property
…
End Class
When I started using the verbose switch, the NAnt process hung because the process generated much more output than before (imagine that, “verbose” equals “more”), and the output buffers filled up before the process finished. So, I had to change how I was grabbing the output messages off.
The VelocityReviews.com link above mentions BeginOutputReadLine, so I did some more digging and came up with this MDSN article which shows how to pull these messages off asynchronously:
http://msdn.microsoft.com/en-us/library/system.diagnostics.process.beginoutputreadline.aspx
This involved handling the OutputDataReceived and ErrorDataReceived handlers for the process, and then appending the messages as they were generated using a pair of StringBuilder objects. The modifications looked like the following (only the relevant portions of the NAntProcess class are shown):
Class NAntProcess
Private _StandardOutputBuilder As StringBuilder
Private _ErrorOutputBuilder As StringBuilder
Public Sub New(ByVal NAntExecutablePath As String, _
ByVal NewScriptToRun As String, _
ByVal NewTargetFramework As String, _
ByVal NewBuildTarget As String, _
ByVal ShouldEnableVerboseMessages As String, _
ByVal NewOtherArgs As String)
…
‘ Configure the asynchronous output collection
Me._StandardOutputBuilder = New StringBuilder
Me._StandardOutputBuilder.AppendLine(Me._NAntExecutable & ” “ & Me.GetArgumentsForNAnt)
Me._StandardOutputBuilder.AppendLine()
Me._StandardOutputBuilder.AppendLine()
Me._ErrorOutputBuilder = New StringBuilder
AddHandler Me._SystemProcess.OutputDataReceived, AddressOf Me.StandardOutputHandler
AddHandler Me._SystemProcess.ErrorDataReceived, AddressOf Me.ErrorOutputHandler
End Sub
Private Sub StandardOutputHandler(ByVal sendingProcess As Object, ByVal outLine As DataReceivedEventArgs)
If Not String.IsNullOrEmpty(outLine.Data) Then
Me._StandardOutputBuilder.AppendLine(outLine.Data)
End If
End Sub
Private Sub ErrorOutputHandler(ByVal sendingProcess As Object, ByVal outLine As DataReceivedEventArgs)
If Not String.IsNullOrEmpty(outLine.Data) Then
Me._ErrorOutputBuilder.AppendLine(outLine.Data)
End If
End Sub
Public ReadOnly Property StandardOutput() As String
Get
Return Me._StandardOutputBuilder.ToString
End Get
End Property
Public ReadOnly Property StandardError() As String
Get
Return Me._ErrorOutputBuilder.ToString
End Get
End Property
End Class
After I got this implemented, I realized that I wouldn’t need the verbose switch to cause this problem. In theory, the “regular” output from a very involved NAnt script could cause the buffers to fill up. It’s just a fluke that I hadn’t hit this up to this point.
Unit Testing for Events July 8, 2009
Posted by markegilbert in Agile, Visual Studio/.NET.add a comment
This the second of a two-part series on Unit Testing. The first part covers testing for exceptions, while this one will illustrate events.
Here’s the scenario that I came across a week or so ago. I have a custom class that performs a potentially long-running import function, and I wanted to communicate to the invoking code when a record was successfully imported, and when a record was rejected for some reason (invalid data, wrong number of data points, etc.). The invoking code was actually the user form, and it was responsible for updating record stats (“Records Imported Successfully: 120″) and logging the rejected records with a meaningful error message so the user can examine them after the fact.
Up to this point, the unit tests for the Import class would pass in a set of delimited data rows, and then analyze the actual records imported or rejected. Now what I wanted to do was to write tests for the Imported and Rejected events that the class was going to throw. To do that, I followed the same general idea as with the unit tests for exceptions – handle the events like I would in “real” code, and make sure that they happen at the right times (or more specifically, that they happened with the expected frequency).
First, I started with a test:
…
Private WithEvents _MyImport As MyBusinessServices.Import
Private _ImportedCount As Integer
Private _RejectedCount As Integer…
<Test()> _
Public Sub DoImport_MinRequiredFields_AllRecordsImported()
Me._ImportedCount = 0
Me._RejectedCount = 0Me._MyImport = New MyBusinessServices.Import(42, “blah”)
AddHandler Me._MyImport.Imported, AddressOf Me.BookImported
AddHandler Me._MyImport.Rejected, AddressOf Me.BookRejected
Me._MyImport.DoImportAssert.AreEqual(3, Me._ImportedCount)
Assert.AreEqual(0, Me._RejectedCount)
End Sub
That in turn requires me to actually define the events that we’re going to be testing. This is done as part of my Import class (the one under test):
Public Event Imported(ByVal sender As Object, ByVal e As EventArgs)
Public Event Rejected(ByVal sender As Object, ByVal e As EventArgs)
It also required me to write the event handlers (part of the test fixture):
Private Sub BookImported(ByVal sender As Object, ByVal e As EventArgs)
Me._ImportedCount += 1
End SubPrivate Sub BookRejected(ByVal sender As Object, ByVal e As EventArgs)
Me._RejectedCount += 1
End Sub
All I’m doing here is counting how many records were imported or rejected given a particular data set. When my test runs and the DoImport method does its thing, I expect there to be one or more events raised. I have event handlers wired up listening for those events and they keep track of the number of times each event is raised. The assertions at the end of the test check those values.
As you can imagine, this is only the tip of what you can do with this general idea. In my production code, both the Imported and Rejected event use a custom class that descends from EventArgs to pass back some additional information about the item that was just imported or just rejected, and it tests that returned data to make sure it was what I expected given the input. I’ve removed this from the above code snippets to avoid muddling the core point (testing for events).
Additionally, the code shown here lacks much of the refactoring that the test fixture eventually went through. Again, I’ve simplified the structure to make my point clearer.
Unit Testing for Exceptions July 6, 2009
Posted by markegilbert in Agile, Visual Studio/.NET.add a comment
This is the first in a two-part series on unit testing. I’ll be covering the structures that I use in my unit tests for custom exceptions and events.
The basic idea for exceptions is that I do something in the unit test that should cause an exception to be thrown, and then wrap that code in a Try..Catch block to check that it IS thrown.
<Test()> _
Public Sub Save_WeightNotNumeric_CorrectExceptionThrown()
Dim MyObject As MyClass
Dim WasCorrectExceptionThrown As Boolean
Dim ExceptionText As String
WasCorrectExceptionThrown = False
ExceptionText = “{exception text was not set}”
Try
MyObject = New MyClass
MyObject.Save
Catch ex As MyClass.InvalidDataException
WasCorrectExceptionThrown = True
ExceptionText = ex.Message
Catch ex As Exception
WasCorrectExceptionThrown = False
ExceptionText = ex.Message
End Try
Assert.IsTrue(WasCorrectExceptionThrown, “Expected exception was not thrown; this one was: “ & ExceptionText)
Assert.IsTrue(ExceptionText.Contains(“field ‘Weight’”), “Exception thrown did not mention the correct field: “ & ExceptionText)
End Sub
The first Catch block looks for the exception that I’m expecting to be thrown, and sets WasCorrectExceptionThrown to True when it executes. I then include a second Catch block that handles any other exceptions thrown. In both cases I also save off the exception text for use in the Asserts.
The assertions look for two things – did the correct exception get thrown, and did that exception have the appropriate message*. The second of these two assertions will vary greatly depending on the particular needs of the test, and in many cases may not be needed at all.
Notice also that I set the ExceptionText variable to a known value before starting – “{exception text was not set}”. This allows the first assertion to cover both the case where the wrong (well, ok, the “expected”) exception was thrown as well as the case were no exception was thrown. I can see which case occurred based on the error message that appears in NUnit.
NUnit does provide an ExpectedExceptionAttribute (see http://www.nunit.org/index.php?p=exception&r=2.2.10 for more information), but that only allows the test to see if the correct exception was thrown. So far as I can tell there isn’t a way to inspect the message that comes back to make sure that it’s correct.
Next we’ll look at testing for custom events.
*You might ask “Mark, why are you passing information back in the message? If you’re going to go to the trouble to build custom exceptions, why not build a new custom exception for every exceptional case?” In a lot of cases I do, but in the cases where I am validating a slew of input parameters before doing some processing and I want to communicate when one doesn’t contain valid data, I’ll throw something like an InvalidDataException, and pass back the name of the field that was invalid. I tend to be lazy and will write these messages to be appropriate for the user, so class that catches the exception can simply clean up what it needs to based on the type of exception thrown and then pass the message back to the UI unmodified.
Fluorine did it, in the ASP.NET Temporary folder, using an InvalidCastException February 9, 2009
Posted by markegilbert in Visual Studio/.NET.add a comment
For two of my more recent projects, the Flash developers involved requested that we use FluorineFX to expose data and functionality as ActionScript Message Format (AMF) web services, allowing them to get data back from the service in strongly-typed ActionScript objects. With the exception of how FluorineFX is implemented under the hood (as an HttpModule instead of an HttpHandler which I think would have made more sense), it turned out to be surprisingly easy to use.
Things seemed to be going well (as they normally do) until we deployed to production (again, as they normally do). In production we noticed that the Flash units would sometimes jam, and you’d have to refresh them several times in a row to get them to show any data coming from the web services. Now normally with a situation like this, I’d fire up Fiddler to watch the traffic between the server and the client. In this case, however, Fiddler couldn’t help all that much because it doesn’t support AMF natively. AMF is a binary format, you see, and while there is some sporadic talk on the internets about a plug-in for Fiddler to decrypt the AMF traffic, I have yet to find one. What does work for this situation is another web proxy called Charles (which one of the Flash devs I was working with swears by). With it, I could see the AMF traffic going back and forth, including one very interesting exception:
InvalidCastException: Unable to cast object of Type ‘X’ to ‘X’
Oh, ASPNET, why the heck are you trying to cast from X to X, and what’s the problem when you do? After consulting with my pal Google, I found this post by Henning Krause. While this was, in fact, the error I was seeing, I wasn’t trying to use Assembly.LoadFile or Assembly.LoadFrom. I wasn’t even trying to cast anything (X-to-X or otherwise). In the immortal words of the Falcon’s Captain – “It’s not my fault!”
After mulling it over for a bit, I theorized that while MY code wasn’t casting anything, perhaps Fluorine was. After all, it had the task of translating an AMF stream to my objects and back again – perhaps IT was using LoadFile or LoadFrom behind the scenes.
I also thought about the strangeness of the issue itself – we never saw this in development, staging, or pre-production. Why production? And why does it seem to work sometimes and not others? What was different? Well, for one, the production server was not one server – it was actually a load-balanced pair of web servers. Ok, if one server was having a bad day, and the other was all rainbows and sunshine, perhaps my repeated requests were hitting one server some of the time and the other the rest. That would explain the intermittent-y nature of the issue. After pointing my HOSTS file to each server and retesting the service, I found that one server would reliably work every time, and the other would reliably fail every time.
The first thing we tried was bouncing the App Pool for the site in question (we had fortuitously placed this particular site in its own App Pool, so this was the only site affected). This didn’t seem to do the trick; the server was still throwing the Invalid Cast Exceptions.
I re-read Krause’s article and pulled in a colleague of mine to get another perspective. One of the sentences in the post caught my attention: “The runtime does not actually run the assemblies from the path the IIS virtual directory points. Instead it copies all assemblies to the Temporary ASP.NET Files…” Ok, let’s continue on this limb, and theorize that there is an out-of-date copy of my assembly (where type X was found) in the ASP.NET Temp folder. Perhaps Fluorine is trying to get the class definition from the /bin copy and trying to instantiate the object from the Temporary ASP.NET copy (or vice versa), and perhaps it’s using LoadFile/LoadFrom to do it.
Well, we’ve made it this far out on the limb – we might as well take the final plunge.
If all of the above was correct, we’d expect to find an out-of-date copy of the assembly in the Temp folder on the bad server, and the correct version on the other one. As it turns out, we found that the bad server had TWO copies of the assembly – the most recent plus an older one, while the other server had only the most recent. We tried deleting the two copies of the assembly from the bad server’s Temp folder (as well as the accompanying assembly.info file in the directory), but the server complained that the files were in use. We stopped the sites in IIS, tried the delete again (which worked), and restarted IIS for those sites. When I hit the bad server again, we saw a single copy of the assembly get placed in the folder, and the service started working again. Now that both nodes in the farm were working, I could hit the Flash units with impunity, and it would reliably return data.
In retrospect this kinda makes sense, but only kinda. At least now we have a procedure for correcting the condition when it occurs, but I still don’t understand how the server got into the state in the first place, which means I don’t understand how to prevent this from happening again with future deployments.
Upcoming MDSM Meeting – October October 5, 2008
Posted by markegilbert in General, Visual Studio/.NET.add a comment
We needed to change hosting providers for the DevMI.com site, so I thought this would be a perfect time to dive into something new, specifically the ASP.NET MVC Framework. I will be presenting an introduction to the framework (using the new site as my example) at the October 23 MDSM meeting. If you’re in the Kalamazoo area on the 23rd, please feel free to join us. We’d appreciate a quick RSVP at Contact@DevMI.com to let us know to expect you.
Hope to see you there!
Be kind to your grey matter: Class Properties September 30, 2008
Posted by markegilbert in Visual Studio/.NET.add a comment
There are a couple of patterns that I’ve frequently used in the past to simplify getting raw data from a query string parameter, form, or session variable or setting data on a form or session variable. These two patterns have the same basic approach – encapsulate the processing logic in a property.
For the former, the pattern would work something like this:
Private ReadOnly Property Quantity() As Integer
Get
If(IsNothing(Request.QueryString(“quantity”))) Then Return 0
If(Not IsNumeric(Request.QueryString(“quantity”))) Then Return 0
Return CType(Request.QueryString(“quantity”), Integer)
End Get
End Property
As you can see, I can now simply say “Me.Quantity” in code, and all of the validation and “cleanup” is done for me in the Property getter.
The second pattern involves wrapping a form field in a property:
Private Property Quantity() As Integer
Set(ByVal value As Integer)
Me.QuantityField.Text = value.ToString.Trim
End Set
Get
If(Me.QuantityField.Text.Trim.Length = 0) Then Return 0
If(Not IsNumeric(Me.QuantityField.Text)) Then Return 0
Return CType(Me.Quantity.Text, Integer)
End Get
End Property
Again, the logic is contained in the Property, and all I have to say in code is “Me.Quantity”.
In both of these cases, the grey matter upstairs only has to think about “something = Quantity” or “Quantity = something”, and not have to remember to clean the data up each time a session object is reference, or a form field is set.
I hit a case late last week where I needed both patterns for the same logical piece of data (quantity, in this case). The page would accept the quantity on the query string, and would store it in a field on the form. My first thought was to handle this with a single property, like the following:
Private Property Quantity() As Integer
Set(ByVal value As Integer)
Me.QuantityField.Text = value.ToString.Trim
End Set
Get
If(IsNothing(Request.QueryString(“quantity”))) Then Return 0
If(Not IsNumeric(Request.QueryString(“quantity”))) Then Return 0
Return CType(Request.QueryString(“quantity”), Integer)
End Get
End Property
Which would have meant that I would have used something like this in code:
Me.Quantity = Me.Quantity
Ouch! Ok, grey matter is twitching!
It didn’t take me long to decide that that would be WAY too confusing for me to hit 6 months from now when I’m trying to maintain this page, let alone for another, unsuspecting, developer. I came up with Plan B. I created two properties: one called “DefaultQuantity” which was ReadOnly and would handle grabbing the value off of the query string; the other called “SpecifiedQuantity” which would wrap the form field. Then my assignment looked like this:
Me.SpecifiedQuantity = Me.DefaultQuantity
Ah. Much better. Grey matter happy now.