Unintelligible

Sunday, July 27, 2008

WSE 2.0 in Visual Studio 2008

A slightly older .Net 2 application I wrote for a client to upload files to Amazon S3 makes use of the Amazon S3 SOAP API. The SOAP API has the advantage over the REST API of being able to stream large files as DIME attachements when uploading to the S3 servers, rather than trying to load them up in one go, which is handy when uploading large files. The S3 WS API requires Microsoft’s Web Services Enhancements (WSE) 2.0 though, rather than the later WSE 3.0, because in WSE 3.0 DIME is replaced by MTOM (which Amazon doesn’t support - in typical WS-* way).

However, when I tried to install this, I got the following error:

Unknown error in CorBindToRuntimeHost

Error 1001.InstallUtilLib.dll: Unknown error in CorBindToRuntimeHost

The workaround (a reminder to myself) is to use the WSE 2.0 SP3 installer rather than the older versions that come up when searching for WSE 2.0 on google.

posted by Nick at 6:24 pm - filed in .net, windows  

Friday, July 20, 2007

Strongly-named assemblies and InternalsVisibleTo

One of the projects I work on wasn’t using strongly-named assemblies, so we decided to sign them (mainly to prevent version conflicts on sales laptops). However, after generating the key-pair and setting up the different assemblies to use it, building the solution gave this error:

Friend assembly reference ‘Company.Product.UnitTests’ is invalid. Strong-name signed assemblies must specify a public key token in their InternalsVisibleTo declarations.

The problem was that some of the assemblies were making their internals visible to the UnitTests assembly (making them accessible so that they could be tested), but when these assemblies are strongly names, the public key token must also be included in the InternalsVisibleTo declaration in Assembly.cs.

This introduces a chicken-and-egg scenario; the A assembly makes its internals visible to the UnitTests assembly, but must know the UnitTests assembly public key in order to build. The UnitTests assembly depends on assembly A to build, but assembly A can’t be built until we know what the public key token for UnitTests is, which in turn can’t build because it depends on assembly A…

After looking into a couple of solutions, the one that worked for me was:

  1. Sign all assemblies with the key-pair
  2. Generate the public key for the key-pair as such (from the Visual Studio command prompt):

    sn -p path\to\keypair.snk path\to\keypair.pub

  3. Get the public key token for the public key as such (still from the Visual Studio command prompt):

    sn -tp path\to\keypair.pub

    This will output a long (256 characters) public key; copy this to the clipboard

  4. Declare the InternalsVisibleTo attribute in Assembly.cs as such:

    [assembly: InternalsVisibleTo("Company.Product.UnitTests, PublicKey=<your public key>")]

    where <your public key> is replaced by the public key output in (3)

  5. Build the solution. The solution should now build as expected.

This assumes that all assemblies use the same key-pair - suggestions to use the public key token (using PublicKeyToken=... rather than PublicKey=...) didn’t work for me.

posted by Nick at 5:58 pm - filed in .net  

Tuesday, May 8, 2007

Problem Installing .Net Framework 3.0

The .Net Framework 3.0 refused to install on my machine this morning - a quick look through the installation logs (particularly C:\DOCUME~1\<your user name>\LOCALS~1\Temp\VSW1\VSSWMSIFailInfo.txt) revealed the following:

Error 1402.Could not open key:
HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/Services/Eventlog/Security/ServiceModel 3.0.0.0.
System error 5. Verify that you have sufficient access to that key,
or contact your support personnel.

I am a local admin on my machine, so this surprised me a little. The permissions on this key were set to grant Full Control to the ASP.NET user. I granted myself Full Control, but this didn’t seem to help. Granting Everyone Full Control seemed to resolve the issue - other keys in the subtree grant Full Control to the local Administrator group and the System user, so I revoked permissions from Everyone and granted these access to the key once the installation was complete (ah, the power…).

posted by Nick at 6:55 pm - filed in .net  

