Blogroll

Disclaimer

The opinions expressed herein are my own personal opinions and do not represent my employer's view in anyway.

Add contents of a stream to a Zip file

In a recent project I needed to create a Zip file containing a number of files and a summary of the contents. Thanks to the .NET 4.5 ZipArcive class, this was relatively straigh forward.

One hurdle that needed to be overcome was adding the a text file to the Zip that contained a list of the files that had been Zipped along with some other information about each record. I started by creating a StreamWriter, using a MemoryStream as I didn't actually want to save the file to disk.

Lines containiing the file details would be written to the StreamWriter as each record was processed, then at the end of the process, the MemoryStream would be saved to the ZipArchive.

Adding multiple parameters to JSON-enabled WCF service

One thing you’ll be tempted to do when you first start creating web services is to add multiple parameters to your web methods. Don’t, it will soon trip you up, especially if any of those parameters are complex types.

A better way to handle calling WCF web services that return JSON formatted results is to use Request and Response objects. Your WCF service accepts a single complex Request object that contains all the values it needs to perform its job. The results, along with any exceptions and messages are passed back to the caller in the Response object.

In this post, we’ll modify our GetPlaces method to use Request and Response objects instead of querystring parameters.

You’ll notice that we’ve changed the WebGet tag to WebInvoke. This declaration enables us to use the HTTP POST verb, instead of GET, since the calling function will be sending a complex object in the request body, not just a parameter in the URL.

To test this web service you’ll need to create a POST HTTP request. The easiest way to do this is use a tool such as Fiddler to create the request.

Add Content-Type:application/json to the request header and specify the body as such:

{"Request":{"Country":"USA", "MaxPopulation":"4000000"}}

You’ll notice the values for Country and MaxPopulation are enclosed in an object called Request. This is because the web method parameter is called Request.

If everything goes well, Fiddler will report a response that includes the following JSON.

Filtering XML data in a DataSet

In the post Read XML File into DataSet we demonstrated how to read every row of data from an XML document by using the ReadXml method. While reading every row of data may be suitable for a smalll set of data, there are few times when you will actually want to return every record from the XML document. There are a number of ways to filter data from an XML document, such as using XQuery which filters the data at the XML Document level. In this example however we will conduct the filtering at the DataSet level, once it has been populated from the XML Document.

To filter out only the records we want from the DataSet, we will use the DataTable.Select method, as outlined below.

//declare and load the DataSet from the XML document

DataSet ds = newDataSet();

ds.ReadXml("AppSettings.xml");

//only select the rows where the name is CurrentInstance

DataRow[] rows = ds.Tables[0].Select("name='CurrentInstance'");

//Loop thru the rows to access each row that matches

foreach (DataRow row in rows)

{

//TODO: do something with each row

}

As you can see the DataTable.Select method returns an array of DataRow objects. We are using the constructor that takes a filterExpression as an argument. In this example we are using a simple equality filterExpression - return all records where name is equal to CurrentInstance. Depending on the datatype of the columns in your DataTable you could create a valid expression using any common operators such as Like, > (greater than), < (less than) and even join multiple exressions together using AND/OR.

C# Getting Information about your Folders

Continuing on our journey converting old VBA code to C#, in this post we’ll revisit getting information about the folders/directories on a system. In .NET parlance, folders on the file system are directories, so from here on in, that’s what we’ll call them.

Copy the following code into the Main method. This code will iterate through the directories under C-drive and print the directory name in the console. NOTE: any slashes '\' in the directory path need to be escaped - for exampl, we have C:\\, not C:\.

Code Snippet

// set the root or starting directory

DirectoryInfo dir = newDirectoryInfo("C:\\");

// get all the children under the root

DirectoryInfo[] children = dir.GetDirectories();

foreach (DirectoryInfo d in children)

{

Console.WriteLine(d.Name);

}

