Infragistics WebHierarchicalDataGrid: “theForm is undefined”

I am using Infragistics WebHierarchicalDataGrid inside my webapplications sometimes. After I deployed one of those applications onto the customers web server (Windows Server 2003 with IIS 6) I got the error mentioned above. I was wondering why, because on my development machine (Windows 7 with installed IIS) everything works fine. Finally renaming the form from “form1” to “theForm” did the trick.


<form id="theForm" runat="server">

Der angegebene Assemblyname oder die Codebasis ist ungültig. (Ausnahme von HRESULT: 0x80131047)

Der Fehler tritt auf, wenn man versucht per Reflection einen invaliden Typ zu ermitteln. Beispiel:


string typename = "SampleLib.Sample, SampleLib, Version=1.0.0.0,Culture=neutral;PublicKeyToken=1e6becac76b64446";
Type type = Type.GetType(typename);

Der Ursprung des Fehlers liegt hier in einem Tippfehler innerhalb des typname-Strings (; statt ,). Hat mich wertvolle Zeit gekostet, bis ich das gesehen hatte…

Mocken von Klasseninstanzen mit Rhino Mocks

Rhino Mocks lässt sich dazu nutzen, um in Unit Tests Klasseninstanzen zu faken, die nicht von einer abstrakten Klasse oder einem Interface abgeleitet sind. Dazu ein kleines simples Beispiel:


    public class Bl
    {
        public string GetStatus()
        {
            Funktionen funktionen = new Funktionen();

            if (funktionen.LangAndauerndeFunktion())
                return "OK";
            
            return "Nicht OK";
        }
    }

Die Funktion GetStatus erzeugt eine Instanz der Klasse Funktionen und ruft eine Methode auf, die einen boolschen Wert zurückgibt. Basierend darauf wird ein Text zurückgegeben (OK/Nicht OK). Die Klasse Funktionen ist folgendermaßen aufgebaut:


    public class Funktionen
    {
        public bool LangAndauerndeFunktion()
        {
            //Hier wird irgendwas performancelastiges ausgeführt
            //komplizierte Berechnungen, Datenbankzugriffe, etc...

            return true; //Rückgabe, damit das Projekt kompiliert werden kann
        }
    }

Um die Funktion GetStatus mit einem Unit Test abdecken zu können, sind folgende Änderungen nötig:

1. Die Funktion LangAndauerndeFunktion() virtual markieren, damit RhinoMocks diese überschreiben kann.


    public class Funktionen
    {
        public virtual bool LangAndauerndeFunktion()
        {
            //Hier wird irgendwas performancelastiges ausgeführt
            //komplizierte Berechnungen, Datenbankzugriffe, etc...

            return true; //Rückgabe, damit das Projekt kompiliert werden kann
        }
    }

2. Die Instanzierung der Klasse Funktionen in eine Factory-Methode verschieben. Die Methode muss protected virtual sein, um im Unit Test eine gefakte Instanz übergeben zu können.


    public class Bl
    {
        public string GetStatus()
        {
            Funktionen funktionen = GetFunktionenInstance();

            if (funktionen.LangAndauerndeFunktion())
                return "OK";
            
            return "Nicht OK";
        }

        protected virtual funktionen GetFunktionenInstance()
        {
            return new Funktionen();
        }
    }

Für die Erstellung der Unit Tests benötigt man nun eine Hilfsklasse, die von der zu testenden Klasse (in diesem Fall Bl) abgeleitet ist. Diese überschreibt die Funktion GetAusgelagerteFunktionen:


    public class BlTestHelper : Bl
    {
        public Funktionen FunktionenInstance { get; set; }
        protected override Funktionen GetFunktionen()
        {
            return FunktionenInstance ?? base.GetFunktionenInstance();
        }
    }