Friday, May 4, 2007

Using WatiN to automate accessibility testing in .Net

WatiN is a web testing framework for .Net - it is a C# port of Watir, which is in Ruby. Both function by driving Internet Explorer and are fully scriptable, which means you can do things like:

[Test]
public void SearchForWatiNOnGoogle()
{
    using (IE ie = new IE("http://www.google.com"))
    {
        ie.TextField(Find.ByName("q")).TypeText("WatiN");
        ie.Button(Find.ByName("btnG")).Click();
        Assert.IsTrue(ie.ContainsText("WatiN"));
    }
}

This is from the WatiN documentation page, which is pretty helpful - as this shows, it’s easy to get started, and writing basic tests is straightforward (although perhaps not as fast as the Ruby version). WatiN also integrates well with NUnit and other testing frameworks (including TestDriven.Net and the Visual Studio 2005 test runner). I’ve been using this at work to run some basic accessibility tests on some of our web-based products; although accessibility testing can’t be completely automated, it’s pretty handy to be able to perform repetitive HTML inspections automatically. This checks that all <img> tags on a page have the required “alt” attribute (required in the WCAG 1.0 guidelines on images):

[Test]
public void CheckAllImagesHaveAltAttributes()
{
    using (IE ie = new IE("http://localhost/test.aspx"))
    {
        foreach (Image img in ie.Images)
            if (img.Alt == null || img.Alt.Trim().Length == 0)
                Assert.Fail(
                    String.Format("The image with id '{0}' "
                    + "and src '{1}' doesn't have a alt tag "
                    + "in '{2}'",
                    img.Id, img.Src, ie.Url)
                );
    }
}

This checks that all links on a page have a “title” attribute (an overly strict interpretation of the WCAG 1.0 guidelines on links):

[Test]
public void CheckAllLinksHaveTitleAttributes()
{
    using (IE ie = new IE("http://localhost/test.aspx"))
    {
        foreach (Link link in ie.Links)
            if (link.Title == null || link.Title.Trim().Length == 0)
                Assert.Fail(
                    String.Format("The link with id '{0}' "
                    + "and text '{1}' doesn't have a title tag "
                    + "in '{2}'",
                    link.Id, link.InnerHtml, ie.Url)
                );
    }
}

Or that all input fields in a form have an associated “label” tag (WCAG 1.0 guidelines on form labels):

delegate void TestInputFor(IE ie, Element inputField);

[Test]
public void CheckAllFormFieldsHaveLabels()
{
    using (IE ie = new IE("http://localhost/test.aspx"))
    {
        TestInputFor assertElementHasLabel =
            delegate(IE ieInstance, Element inputField)
        {
            //check whether the corresponding label exists.
            Debug.WriteLine("Checking whether element "
                + inputField.Id + " has a label");
            int cnt = 0;
            foreach (Label lbl in ieInstance.Labels)
                if (lbl.For.Equals(inputField.Id))
                    cnt++;
            //assert the label was found
            Assert.AreEqual(1, cnt,
                String.Format("Expected a label for text field"
                + " with ID {0}, but found {1:d} in page '{2}'",
                inputField.Id, cnt, ieInstance.Url));
        };

        foreach (CheckBox cb in ie.CheckBoxes)
        {
            assertElementHasLabel(ie, cb);
        }

        foreach (TextField tf in ie.TextFields)
        {
            if(tf.GetAttributeValue("type").Equals("hidden"))
                continue;
            assertElementHasLabel(ie, tf);
        }

        foreach (SelectList sl in ie.SelectLists)
        {
            assertElementHasLabel(ie, sl);
        }

        foreach (RadioButton rb in ie.RadioButtons)
        {
            assertElementHasLabel(ie, rb);
        }
    }
}

These are rather basic tests; and they are far from extensive. However, they should give a good idea how much time can be saved by automated testing, especially in the context of standard systems which get customised on a per-client basis (e.g. a content management system for which the layout is customised on a per-client basis; the tests are written once and can be run against each client’s version).

