TFS and Baby Steps

I just finished attending ObjectSharp's SMART (Software MAnagement Round Table) session on the impact of quality assurance on the development process and had a couple of observations to share.

First off, the biggest takeaway from the session is the need to move quality to the front of the development process. In this way, quality is a lot like security. There is no way to create a really secure application by adding security features at the end of the development cycle. In the same way, there is no magic powder that can be sprinkled on a completed application to greatly improve its quality. The overall quality of an application is found in its architectural choices, whether it was designed to be testable and the approach taken by the development staff with regards to testing.

However, one of the conversations I had with an attendee regarding Visual Studio Team Systems was just as interesting. He had just installed Team Foundation Server and had created a team project using the default Agile template. The team project he created was going to be for a working application. I found this approach interesting, not the least because (by his own admission) there was no "process" for developing software currently in play.

The interesting aspect (for me) was the supposed lack of software development process in his company. I would strongly suggest that there really was a process in place. Even though you might not think a process is in place with your development team, doesn't mean that a process doesn't exist. In any kind of team development environment, processes will form. It's just a question of how formal the process is. So your 'lack of process' (call it an unprocess) is really just a lack of documentation and formalization. Because of its lack of formality, unprocesses frequently operate below the radar of even the people involved.

If you haven't worked with Team Systems before, let me preface my comments by saying that it absolutely introduces structure to the development process. If you plan on using it 'out of the box' with no customization, you will need to use the process described by one of the canned templates. For those who don't currently have a process, the Agile template is the most likely starting point. But the Agile template includes process. There is a workflow for tasks. There is a workflow for defects. And workflow equals process.

I can appreciate the idea behind starting out with the canned templates. Its presence would indicate that it's a process with proven success. And using the product as it arrives is a first, small 'baby step' into the world of development process. The problem is that the first step you're taking isn't a small one. Instead, you have taken a giant step into the world of Agile development. Complete with all of the process that is codified in the Agile template. And Agile has more process than most people think. The result is that the first 'baby' step can be a killer for Team Systems.

If someone new to a development process truly wants to take baby steps with TFS, they should start by thinking about the unprocess which is currently being used in their organization. Spend a day or even a few hours talking to someone who is familiar with development methodologies, to identify the flows that are currently at play. The default template should be customized to follow this unprocess. Then, over time, the structure originally defined by the Agile template can be added back in, if needed.

Does this require a little more effort on your part? Yes. But the steps involved in modifying the template are both well documented and fairly easy to follow. By taking this approach, you truly can learn Team Systems by taking baby steps. And this is a lot less painful than trying to make the leap from unprocess to Agile.

WebParts and the need for a Database

I'm doing some work creating WebPart components in ASP.NET 2.0 and discovered a dependency that I wasn't initially expecting...the need for a database.

It appears that in order to even place a WebPart onto a form, you need to have a database. Or at least a persistent data store. A little bit of investigation found this information available in a number of places. The WebPart isn't actually the problem, so much as the WebPartManager. The manager is responsible for keeping track of the various WebPartZones and which WebPart is in which Zone. To persist this information across iterations of the page, the location information is stored in a database. So, even when the page is displayed the first time, a database connection needs to be available.

While you can create your own provider, the easiest mechanism is to use the aspnetdb, which is also used by the Membership and Role providers. To add the database to an existing SQL Server instance (either SQL Server 2000 or 2005), use the aspnet_regsql command, which is found in c:\Windows\Microsoft.NET\Framework\v2.0.50215. Once the database is available, a connection string (call it AspNetDbConnectionString to match the upcoming example) should be defined in the web.config file, along with a webParts element that includes a personalization tag, similar to the following:

<webParts>
  <personalization defaultProvider="SqlPersonalizationProvider">
    <providers>
      <add name="SqlPersonalizationProvider"
        t
ype="System.Web.UI.WebControls.WebParts.SqlPersonalizationProvider"
        connectionStringName="AspNetDbConnectionString"
        applicationName="/" />
    </providers>
    <authorization>
      <deny users="*" verbs="enterSharedScope" />
      <allow users="*" verbs="modifyState" />
    </authorization>
  </personalization>
</webParts>

Decrypting Stored Procedures

As part of work that I was doing recently, I had to generate the creation script for a SQL Server database. While running through the Generate Script task in Management Studio, I received an error that indicated that the stored procedure was encrypted. Never having running into encrypted stored procedures before, I was a little surprised. It turns out that encrypted stored procedures can’t be scripted. Could be that they’re encrypted. Duh!

Anyway, the documentation says that, for encrypted stored procedures, it is important to generate the creation script prior to encryption. So I started asking the client if they had the creation scripts. It turns out that a previous DBA had invoked the annoying ‘job security’ clause when creating the stored procedures, so the creation scripts were nowhere to be found.