In the code above we set the starting directory to the C-drive root, but it is important to know that you can set the starting directory to any valid directory on the system, not just drives.

It is possible to continue down the system hierarchy and return the children of each of directory by calling the GetDirectories method on each. Writing a function that recursively calls GetDirectories for each subsequent DirectoryInfo object would effectively traverse the entire directory structure.

C# Getting Information about your Drives

Many moons ago I wrote a series of posts on how to access the file system from your Access database using Scripting.FileSystemObject in VBA. Just for fun and partly as a learning experience, I thought it was time to look at how the same can be achieved in .NET and more specifically C#.

To get started, open Visual Studio 2010 and create a new Console Application. In the Program.cs file add a using statement for the System.IO namespace, which contains all of the methods you’ll need to access drives, directories and files.

Code Snippet

using System.IO;

Now insert the following code in the Main method. This code will get an array of DriveInfo objects, which contain the basic information of all the drives available on your system.

Code Snippet

// get a list of drives available on the system

DriveInfo[] drives = DriveInfo.GetDrives();

foreach (DriveInfo drive in drives)

{

Console.WriteLine(drive.Name);

}

Some interesting properties of the DriveInfo object are Name, AvailableFreeSpace and DriveForm (FAT/NTFC).

Reading XML files with child elements

In the previous post we looked at how to create a DataSet by reading from a simple XML file. In this port we will investigate how .NET handles more complex XML files and in particular how the .NET DataSet handles XML files containing multiple child elements under the root.

<?xmlversion="1.0"encoding="utf-8" ?>

<AppSettings>

<settingname="CurrentInstance"serializeAs="String">

<value>1</value>

<currentStatus>

<status>live</status>

<lastUpdated>01-01-2010</lastUpdated>

</currentStatus>

</setting>

<settingname="OutputDirectory"serializeAs="String">

<value>\\SV-OCRMGR\mbrc\ocr\xmloutput</value>

<currentStatus>

<status>live</status>

<lastUpdated>01-01-2010</lastUpdated>

</currentStatus>

</setting>

</AppSettings>

As we found in the previous post, when .NET parses the XML into the DataSet it creates a DataTable for the root element, in thise case the table is called AppSettings. With the more complex XML shown above, simple elements, like value are parsed into a column of the AppSettings table. Elements that contain child elements themselves, such as currentStatus are parsed into a new DataTable within the DataSet. .NET also creates a relationship, similar to a foreign key relationship you may be familiar with from database development.

We can modify the code from the previous post to take advantage of this functionality.

The output from this file (show below) shows that we have returned the status element for each row in the setting table:

CurrentInstance 1 live OutputDirectory \\SV-OCRMGR\mbrc\ocr\xmloutput live

What isn't clear is how all this works. To illustrate this better, we can write some code to reveal the relationship .NET created between our original setting table and the child element currentStatus.

.NET has created a DataRelation called setting_currentStatus which links the setting table to the currentStatus table in a field called setting_Id. You'll notice the XML file does not have a field called setting_Id, .NET created that when it parsed the file into the DataSet. In our earlier code we took advantage of this relationship by calling the GetChildRows method on each DataRow in setting. GetChildRows takes as its parameter a DataRelation object, which tells .NET everything it needs to know to grab the related child rows.

As we only had one complex child element in our XML, we were able to use the define the correct DataRelation by simply pointing to the first DataRelation in the collection using the code dr = ds.Relations[0]. Obvisously, when our XML has more than one complex child element, we need a way to determine the DataRelation we want to use. Lets modofy the XML file again and add a new element called currentScope.

<?xmlversion="1.0"encoding="utf-8" ?>

<AppSettings>

<settingname="CurrentInstance"serializeAs="String">

<value>1</value>

<currentStatus>

<status>live</status>

<lastUpdated>01-01-2010</lastUpdated>

</currentStatus>

<currentScope>

<scope>user</scope>

<lastUpdated>01-01-2010</lastUpdated>