Die Unit Tests sehen für die GetStatus – Methode der zu testenden BL wie folgt aus:


    [TestFixture]
    public class BlTests
    {
        [Test]
        public void GetStatus_LangAndauerndeFunktionReturnsFalse_ReturnsNichtOk()
        {
            MockRepository mockRepository = new MockRepository();
            Funktionen funktionen = mockRepository.Stub<Funktionen>();

            using (mockRepository.Record())
            {
                SetupResult.For(funktionen.LangAndauerndeFunktion()).Return(false);
            }

            BlTestHelper helper = new BlTestHelper();
            helper.FunktionenInstance = funktionen;

            string status = helper.GetStatus();

            Assert.That(status.Equals("Nicht OK"));
        }

        [Test]
        public void GetStatus_LangAndauerndeFunktionReturnsTrue_ReturnsOk()
        {
            MockRepository mockRepository = new MockRepository();
            Funktionen funktionen = mockRepository.Stub<Funktionen>();

            using (mockRepository.Record())
            {
                SetupResult.For(fFunktionen.LangAndauerndeFunktion()).Return(true);
            }

            BlTestHelper helper = new BlTestHelper();
            helper.FunktionenInstance = funktionen;

            string status = helper.GetStatus();

            Assert.That(status.Equals("OK"));
        }

    }

Zu beachten ist, dass man in den Tests die BlTestHelper – Klasse instanziert und dieser den vom MockRepository erzeugten Stub übergibt. Die Testergebnisse zeigen, dass meine BL wie gewünscht reagiert:
Ergebnisse des Unit Tests

Setzen eines Properties per Reflection

Ab und an kann es nützlich sein, Properties einer Klasse per Reflection setzen zu können. Dazu ist lediglich folgender Code nötig:


public void SetProperty( string nameOfProperty, object value )
{
    PropertyInfo propertyInfo = GetType().GetProperty( nameOfProperty, BindingFlags.Public | BindingFlags.Instance | BindingFlags.IgnoreCase );
            
    if( propertyInfo == null )
        throw new NullReferenceException( string.Format( "Die Eigenschaft {0} konnte nicht gefunden werden!", nameOfProperty ) );

    Type propertyType = propertyInfo.PropertyType;
    propertyInfo.SetValue( this, Convert.ChangeType(value, propertyType), null );
}

Beispiel:


public class Person
{
    public string Vorname { get; set; }
    public string Nachname { get; set; }

    public override string ToString()
    {
        return string.Format("{0}, {1}", Nachname, Vorname);
    }

    public void SetProperty( string nameOfProperty, object value )
    {
        PropertyInfo propertyInfo = GetType().GetProperty( nameOfProperty, BindingFlags.Public | BindingFlags.Instance | BindingFlags.IgnoreCase );
            
        if( propertyInfo == null )
            throw new NullReferenceException( string.Format( "Die Eigenschaft {0} konnte nicht gefunden werden!", nameOfProperty ) );

        Type propertyType = propertyInfo.PropertyType;
        propertyInfo.SetValue( this, Convert.ChangeType(value, propertyType), null );
    }
}


class Program
{
    static void Main(string[] args)
    {
        Person person = new Person();
        person.SetProperty("Vorname", "Thorsten");
        person.SetProperty("Nachname", "Vogt");
        Console.WriteLine(person); // Ausgabe: Vogt, Thorsten
    }
}

Visual Studio, IIS und Skype

Wer ein Webprojekt in Visual Studio via IIS starten möchte und Skype installiert hat, kann unter Umständen folgende Fehlermeldung bekommen:

Ein Blick in den IIS – Manager zeigte, dass die Standardwebsite gestoppt war. Ein Starten der Website war nicht möglich. Der für die Website konfigurierte Port 80 wurde offensichtlich durch eine andere Anwendung blockiert.

Die Ursache lag bei mir in der Konfiguration von Skype. Standardmäßig ist da der Port 80 als Listener für eingehende Verbindungen eingestellt.

Ein deaktivieren der Option und Neustart von Skype behebt das Problem. Natürlich muss die Website im IIS-Manager anschließend noch gestartet werden.

Bei der Fehlersuche erwies sich hier TCPView als äußerst nützlich.

