Monday, February 28, 2005

How to Test Private and Protected methods

[This was originally posted at http://timstall.dotnetdevelopersjournal.com/how_to_test_private_and_protected_methods.htm]

I published an article on CodeProject How to Test Private and Protected methods.

This article explains some theory behind testing/not testing private methods, and then provides and walks through a downloadable code sample to demonstrate these testing techniques.

Sunday, February 27, 2005

Tips to Handle Config files for Testing and Deployment

[This was originally posted at http://timstall.dotnetdevelopersjournal.com/tips_to_handle_config_files_for_testing_and_deployment.htm]

.Net provides Config files to store configuration values for applications. Each application (an executable or web application) can have its own config file. Two common config files are:

  • Web.Config - used by an ASP.Net or Web Service project.
  • App.Config - used by executables like console apps or Windows Forms.

For example, a standard solution might include a web application (with a web.config) and a Console application to run unit tests (with a App.Config). There are challenges with config files for both testing and deployment:

  • Testing - you may want to localize the config file to the test environment. For example, the app.config may store the database connection string, and you may want to set this connection string to the test database.
  • Deployment - Each environment should have its own config. When you deploy an app to a new environment, you need to also have the correct config deployed too.

This prompts three questions:

  • Should you include the config in the project file?
  • How do you get the latest version of the config?
  • How do you localize the config for a specific environment?

Let's look at each one of these:

Should you include the config in the project file?

Having a file in the physical directory, and having the file listed in the project are two different things. If in Visual Studio, Solution Explorer, you click "Show all files", you'll see all the files in the physical directory that aren't listed in the proj file.

 ProCon
Include
  • Easy to get the latest (just do a Get-Latest from VSS)
  • Can be used by NUnit if you step through your tests in Visual Studio.

 

  • Hard for each developer to have their own individual copy.
Exclude
  • Easier for MSI Installer. If the config file isn't included, then deploying the MSI won't overwrite any existing config. This makes it very easy to redeploy the application without breaking the config.
  • Each developer keeps local copy, doing a get-latest won't overwrite your localized copy because VS.Net's source control features only update files that are part of the project.
  • Config won't be available to NUnit or TestDriven.Net Plug-in (a free plug-in to let you run NUnit in Visual Studio).

How do you get the latest version of the config?

Two ways to get the latest version of a file:

  • Pull from Visual Studio (such as doing a "Get-Latest")
  • Push from VSS.

How do you localize the config for a specific environment?

Perhaps the best way to localize configs for your environment is to have a localized version in another folder, and then have a DOS script that can copy that localized version into the project folder.

Suggestion

Based on these questions, I've found the following parameters to work well.

Config FileInclude/ExcludeWhyHow to get latestLocalize
Web.Config - used for web application.Exclude
  • Best for deployment. Re-running the MSI installer doesn't override the config (because it's not included in the MSI installer).
  • Never run NUnit on Web app directly, so this isn't a problem.
Manually push from VSSNeed to localize it the first time, but then do nothing afterwards because a get-latest won't override it.
App.Config - used for Unit Tests.IncludeNeeded for NUnitAutomatic when getting project within VS.NetRun DOS script to copy in your localized files.

In terms of keeping configs updated, I find the following process helpful:

  1. If a change is made to the config (which should be rare), then all devs will be notified
  2. Regardless of technique (whether include or exclude), a localized copy should still be stored on each dev machine
  3. Each developer is ultimately responsible for updating their local copy.

Wednesday, February 23, 2005

Tips with OOP - New, Virtual, and Abstract

[This was originally posted at http://timstall.dotnetdevelopersjournal.com/tips_with_oop__new_virtual_and_abstract.htm]

As I prepare to teach a C# class, I've being looking at ways to explain and clarify certain Object Oriented Programming (OOP) concepts. I find that while a lot of people are familiar with the terms, the specifics always seem confusing. Two questions I often hear are:

  1. What is the difference between using virtual/override and new?
  2. What is the difference between virtual and abstract?

While there are certainly smarter people then myself who have thoroughly explained every inch of OOP, I'll give it my two cents anyway. (For those interested in other resources, I personally like Deitel and Microsoft's C# Spec).

What is the difference between using virtual and new?

The Virtual keyword (used in the base class) lets a method be overridden (by using override in the derived class) such that if you declare an object of a base type, and instantiate it of a derived type, then calling the virtual method will call the derived type's method, not the base type. This is polymorphism.

The new keyword (used in the derived class) lets you hide the implementation of a base method such that when you declare and instantiate an object of the same type, the method of that type is called. There is no polymorphism here.

I think the best way to explain this is via a code sample that shows the different effects of using virtual vs. new. Say you have the following two classes:

    public class MyBase
    {
        public virtual string MyVirtualMethod()
        {
            return "Base";
        }

        public string MyNonVirtualMethod()
        {
            return "Base";
        }
    } //end of sub class

    public class MyDerived : MyBase
    {
        public override string MyVirtualMethod()
        {
            return "Derived";
        }

        public new string MyNonVirtualMethod()
        {
            return "Derived";
        }
    } //end of sub class

This has two classes, MyBase and MyDerived. For illustration, the classes each only have two methods. For comparison, MyBase has one method virtual, and one not. Likewise, MyDerived overrides the virtual method and hides the non-virtual. The following code snippet shows three separate cases. Note that the virtual-new keywords affect the value of MyNonVirtualMethod based on whether the object is declared as type MyBase or MyDerived.

MyBase m1 = new MyDerived();
Console.WriteLine("MyVirtualMethod='" + m1.MyVirtualMethod() + "', MyNonVirtualMethod='" + m1.MyNonVirtualMethod() + "'");
//    Returns: MyVirtualMethod='Derived', MyNonVirtualMethod='Base'

MyDerived md = new MyDerived();
Console.WriteLine("MyVirtualMethod='" + md.MyVirtualMethod() + "', MyNonVirtualMethod='" + md.MyNonVirtualMethod() + "'");
//    Returns: MyVirtualMethod='Derived', MyNonVirtualMethod='Derived'

Note that in the first case, where we declare the object of type MyBase yet instantiate it to type MyDerived, calling MyNonVirtual method is called on the declared type. In the second case, it is called on the Instantiated type.

These concepts are very common when declaring an array of base objects, and then cycling through the array and calling virtual members. A classic example is making an array of Shape objects, calling the GetArea() method on each one, and it correctly returning the area for that shape.

What is the difference between virtual and abstract?

These two keywords are sometimes confused because both can be over-ridden. However, unlike Virtual members, Abstract members have no implementation. As Deitel puts it, "Abstract base classes are too generic to define real world objects" (C# How to Program, pg 392). The Abstract keyword can be applied to either members or the class as a whole. Note that if a class has an abstract member, then that class must itself be abstract (There is no such thing as a "virtual" class).

In the following code snippet below (from Deitel, pg. 394), the abstract class shape has two virtual methods: Area and Double, and one abstract property Name. Note that both virtual members have a concrete implementation. If you create a derived class "Point", and call its Area method, it will return 0.

public abstract class Shape
{
    public virtual double Area()
    {
        return 0;
    }

    public virtual double Volume()
    {
        return 0;
    }

    public abstract string Name
    {
        get;
    }
}

The following table highlights these differences:

 VirtualAbstract
Has implementationYesNo
Scopemembers onlymembers and classes
Can create an instance ofNot Applicable (you can only create instances of classes, not members)No - but you can create an instance of a class that derives from an abstract class. And you can declare a type Abstract class and instantiate that as a derived class.

Common Abstract classes in the .Net framework include System.Xml.XmlNode and System.IO.Stream. Perhaps the most common virtual method is System.Object.ToString().

Tuesday, February 22, 2005

Using HttpUtility.UrlEncode to Encode your QueryStrings

[This was originally posted at http://timstall.dotnetdevelopersjournal.com/using_httputilityurlencode_to_encode_your_querystrings.htm]

Perhaps the most popular way to pass data between web-pages is via querystrings. This is used to both pass data to a new pop-up window, as well as to navigate between pages. (Side note: A querystring is the part of the URL that occurs after the ?. So in http://localhost/myWeb?id=3&name=Tim, id=3&name=Tim is the querystring. The querystring provides name-value pairs in the form of ?name1=value1&name2=value2...)

While this works great for simple alpha-numerics, it can be a problem to pass special characters in the URL, especially in different browsers.

  • An ampersand would split the name-value pairs. (If you want to pass the value "A&B", but the & indicates a new name-value pair, then the value will be truncated to just "A". For example, in "id=A&B", getting the querystring "id" will return just "A", and B will be interpreted as its own key.
  • Apostrophes, greater than or less than signs may be interpreted as a cross-site scripting attack by some security plug-ins. As a result, these plug-ins may block the entire page.
  • Other special characters (like slash or space) may be lost or distorted when sending them into a url.

While some may argue that querystring values should only contain simple IDs, there are legitimate benefits to being able to pass special characters. For example:

  • Legacy Systems - The client's legacy system could include & or ' in the primary key.
  • Performance - You could be returning a value (such as a name like "O'reilly" or "Johnson & Sons") from a pop-up control. Just passing the id would require re-hitting the database. Therefore you could pass the name as well to help performance.

Fortunately there is a solution to handling special characters. .Net provides us the ability to Encode and Decode the URL using System.Web.HttpUtility.UrlEncode and HttpUtility.UrlDecode (note this is not HtmlEncode, which encodes html, and won't affect the &. We want Urls). This replaces problematic characters with URL-friendly equivalents.

The following table shows what UrlEncode translates:

ASCII Codes

CharacterUrlEncode
DecHex
3220 +
3421"%22
3522#%23
3624$%24
3725%%25
3826&%26
432B+%2b
442C,%2c
472F/%2f
583A:%3a
593B;%3b
603C<%3c
613D=%3d
623E>%3e
633F?%3f
6440@%40
915B[%5b
925C\%5c
935D]%5d
945E^%5e
9660`%60
1237B{%7b
1247C|%7c
1257D}%7d
1267E~%7e

While alpha-numerics aren't affected, these special characters aren't encoded either:

ASCII Codes

Character
DecHex
955F_
452D-
462E.
3927'
4028(
4129)
422A*
3321!

Side note 1: You can see the full ASCII tables online.

Side note: You can generate these tables with a simple loop like so:

for (int i = 0; i< 128; i++)
{
    string s = ((char)i).ToString();
    Console.WriteLine(i.ToString() + " Char: [" + s + "], UrlEncode: [" + System.Web.HttpUtility.UrlEncode(s) + "]");
}

Essentially UrlEncode replaces many problematic characters with "%" + their ASCII Hex equivalents.

Most of these remaining special characters don't pose a problem, except for the apostrophe that can cause cross-site scripting warnings. For that, one solution is to replace it with a unique token value, such as "%27". Note that we pick a reasonable token - "27" is the ASCII Hex for the apostrophe, and it follows the pattern of other Encodings. We could then write our own Encode and Decode methods that first apply the UrlEncode, and then replace the apostrophe with the token value. These methods could be abstracted to their own utility class:

public static string UrlFullEncode(string strUrl)
{
    if (strUrl == null)
        return "";
    strUrl = System.Web.HttpUtility.UrlEncode(strUrl);
    return strUrl.Replace("'",_strApostropheEncoding);
}
private const string _strApostropheEncoding = "%27";

public static string UrlFullDecode(string strUrl)
{
    if (strUrl == null)
        return "";
    strUrl = strUrl.Replace(_strApostropheEncoding,"'");
    return System.Web.HttpUtility.UrlDecode(strUrl);
}
 

 

Monday, February 21, 2005

Making a MessageBox in JavaScript

[This was originally posted at http://timstall.dotnetdevelopersjournal.com/making_a_messagebox_in_javascript.htm]

This is classic - I lose track of how often I see people asking the practical question "How do I create a MessageBox in ASP.Net?" The basic problem is that MessageBoxes occur at the client-side, whereas ASP.Net runs on the server. Therefore you need to have ASP.Net call client-side script, like JavaScript, in order to create the MessageBox.

I had the opportunity to explain this in detail on an article at 4guysfromrolla, at:  http://aspnet.4guysfromrolla.com/articles/021104-1.aspx. Although that article was a year ago, I still get regular emails about parts of it. Most people wanted to know how to have a button give a Yes/No prompt, and then trigger the appropriate server event. Eventually to simplify it I wrote a custom-server control and uploaded it to the control gallery on www.asp.net, at: http://www.asp.net/ControlGallery/ControlDetail.aspx?Control=2071&tabindex=2. It's a free control, with a link to a demo.

[Update]: I posted the source code for this control:

The gist of it is you:

  1. Have ASP.Net create the JavaScript confirm or prompt using either Me.BtnDelete.Attributes.Add(...) or Page.RegisterStartupScript
  2. Put a runat=server hidden html control on the WebForm.
  3. Clicking a button on the JavaScript messagebox runs a client-side script that (1) sets the hidden control's value property and then (2) submits the form (to return flow to the server).
  4. The ASP.Net classes can access the hidden control's value property at the server.

Essentially, you go from Server to Client by registering the script, you go from client to server by submitting the form, and you make data accessible to both by storing it in a runat=server hidden control.

Sunday, February 20, 2005

Using System.Diagnostics to run external processes

[This was originally posted at http://timstall.dotnetdevelopersjournal.com/using_systemdiagnostics_to_run_external_processes.htm]

Sometimes you'll want to run an external program, like bat, exe, or vbs. I find this especially useful for testing and deployment - I'll want to reset IIS or run a VBScript that initializes the environment, or call osql (the command line for SQL Server) to run a database script. Fortunately .Net provides a great way to do this using the System.Diagnostics namespace.

The simplest approach is a static utility method that can take the filename and command line arguments ike so:

System.Diagnostics.Process.Start("Simple.bat", "arg1 arg2");

This opens up a console window and runs the command. While it works for simple things, such as resetting IIS, there's two additional useful features we may want to do, especially for quick-running processes: (1) Run the process in a hidden window, (2) Wait for the process to exit. We can do both of these with code like the following:

public static void RunHiddenConsole(string strFileName, string strArguments, bool blnWaitForExit) {    //run in process without showing dialog window:    ProcessStartInfo psi = new ProcessStartInfo();    //psi.CreateNoWindow = true;    psi.WindowStyle = ProcessWindowStyle.Hidden;    psi.FileName = strFileName;    psi.Arguments = strArguments;    Process p = System.Diagnostics.Process.Start(psi);    if (blnWaitForExit)        p.WaitForExit();} //end of method

To run the process in a hidden window, we create a ProcessStartInfo object and specify its window style to be Hidden. We can then pass this ProcessStartInfo into the Process.Start method. To wait for the exit, we create a process object from the Process.Start method, and use its WaitForExit method.

Note that this is very context-independent functionality, and is therefore great to put into your own utilities class that you can reuse from project to project.

Thursday, February 17, 2005

Validating external dependencies

[This was originally posted at http://timstall.dotnetdevelopersjournal.com/validating_external_dependencies.htm]

In any project, there are always external dependencies that your components depend on. Perhaps two of the most common are database tables that you can only read from, and someone else's machine that you need to deploy to. I've found some tips for handling each of these cases.

Verifying that your data works for external datatables

Say that there are datatables that you use, but they are maintained by another department. For example, you may need to use an external table as lookup values in your own records, but someone may change the source table after you've already gotten the value from it. Even worse, those tables might not have any referential integrity on them. Although your component may work perfectly with all your unit-test data, it's very possible that their data could be invalid. Given that you don't have the resources to also test every way that their data could be invalid, it would be nice to run a quick diagnostic check.

One solution is to create a stored procedure to do this. You could check that lookup values still exist in the source table or that certain char/varchar fields don't contain invalid characters. A simple such SP with two rules might be:

Begin
    if not exists(select myCode from TblCode where myCode is not null)
        Print 'Error: TblCode has a null myCode.'

    if exists (select * from TblLocation where [description] like '%&%')
        Print 'Error: Location can not contain a & '
End

Verifying someone's else environment is set up correctly.

It seems like every developer I meet, including myself, has the problem of writing code that works on our environment, but fails elsewhere. While sometimes it's a legitimate bug in the code, sometimes it's also a error in the other person's environment. For example, the other machine might be missing the correct prerequisite software or have a bad configuration file. I especially see this problem with Unit Tests because all the developers want to always be able to run all the unit tests on their machine. This means that your code will frequently be run on another's machine.

A solution I've found useful is for the team or testing lead to write a small set of diagnostic tests to check that the environment is set up correctly. These diagnostic tests could include:

  • Write "Hello World" to the command line to ensure that test engine is installed correctly
  • Access external data stores (such as the database or file system) to ensure that the system is configured correctly.

This way I find that if someone says the tests are failing, I can quickly diagnose if they have an easily-fixable environmental problem like bad config files.