</currentScope>

</setting>

<settingname="OutputDirectory"serializeAs="String">

<value>\\SV-OCRMGR\mbrc\ocr\xmloutput</value>

<currentStatus>

<status>live</status>

<lastUpdated>01-01-2010</lastUpdated>

</currentStatus>

<currentScope>

<scope>application</scope>

<lastUpdated>01-01-2010</lastUpdated>

</currentScope>

</setting>

</AppSettings>

We have a couple of options when defining the DataRelation, one is to use the index as we did previously, which will return the related children in the order they appear in the XML. The second is to use the name of the DataRelation, which as we saw earlier is created by combining the names of the parent and child tables. Either way, we need to know the structure of the XML file and be confident that it is not going to change too dramatically. Lets modify the code to use the DataRelation name to retrieve the child rows from the newly added currentScope element.

Connecting to the SQL Server database

Performing operations on data stored in a database is one of the most common tasks performed by developers. In fact, most modern web and desktop applications rely on data stored in databases at least to some degree. In the .NET world, SQL Server and especially SQL Server Express is almost the defacto standard database management system and even the free Express versions of the popular Visual Studio development tools support SQL Server database straight out of the box.

Of course you can use other database types, such as Access and Oracle, by simply using the libraries that are available for each specific database. Microsoft provide the System.Data.OleDB, which can be used for Access databases and third party libraries, such as the Oracle Data Provider for .NET (ODP.NET) are also available for a number of .NET framework versions.

//when using a data reader you must explicitly open and close the connection

conn.Open();

SqlDataReader dr = cmd.ExecuteReader();

conn.Close();

NOTE: Most experts recommend avoiding dynamically created SQL statements, as these can cause performance issues and represents a potential security threat. Use stored procedures unless there is no other choice (and yes there is always a choice).

while

do

Similar to a while loop, the do loop executes a code block while an expression remains true. Unlike a while loop, a do loop checks the condition after running the code. This means that a do loop will always run at least once.

for

The for loop runs a block of code until an expression is false. It is useful when you know the number of times to iterate through the code, such as when iterating through an array.

The basic syntax is as follows:

for (initializer; condition; iterator)

initializer: the initial condition

condition: a Boolean expression to evaluate

iterator: defines what to do after each iteration

In the example below, we first create a string array and then iterate through the array. A couple of things to note, arrays are zero-based, so your initializer i needs to be set to 0. The maximum value to compare against in the condition will be the length of the array, minus 1. After each iteration we’ll increase i by one. This will enable us to iterate through every value in the array.

Conditional Blocks

Conditional blocks or selection statements provide a mechanism for choosing between alternate blocks of code.

if-then

The most common of the selection statements is the if-then statement that runs different blocks of code depending on the results of a condition. Conditions can be any expression that returns a Boolean, such as comparing two numbers.

When the condition evaluates to true, the ‘then’ portion of the statement runs. Unlike VB, in C# you don’t need to explicitly use the Then keyword, anything directly after the condition (usually in the curly braces) is the then statement. I said usually in the curly braces, because if your then block consists of only one line of code, you can omit the braces.

// omit the curly braces {} for single lines of codeif(myVariable1 > 0)
Console.WriteLine("Bigger than zero");

The condition can include more than one comparison using logical operators, such as && (and) or || (or)

switch

The switch statement runs one of the number of code blocks based on the value of the switch expression. Each code block begins with a case keyword and a value to compare against the switch expression. If the case and switch expression match, the code in that section runs. Instead of each block of code being delineated by curly braces, a jump statement (usually break) is used to exit the switch.

// compare the value of myVariable1 against 3 different case // the last is the catch-all or default that runs if neither// of the previous sections offer a matchswitch (myVariable1)
{
case 0:
Console.WriteLine("Equal to zero");
break;
case 1:
Console.WriteLine("Equal to one");
break;
default:
Console.WriteLine("Some other number");
break;
}