Some additional research on the problem and I find a third party component that can decrypt the stored procedures. It’s called SQL Decrypter and it’s from Orbital Technologies (http://www.orbitaltechnologies.org/decryptor/). I have to say, it’s a nice tool. Does exactly what it’s supposed to do, quickly, easily and painlessly. So the client gets the generation scription and Orbital gets another (I’m sure) satisfied customer.

DataFormatString doesn't seem to work on BoundField elements

I was using the BoundField element in ASP.NET 2.0’s GridView control. More specifically, I was attempting to use the DataFormatString element in order to change the look of dates and dollar amounts as they get displayed. Much to my dismay, it didn’t look like the format string was being applied to the data.

After digging around a bit (and making sure that my memory of the format codes was accurate), it turns out that the problem is caused by a combination of factors. The first is that the default value for the HtmlEncode is true. The HtmlEncode property determines whether the value of the bound field is HTML encoded before being transmitted to the browser. The second factor is that, when the DataFormatString is applied to the value, any HTML encoding takes place prior to the formatting.

When, for example, a date is rendered, the date value is converted to string using the ToString() method. The string is then HtmlEncoded. Finally, the String.Format method is used to format the string using your format codes. However, your date format codes won’t work because the ‘date’ is no longer a DateTime variable. It’s a string. So instead of formatting the data, it is displayed using the ToString() layout. The same problem exists for other non-string types, including currency, floats, etc.

The solution is to set the HtmlEncode attribute to false on the BoundField element. Now the value is not converted to a string prior to the Sting.Format method call, the result being that the String.Format method uses the typed value (not the ToString version) and the format string in the manner that you (and I) expect.

Register for the Toronto Code Camp

The registration page has been available since the middle of December (at http://www.torontocodecamp.net), but my heads-down end of year mode kept me from mentioning it until now.

If you’re not familiar with the Code Camp concept, it is a free day-long conference on all things geeky. Geeky to developers, that is. Code Camps are run on a Saturday to give people who might not normally be able to attend a conference the opportunity. The Toronto Code Camp has its focus on Microsoft technologies (although not exclusively) and includes content on current and future technologies, both at the introductory and advanced level.

For those of you who don’t get enough technology during the course of a normal week, the Code Camp is a wonderful opportunity to get the latest and greatest in information from some wonderful speakers. Also, if you have wanted to speak to a group of enthusiastic users, the Code Camp provides a nice, safe, informal environment to get started.

So if you haven’t registered already, get to the Toronto Code Camp site and sign up now. You’ll get much more than your money’s worth. :)

Team Foundation Server and SQL Collations

I just got through a grueling session of installing the release candidate for Team Foundation Server. And by grueling, I mean about 16 hours worth. And given all of the glowing reports, I was surprised that this install turned about to be more challenging that the Beta 3 Refresh.

My problem centered around one particular point in the process. After having installed IIS, SQL Server, and Sharepoint Services on a fresh version of Windows 2003 (and the .NET 2.0 Hotfix), the installation of TFS performs a health check. My results coming out of the health check was that the running SQL Server instance was using an unsupported collation. Now while I have installed SQL Server many times, I’ve never given much thought to the collation. So I started looking at the problem. Since I had made no changes during SQL Server installation (with respect to collation), I uninstalled SQL Server and reinstalled it specifically choosing the Latin1_General option. Also, because the instructions in the installation help file said that TFS didn’t support case sensitive, binary or binary 2 collations, I left all of the check boxes on that form blank. To no avail. The SQL Server collation was not supportable by TFS

Just to be clear, after all of the dust had settled, my SQL Server’s collation was Latin1_General_CI_AI and TFS just didn’t like that.

So I go digging into the installation log file and come across the SQL statement which gets executed as part of the collation health check:

SELECT * FROM (SELECT CONVERT(char(100), SERVERPROPERTY('collation')) AS Collation) as c WHERE (Collation LIKE '%[_]CS%') OR (Collation LIKE '%[_]AI%') OR (Collation LIKE '%[_]BIN%') OR (Collation LIKE '%[_]BIN2%')

The thing that stood out for me was the inclusion of the Collation Like ‘%[_]AI%’ clause. Unless I’m reading this wrong, it means that TFS doesn’t like Accent Insensitive collations. And I don’t see this small tidbit documented anyplace.

The sole bright spot is that after I reinstalled SQL Server with the ‘Accent – sensitive’ check box on the Collation Settings portion of the installation checked, all went well. I now have a running version of TFS that is capable of working over HTTP. Let the games begin.

 

Java, .NET, Web Services and Enums

While working on getting a Java Web service and a .NET Web service client to talk to one another, I ran into an interesting situation. The problem had to do with the WSDL being produced by the Java service. Actually, the entire process involved the following steps:

  • An interface written in C# was used to generate a WSDL file.
  • That WSDL file was imported into JDeveloper and a web service was created
  • The WSDL file exposed by the JDeveloper web service was used (through the wsdl.exe tool) to create a proxy class to be used by a .NET client.

The problem was caused by enumerations being used in the interface. The WSDL file generated using the C# interface included defined a separate type (with a base of string) for each enumeration and then restricted the string values for that type. However, the WSDL file exposed by the JDev web service expected that the enumerated parameters would be of type string. Not the restricted, created type that C# wants to send. The resulting type mismatch caused the requests from the .NET client to the Java web service to be rejected with an ‘unknown type’ message.

The solution, while admittedly a hack, demonstrations a little discussed features of enumerations. Consider property called Status that is declared as an enumerated type of CallStatus. I added a field called StatusString defined as below and decorated the Status property with a SoapIgnore attribute as follows:

[SoapElement(“Status”)]
public string StatusString
{
   get { return Enum.GetName(typeof(CallStatus), status); }
   set { status = (CallStatus)Enum.Parse(typeof(CallStatus), value); }
}

[SoapIgnore()]
public CallStatus Status
{ … }

The SoapIgnore attribute hides the ‘real’ Status property from the SOAP serialization process. Instead the StatusString property, which is used to convert enumerated values to and from a string, is marked as being the ‘Status’ from the perspective of SOAP serialization. One item that may or may not be a problem is that the assigned value of StatusString could be null. This isn’t considered as part of this example, as the Web service was under a compulsion to return a valid value. But if the field is nilable, then you would need to code for that in the StatusString setter.

 

Automatic Check-Out Not Working with VSTS/TFS

For the last little while I have been having an issue using source control under TFS. Specifically, when I go to edit a file that (I believe) is under source control, I'm allowed to do so. What's worse, when I go to save the file (like when the application is executed or I'm running through TestManager), I'm told that the file is read-only and I'm asked if I want to overwrite it. Even if I overwrite the file, I still have to go to the Source Control Explorer and manually check the file out for editing. This is, as I'm sure many of you would agreed, annoying beyond belief. I could easily go on for paragraphs about how I'm being taken out of the flow and why isn't this happening automatically.

When I first discussed this problem with others, I was told to go to the Tools | Options dialog box. Once there, in the Source Control | Environment section, there is a couple of controls that control what happens to files upon Saving and Editing. It was suggested that setting these to “Check out automatically” would work.

Unfortunately, this wasn't the first. First off, it appears that these settings are the default values. At least, they were on my system. Frustration ensued for another couple of weeks.

Then, for reasons which I'm not sure of, some of the projects in my solution started acting the way they were supposed to. As I started editing a file, a quick “checking out” message appeared. I was confused, to put it mildly. Not to mention intrigued. As I started looking I found that the working projects contained a file with an extension of .vspscc. This is the source control bindings information for the project. After a little more work, I discovered how to create this file through the Visual Studio IDE. From the File menu, select Source Control | Change Source Control. In the dialog box that appears, the non-working projects will not be bound to a TFS server. Assuming that you are already connected to the correct TFS server, select the unbound projects and click on the Bind button at the top of the screen. This will check out the project files and you will (naturally) need to revolve any conflicts and check them back in. As well, you may need to restart Visual Studio to get the automatic check-out to work (I'm 50-50 on having to do this). But most importantly, source control will now work more like you would expect.

How Do I Revert a Changest in Team Foundation Source Control?

This question came up in our VSTS for Developers Training Course in Toronto this week. One of my students wanted to know how to undo or rollback a checkin, something you could do in Visual Source Safe.

Unfortunately this feature was cut for V1 of Team Foundation Server. Buck Hodges and Brian Harry from Microsoft share how this was a painful cut to help get V1 out the door in this forum post. 

Update: James Manning (via the comments) points out that the Team Foundation PowerToy will do this for you. Great tool btw - check it out. Includes the following tools: Unshelve & Merge local changes, Rollback, Online (syncs offline changes to source control), Get Changset, and Undo Unchanged.

Toronto Code Camp Registration Opens

The rumours have been swirling. Now the truth is out.

On Sat. Jan 14, there will be a Toronto Code Camp. You can register/find more infomation/hang out at http://www.torontocodecamp.com/

If you're a developer looking for in-depth content from the people who know (that would be other developers), then the code camp is the place to be. If you're a developer that has in-depth content that other developers could use, this is you're chance to shine. Regardless, it will be a blast. Clear your schedule now to be there.