simple random alpha char string variable in C#

Just a quick little code sample which creates a variable which generates a random alpha character string (upper and lower case). This can be very useful when you need to randomise a name, or create one or more temporary directories or files on the fly.

private const int _length = 15;
private static string RandomAlphaString {
	get {
		var ret = "";
		var random = new Random();
		while (ret.Length < _length)
			if (random.Next(1, 9) % 2 == 0)
				ret = ret + Convert.ToChar(random.Next(65, 90));
			else
				ret = ret + Convert.ToChar(random.Next(97, 122));
		return ret;
	}
}

Usage is to declare a var within your code, such as var randomName = RandomAlphaString; and this will be createda a string of length _length randomly using upper and lower case alpha characters (letters).

use CAB files in C# and .NET

An often overlooked element of working in C# and .NET is the ability to work with CAB files. These are very useful compressed files, which can help you immensely when you are deploying applications and need to move a large volume of files. They are EXTREMELY simple to use. Firstly, make sure you reference the library in your project (Microsoft.Deployment.Compression.Cab) and then you can easily use them in on a couple of lines. My example is actually overly verbose in the number of lines it uses in order to maintain clarity.

 
//Create cab files 
var pathToContainingFolder = @"C:\Desktop";
var cabFile = Path.Combine(pathToContainingFolder, + @"cabinet.cab");
var cabToPack = new CabInfo(cabFile);
var sourceDir = @"C:\Desktop\stuff";
cabToPack.Pack(sourceDir, true, Microsoft.Deployment.Compression.CompressionLevel.Min, null);

And there we have a compressed CAB file ready to use.

On the other end, extraction is equally straight-forward:

// extract the CAB file to the specified directory
var destDir = @"C:\Desktop\cabDemo";
EnsureDirectoryExists(destDir);
var cabToUnpack = new CabInfo(cabFile);
cabToUnpack.Unpack(destDir);

the above sample uses my little helper EnsureDirectoryExists(string dir):

private static void EnsureDirectoryExists(string dir) {	
	if (!Directory.Exists(dir)) {
		Directory.CreateDirectory(dir);
	}
}

