Tuesday, August 28, 2007 : 3:28 PM
- (0 comments)
I've submitted this issue/bug to Microsoft Connect, but the next version of the framework won't come out for a long time (I'm not talking about 3.5 here). So for those of you who don't already know, here's a tip about the GridView.
The GridView intentionally nulls out the "DataItem" of each row after calling the "OnDataBound" method for that row.
The decompiled code is:
row.DataBind();
this.OnRowDataBound(e);
row.DataItem = null;
This is found at the bottom of the "CreateRow" method on the GridView class. Why did the developer go through the trouble of removing the ability for future developers to access this property in a later event (such as PreRender)? Anyway, you can get around it by storing the DataItems into a dictionary (with the "rowIndex" as the key) and use it later.
this.ResultsGrid.RowCreated += delegate(object sender, GridViewRowEventArgs args)
{
if (args.Row.RowIndex > -1)
{
this.dataSourceLookup.Add(args.Row.RowIndex, ((DataRowView)args.Row.DataItem).Row);
}
};
You can comment about this here, or add feedback to the Microsoft Connect entry here: GridView intentionally nulls "DataItem" after databinding.
Friday, August 24, 2007 : 8:14 AM
- (0 comments)
Typically at my job each of the developers handle about three or four at a time. Because I work in the service industry, we never really "end" a project, but rather we just finish the major development and then continue to "support" our projects from here on out.
Due to the incredibly repetitive nature of our work, we've built a lot of tools that handle most of the work. This makes they typical job only about 20 to 40 hours of work. However, we also get our fair share of bigger clients whose projects demand more time. At that point, an RSD is essential!
I'm currently working on a project that I've scoped to be about 500 hours total architechture / development time, and the last three weeks have been dedicated to understanding and documenting the client's needs. Now that I'm taking my loose notes and compiling them in to a "Phase 1 RSD", I've started to do a few new things that I am finding very helpful.
Write A Story
Some people (including my boss) will argue that you should start off with a Microsoft Word RSD Template, and build your document with a Table of Contents, an Overview section and then move on from there. But I think that there is a better approach for your Phase 1 RSD document.
I'm writing out the spec in a sort of "story" fasion, and so far I'm really liking the way the document quickly teaches and explains the client's needs, and how the system being designed will fill all of those needs.
Don't get me wrong, I'm not talking about a "once upon a time", but rather the document sounds more like: "A manager will recieve his set of assignments that needs to be worked. He will log into the web interface, and choose the 'new assignments' section. Then, after filling out the contractor information..." etc.
Basically, if you memorized my RSD, you could give it as a presentation and people will simply assume that you have a complete grasp of the project.
Vocabulary Definition Links
As I am writing my "RSD Story", I would use terminology that I realize is not commonly known. So right away, I have a "Vocabulary" section at the bottom of my RSD, and every time I write a word (for the first time in the document) that is system or even client specific, I make a vocab entry and link to it in the Word document.
Just in the first two pages alone, I have about 25 links to new terms. This will help you and your client to be on the same page regarding words and terms that they may take for granted. Being on the same wave length with your client is key in agile programming.
Tuesday, August 21, 2007 : 7:50 PM
- (3 comments)
The more I use Visual Studio 2008 (and in particular, the new language features of .NET 3.5), the more I wonder how I ever programmed without it. My current love is the "Language Integrated Query" (LINQ) features that have been introduced in .NET 3.5 (with LINQ to SQL, XML, Entities etc). What I'm talking about right now is just the language itself (as the below example would just be considered LINQ to Objects).
If you're used to using SQL, then you're probably familiar with the "joining" (linking multiple sources together in your "from clause"). You've probably thought before, "this functionality would be great in every day programming, not just in SQL". Here is a quick snippet of C# code that shows how to perform joining using LINQ. This is just straight query expressions here, nothing special.
var result = from article in this.Articles
join author in this.Authors
on article.Author equals author.Name
select new
{
ArticleTitle = article.Title,
ArticleBody = article.Body,
AuthorName = author.Name,
AuthorDateOfBirth = author.DateOfBirth
};
Those two objects (this.Articles and this.Authors) are simply generic lists of a couple of objects I've created. If you'd like to see the whole thing to get more insight on how easy it is to join in LINQ, here's the code:
public class Article
{
public string Title { get; set; }
public string Body { get; set; }
public string Author { get; set; }
}
private class Author
{
public string Name { get; set; }
public DateTime DateOfBirth { get; set; }
}
private List<Article> Articles = new List<Article>();
private List<Author> Authors = new List<Author>();
Monday, August 20, 2007 : 7:17 AM
- (0 comments)
My company has switched from DTS packages to SSIS as a new standard. Since we have literally hundreds of DTS packages, we've decided not to try and port everything over, but instead to slowly "phase out" the old. Since I love the "cutting edge" so much, I was given the task of creating a few SSIS packages for some new client processes. No, I'm not saying that SSIS is really "cutting edge" (as it's been around for a few years now), but in terms of my company, it is.
Encrypted Connection Strings
The point of this post is that I'm very impressed with the way that "secure" information (such as connection strings) are handled in SSIS. At first I didn't understand why my SSIS package would work locally (while designing in "SQL Server Business Intelligence Development Studio" - that's a long name), but it wouldn't work when I've moved it to the extract server.
The SSIS package failed because the connection strings could not be decrypted by the SQL Agent (the default user that runs SSIS packages). As a side note, I didn't even realize that the connection strings were encrypted because whenever I would open the designer, I would see clear text connection strings (of course, because I had permission to decrypt).
When you check the history logs, you'll see a very cryptic error message: "Failed to decrypt protected XML node 'DTS:Password' with error 0x8009000B 'Key not valid for use in specified state.'. You may not be authorized to access this information. This error occurs when there is a cryptographic error. Verify that the correct key is available."
The Solution Is Simple
Again, the reason for this is that the "SQL Agent" user cannot decrypt any secure information (such as the connection string). The solution is to tell SSIS not to encrypt the secure information based on the current user (which is the default behavior), but instead to encrypt the secure settings in the "MSDB" (which does not stand for "Microsoft Database", but rather "Management Studio Database").
To do this, you go to "File -> Save Copy of Package.dtsx As..." and fill out the save dialog to look like this:
The key is the "Rely on server storage and roles for access control" setting. Once you have stored your package on the SSIS server with the above security settings, you can schedule a job and run it under the SQL Agent context and all the connection strings (and any other secure data) will decrypt as normal.
Saturday, August 18, 2007 : 4:25 PM
- (0 comments)
Probably one of the most frustrating things that comes with the territory of being a programmer, is when people find out, and they want you to work on a "dream job" on the side. One such "job" I'm working on right now (for a small busines) is a QuickBooks/Authorize.net integration.
They've recently started selling some of their products through an infomercial. So the Call Center will put the PGP encrypted sales records on their FTP, then I download them, decrypt them, load the customers into QuickBooks (using a nasty XML API), enter the sales reciept, charge the credit card with Authorize.net, print a shipping label (with another nasty API), and then cry... yes, that's the part where I just sit down and cry for a while because all this work isn't worth it :P
Even though I'm going to be paid for my services, it's almost never worth the money. The only thing I really get out of all of this is knowledge (as this is the first QuickBooks integration I've done). Oh, and I also get the knowledge (a reminder really) never to tell anyone that I'm a programmer :)
Friday, August 17, 2007 : 1:16 PM
- (0 comments)
I love when a complex problem is solved with a regular expression... and I probably would not have had any other way to accomplish this need without coming up with a nice regex I call "While Not Between".
Basically, the scenario was this: While writing an article on Eels, I wanted to include an HTML sample containing an "un-ordered list". This is simple enough, but the problem was that the Eels article engine was turning this:
<ul>
<li>Test</li>
</ul>
Into this:
So, after debugging for a few hours and stepping through the article engine's formatting code, I realized that I didn't want to parse a "<ul>" tag while it was between "[code][/code]" blocks. So, I came up with this one regex to rule them all:
(?<!aaa((?!bbb)[\s\S])*)SomeText
This will match the word "SomeText" in this sentense, but it won't match "aaaSomeTextbbb". I've explained it a little better on RegexLib.com.
Friday, August 17, 2007 : 9:26 AM
- (0 comments)
It's been a long time coming, but we've finally put together a (crude) blogging system. It's open to ALL members. Eels blogs use the same parsing engine as our articles do, so you can use the same syntax-highlighting, bulleted lists, numbered lists, images, links, file-downloads, etc.
Using the same "[code][/code]" blocks you can do things like this:
public void DeclareHappiness()
{
this.Response.Write("I am so happy!");
}