posted by Nick at 8:00 pm - filed in .net, accessibility, testing  

Thursday, October 5, 2006

String Formatting in C#

String formatting is handy to save on both code and garbage collection - it saves on code because it handles formatting including localisation in a way which would be tedious to reproduce manually, and on garbage collection because it uses a StringBuilder internally to perform its magic. This is a quick reference for the different types of formatting offered by the String.Format() method.

Basics

String formatting occurs via character subsitution: control characters in the string to be formatted are replaced with the arguments you provide it as such:

String.Format("{0} says hello", "John");

-> "John says hello"

Here, {0} is substituted with the argument provided - you can pass up to three arguments or an argument array:

String.Format("{0} from {1} says hello to {2}", "John", "Sheffield", "Jane");

String.Format("{0} from {1} says hello to {2} from {3}", new object[]{"John", "Sheffield", "Jane", "Hull"});

The parameters to be substituted (e.g. {0}) are formatted as such:

{<index>[,<alignement>][:<format specifier>]}

Where:

  • index is the index of the object in the argument array to be used in the substitution
  • padding determines whether the substituted string should be padded to be a certain length
  • the format specifier allows the use of predefined formatting for the parameter

The .Net Framework provides standard specifiers depending on the type of the argument, as well as the ability to perform custom formatting for numeric and DateTime data types. The following specifiers can be used:

Numerals - Standard Formatting

The following standard specifiers are available for formatting numbers:

Specifier Name Syntax Output
(using double 9.8765)
Output
(using int -98765)
c (or C) Currency {0:c} £9.88 -£98,765.00
d (or D) Decimal
(whole number)
{0:d} System.FormatException -98765
e (or E) Exponent {0:e} 9.876500e+000 -9.876500e+004
f (or F) Fixed point {0:f} 9.88 -98765.00
g (or G) General {0:g} 9.8765 -98765
n (or N) Number {0:n} 9.88 -98,765.00
r (or R) Round trippable {0:r} 9.8765 System.FormatException
x (or X) Hexadecimal {0:x} System.FormatException fffe7e33

The currency specifiers is culture-dependent, and output will depend on the Locale of the current thread - the example outputs come from my box running with the “en-UK” locale, but would be different when run on another locale.

Numerals - Custom Formatting

In addition to the standard date specifiers, the following specifiers can be used for custom number formatting:

Specifier Name Syntax Output
(using double 9.8765)
Output
(using int -98765)
0 Zero Placeholder {0:00.0000} 09.8765 -98765.0000
# Digit Placeholder {0:##.##} 9.88 -98765
. Decimal Point Separator {0:#.#} 9.9 -98765
, Thousands Separator {0:#,#} 10 -98,765
% Percentage {0:#%} 988% -9876500%
e (or E) Exponent Placeholder {0:00e+000} 99e-001 -99e+003
; Group Separator {0:#,##0.00;(#,##0.00);Zero} 9.88 (98,765.00)

Dates - Standard Formatting

The following standard specifiers are available for formatting dates:

Specifier Name Syntax Output
(using June 6th, 2000, at 00:00:01)
d Short Date {0:d} 01/06/2000
D Long Date {0:D} 01 June 2000
t Short Time {0:t} 00:00
T Long Time {0:T} 00:00:01
f Full date and time (short time) {0:f} 01 June 2000 00:00
F Full date and time (long time) {0:F} 01 June 2000 00:00:01
g Default date and time (short time) {0:g} 01/06/2000 00:00
G Default date and time (long time) {0:G} 01/06/2000 00:00:01
M Day and Month {0:M} 01 June
r RFC1123 date string {0:r} Sat, 01 Jun 2000 00:00:01 GMT
s Sortable date and time (ISO 8601) {0:s} 2000-06-01T00:00:01
u Universal, local time {0:u} 2000-06-01 00:00:01Z
U Universal, UTC time {0:U} 31 May 2000 23:00:01
Y or y Month and Year {0:Y} June 2000

Dates - Custom Formatting

In addition to the standard date specifiers, the following specifiers can be used for custom date formatting:

Specifier Name Syntax Output
(using June 6th, 2000, at 00:00:01)
dd Day Number {0:dd} 01
ddd Short Day Name {0:ddd} Sat
dddd Full Day Name {0:dddd} Saturday
f, ff, fff etc… Second fractions {0:fff} 000
gg Era {0:gg} A.D.
hh 2 digit hour (12 hour) {0:hh} 00
HH 2 digit hour (24 hour) {0:HH} 00
mm 2 digit minute {0:mm} 00
MM Month Number {0:MM} 06
MMM Short Month Name {0:MMM} Jun
MMMM Full Month Name {0:MMMM} June
ss Seconds {0:ss} 01
tt AM/PM {0:tt} AM
yy 2 digit year {0:yy} 00
yyyy 4 digit year {0:yyyy} 2000
zz Short Timezone Offset {0:zz} +01
zzz Full Timezone Offset {0:zzz} +01:00
: Separator {0:hh:mm:ss} 00:00:01
/ Separator {0:dd/MM/yyyy} 01/06/2000

All of these specifiers are culture-dependent (apart from the Universal specifiers, which are universal and therefore not culture-dependent), and will depend on the Locale of the current thread - the example outputs come from my box running with the “en-UK” locale, but would be different when run on another locale.

Enumerators

The following standard specifiers are available for formatting Enums:

Specifier Name Syntax Output
(using DateTimeKind.Local)
g General (Flag if present, Decimal otherwise) {0:g} Local
f Flag (string) {0:f} Local
d Decimal {0:d} 2
x Hexadecimal {0:z} 00000002

Strings

The only formatting available to Strings is the padding option, which can be positive or negative depending on whether the string should be left- or right-aligned:

String.Format("'{0,10}'", "John");

-> ' John'

String.Format("'{0,-10}'", "John");

-> 'John '

Culture

As mentionned previously, the currency and date formats are culture-dependent. This means that the output of the formatted string will depend on what locale is made available to the method. By default, the String.Format method will use the locale of the current thread as a basis for formatting; the current thread locale can be set as such:

//set the culture in the current thread to French
Thread.CurrentThread.CurrentCulture = new CultureInfo("fr-FR");
String.Format("{0:c}", 22.45);

-> 22,45 €
String.Format is also overloaded to accept a CultureInfo argument, which can be used to format a DateTime or currency based on a specific locale:

//Format a currency using French currency formatting
String.Format("{0:c}", 22.45, new CultureInfo("fr-FR"));

-> 22,45 €

Sample Code

Sample code demonstrating all of the specifiers mentionned above and setting the culture for the current thread:
C# String Formatting - Sample Code

This code can be compiled using the C# compiler and run from the command line. Using the command prompt (and assuming the code has been saved to C:\StringFormatExample.cs):

C:>SET PATH=%PATH%;%WINDIR%\Microsoft.NET\Framework\v2.0.50727;
C:>csc StringFormatExample.cs
Microsoft (R) Visual C# 2005 Compiler version 8.00.50727.42
for Microsoft (R) Windows (R) 2005 Framework version 2.0.50727
Copyright (C) Microsoft Corporation 2001-2005. All rights reserved.

C:>StringFormatExample.exe fr-FR

Reference

There is actually quite a reasonable amount of reference material available - I only found the other two blog posts after writing this though :-/ (I decided to post anyways)

MSDN docs for standard number formatting

MSDN docs for custom number formatting

MSDN docs for standard date formatting

MSDN docs for custom date formatting

http://blog.stevex.net/index.php/string-formatting-in-csharp/

http://idunno.org/archive/2004/14/01/122.aspx

posted by Nick at 6:51 pm - filed in .net