copying or deleting everything in a directory (C#)

In C# we have the ability to move Directories or Files using System.IO.File.Move(sourceFile, destFile) and System.IO.Directory.Move(sourceDirPath, destDirPath) (making sure your paths use the string literal, ie var sourceDirPath = @"C:\Users\Public\public\test\"), however sadly there is no way to easily copy or delete entire directories (there is no Directory.Copy(fromDir, toDir) method available to us, only File.Copy(fromFile, toFile); and Directory.Delete(dir) only works for empty directories, so we need to empty them recursively!!). I have pulled together two methods to do this recursively.

The first is CopyAllDirectoriesAndFiles(string fromDirectory, string toDirectory), and also uses another method EnsureDirectoryExists(string dir):

private static void CopyAllDirectoriesAndFiles(string fromDirectory, string toDirectory) {
	if (Directory.Exists(fromDirectory)) {
		string[] files = Directory.GetFiles(fromDirectory);
		// make sure it exists
		EnsureDirectoryExists(toDirectory);
		// Copy the files and overwrite destination files if they already exist.
		foreach (string file in files) {
			var fileName = Path.GetFileName(file);
			var destFile = Path.Combine(toDirectory, fileName);
			File.Copy(file, destFile, true);
		}
		var di = new DirectoryInfo(fromDirectory);
		DirectoryInfo[] subDirs = di.GetDirectories();
		foreach (DirectoryInfo dirInfo in subDirs) {
			var directoryName = dirInfo.Name;
			var fromPath = Path.Combine(fromDirectory, directoryName);
			var toPath = Path.Combine(toDirectory, directoryName);
			EnsureDirectoryExists(toPath);
			// copy all files and folders across recursively
			CopyAllDirectoriesAndFiles(fromPath, toPath);
		}
	}
}

private static void EnsureDirectoryExists(string dir) {	
	if (!Directory.Exists(dir)) {
		Directory.CreateDirectory(dir);
	}
}

The second is DeleteAllDirectoriesAndFiles(string topDirectory):

private static void DeleteAllDirectoriesAndFiles(string topDirectory) {
	if (Directory.Exists(topDirectory)) {
		string[] files = Directory.GetFiles(topDirectory);
		foreach (string file in files) {
			File.Delete(file);
		}
		var di = new DirectoryInfo(topDirectory);
		DirectoryInfo[] subDirs = di.GetDirectories();
		foreach (DirectoryInfo dirInfo in subDirs) {
			var directoryName = dirInfo.Name;
			var fromPath = Path.Combine(topDirectory, directoryName);
			// delete all files and folders recursively
			DeleteAllDirectoriesAndFiles(fromPath);
		}
		// delete this folder
		Directory.Delete(topDirectory);
	}
}

Hopefully the inline comments are self-explanatory, if not, hit me up in the comments and I’ll provide you with more detail.

ensuring a Directory exists in C#

Often we need to ensure a Directory exists before we reference or use it. This is a little method that does this for you. Nothing complicated, but if you need to check that 2 or more directories exist, this will save you lines of code:

private static void EnsureDirectoryExists(string dir) {	
	if (!Directory.Exists(dir)) {
		Directory.CreateDirectory(dir);
	}
}

asp:DeclarativeCatalogPart WebPartsTemplate must have odd number of elements

I discovered an interesting anomaly today, working with ASP.NET and Web Parts, I had an issue whereby creating a CatalogZone caused the HTML generated from template to lose a whole lot of closing tags. This threw the whole page out the window as the CSS was stuffed. I did a LOT of Googling to no avail.

Finally I went into the tried and true method of trial and error; removing one element at a time until I found the problem bit. This was also anomalous as I have three pages with essentially the same code and only one breaks! I won’t bore you by going through every iteration and step I took, I’ll just bounce to the solution.

In their wisdom Microsoft has apparently made the template work for an odd number of elements, but an even number has a tantrum and is not composed correctly. It was only when I realised that that during my trial and error, the two working pages had 15 and 5 elements respectively, and the “broken” page had 6 elements; thinking this could not possibly be the issue, I checked and was astounded. The general response from my colleagues was “you’ve got to be f@$#en kidding me”. I swear, I’m not.

In summary, from an HTML point of view, this works:

<asp:CatalogZone ID="CatalogZone" runat="server">
	<ZoneTemplate>
		<asp:DeclarativeCatalogPart ID="DeclarativeCatalogPart" runat="server">
			<WebPartsTemplate>
				<tfr:stuff1 ID="stuff1" runat="server" />
				<tfr:stuff2 ID="stuff2" runat="server" />
				<tfr:stuff3 ID="stuff3" runat="server" />
			</WebPartsTemplate>
		</asp:DeclarativeCatalogPart>
		<asp:PageCatalogPart ID="PageCatalogPart" runat="server" />
	</ZoneTemplate>
</asp:CatalogZone>

and this doesn’t:

<asp:CatalogZone ID="CatalogZone" runat="server">
	<ZoneTemplate>
		<asp:DeclarativeCatalogPart ID="DeclarativeCatalogPart" runat="server">
			<WebPartsTemplate>
				<tfr:stuff1 ID="stuff1" runat="server" />
				<tfr:stuff2 ID="stuff2" runat="server" />
			</WebPartsTemplate>
		</asp:DeclarativeCatalogPart>
		<asp:PageCatalogPart ID="PageCatalogPart" runat="server" />
	</ZoneTemplate>
</asp:CatalogZone>

How to use a C# for loop

The for loop in C# is useful for iterating over arrays and for sequential processing. That is the statements within the code block of a for loop will execute a series of statements as long as a specific condition remains true. E.g.:

for(initialization; condition; increment) {
	statement/s
}

initialization :   Initialize the value of variable
condition :            Evaluate the condition based on the variable
increment :            Step taken for each execution of loop body

The for loop initializes the value before the first step. Then checks the condition against the current value of the variable and executes the statement/s inside the loop before incrementing.

int count = 4;
for(int i = 0; i < count; i++) {
	MessageBox.Show("The first number is: " + i);
}

This outputs:

The first number is: 0
The first number is: 1
The first number is: 2
The first number is: 3

The loop executes four times because we set the condition as being i is less than count, and i was initially 0.

All expressions in a for loop declaration are optional. The following creates an infinite loop:

for( ; ; ) {
	statement/s
}

in much the same way as simply using while(true) creates an infinite loop, e.g.:

while(true) {
	statement/s
}

Happy looping!

today’s update

I checked in my first bug fix today! Slight sense of accomplishment when that happened. I’ve actually contributed something to the team. It wasn’t the most complicated of bug fixes, but it needed to be done and I got it sorted quickly and cleanly. Along the way I gained a lot of insight into the structure of the software and how it hangs. That said, I still know pretty much nothing about about the package (guys who have been here 11+ years still don’t know it themselves).

The main thing I think, was that I was able to show that I could understand the problem, then dive into some unknown code, find the “hub” and design and implement an efficient, effective solution without supervision. And, my coding practices seem to be in line with the other developers, which is definitely a good thing. After that I got to jump into a fix/update for our web client. This turned out to be extremely simple, and where I thought to go for “more aesthetic and dynamic” responses to user input I didn’t need to. So, by lunchtime I had committed my first two bits of code to the repository.

This afternoon I spent in the web client again, delving into greater depths. Most of what I was hitting up against was involving interactions between C# and JavaScript. I found a fantastic post explaining how to share dynamic variables between the two here, although I didn’t end up implementing as it was overkill for the requirements and we’ve established a more practical and elegant solution to that hurdle.

Off for my evening constitutional now, so more updating tomorrow.