Public Key Token einer Assembly ermitteln

Um den Public Key Token einer signierten Assembly zu ermitteln, kann das Tool sn.exe genutzt werden. Hierzu einfach den Parameter -T mit angeben und die entsprechende Assembly an den Befehl anhängen. Soll der entsprechende Public Key der Assembly mit ausgegeben werden, so ist der Parameter -Tp zu verwenden.

sn -Tp MyAssembly.dll
Microsoft (R) .NET Framework Strong Name Utility Version 3.5.30729.1
Copyright (c) Microsoft Corporation. All rights reserved.

Public key is
00240000048000009400000006020000002400005253413100040000010001007b625679a9fee3
f6c3c6fa478d4fbcbf46148d0691210aa88aeaec4ff4d350e2261a49b261227105e9257503dc69
51c417e0b0cc924f0c53afa7815499c4c3bc3321547b6f883f75c42b88bcf0ac39690c0f8b3d42
2cc3e5e93f3528e15c32aedf70b930cd75a0ee1f0c87d1f8b35a633d3d002afc566191175d7c5d
90f1fdb2

Public key token is 2bb82c850a7b28d3

Ich habe noch einen Blogeintrag gefunden, der die Einrichtung in Visual Studio beschreibt.

Prüfen ob eine Klasse ein bestimmtes Interface implementiert

Ab und an kann es vorkommen, dass man zur Laufzeit bestimmen muss, ob eine Klasse ein bestimmtes Interface implementiert. Dies läßt sich mit der Methode IsAssignableFrom() der Klasse System.Type realisieren:


public interface IMyInterface
{
    //Interface Code        
}

public class MyInterfaceImplementation : IMyInterface
{
    //Implementierung
}

public class AnotherClass
{ 
    //...
}

typeof(IMyInterface).IsAssignableFrom(typeof(AnotherClass)); //false
typeof(IMyInterface).IsAssignableFrom(typeof(MyInterfaceImplementation)); //true


Erweiterungsmethode: String.Like

Hier eine kleine Erweiterungsmethode, die ein SQL Like auf Strings ermöglicht:


public static bool Like( this string value, string pattern )
{
    string parsedPattern = "\\A" + Regex.Escape( pattern ).Replace( "\\*", ".*" ).Replace( "\\?", "." ) + "\\Z";

    Regex regex = new Regex(parsedPattern, RegexOptions.IgnoreCase);

    return regex.IsMatch(value);
}

Die Funktion eignet sich, wenn ich statt einer Linq-Abfrage einen Lamda-Ausdruck verwenden will/muss:


List<string> theSimpsons = new List<string>(){"Homer", "Bart", "Marge", "Lisa", "Maggie"};

Func<string, bool> matchCriteria = person => person.Like("*ar*");
Debug.WriteLine( "*ar*" );

foreach (string character in theSimpsons.Where(matchCriteria))
{
    Debug.WriteLine( character );
}

matchCriteria = person => person.Like( "M*i*" );
Debug.WriteLine( "M*i*" );
foreach( string character in theSimpsons.Where( matchCriteria ) )
{
    Debug.WriteLine( character );
}

matchCriteria = person => person.Like( "M*e" );
Debug.WriteLine( "M*e" );
foreach( string character in theSimpsons.Where( matchCriteria ) )
{
    Debug.WriteLine( character );
}

matchCriteria = person => person.Like( "*a*" );
Debug.WriteLine( "*a*" );
foreach( string character in theSimpsons.Where( matchCriteria ) )
{
    Debug.WriteLine( character );
}

matchCriteria = person => person.Like( "*a" );
Debug.WriteLine( "*a" );
foreach( string character in theSimpsons.Where( matchCriteria ) )
{
    Debug.WriteLine( character );
}


Ausgabe:
*ar*
Bart
Marge
M*i*
Maggie
M*e
Marge
Maggie
*a*
Bart
Marge
Lisa
Maggie
*a
Lisa