Running SQL on Entity Framework

by fkollmann 9/5/2009 12:25:37 AM

Easy and clean:

public static DbConnection GetStoreConnection(this ObjectContext oc)
{
    if (oc == null)
        throw new NullReferenceException("oc is null");

    var conn = (EntityConnection)oc.Connection;

    if (conn.State == ConnectionState.Closed)
        conn.Open();

    return conn.StoreConnection;
}

Visual Studio 2008 refuses to bind to TFS or to open solution source controlled

by fkollmann 8/25/2009 7:47:40 PM

We came up with the issue that there are one of the following errors regarding the TFS 2008.

Either you are unable to bind a solution at all, showing:

The solution you have opened is under source control but not currently configured for integrated source control in Visual Studio. …

Or the solution is opened without source control, showing:

The solutions appears to be under source control but its binding information cannot be found. …

Output Window: The solution is offline because its associated Team Foundation Server is offline.

The solution is quite simple: Recreate the server entry in Visual Studio 2008:

1) Close the solution

2) Disconnect the TFS

clip_image002

3) Remove the server

clip_image002[4]

clip_image002[6]

clip_image002[8]

4) Re-add the server

clip_image002[10]

5) Open the solution. Everything should be fine now.

Q: http://markitup.com/Posts/Post.aspx?postId=6355ea6f-3af6-4cfc-86b0-b6467de2cd0d
Q: http://social.msdn.microsoft.com/Forums/en-US/tfsversioncontrol/thread/308255ac-2e10-426c-996c-ca62321c8e1f

Loading Assembly’s exported Types

by fkollmann 8/6/2009 3:04:35 PM

Simple and clean…

public class ExportedTypesLoader : IDisposable
{
    private AppDomain _domain;
    private IEnumerable<Type> _types;

    public IEnumerable<Type> ExportedTypes
    {
        get { return _types; }
    }

    public Type FindType(string fullName)
    {

        if (string.IsNullOrEmpty(fullName))
            throw new ArgumentException("null or empty", "fullName");

        return (
            from t in _types
            where t.FullName == fullName
            select t
            ).FirstOrDefault();
    }

    public void Dispose()
    {
        if (_domain != null)
        {
            AppDomain.Unload(_domain);
        }
    }

    public ExportedTypesLoader(string asmPath)
    {
        if (string.IsNullOrEmpty(asmPath))
            throw new ArgumentException("null or empty", "asmPath");

        // file exists?
        var asmFile = new FileInfo(asmPath);

        if (!asmFile.Exists)
            throw new ArgumentException("assembly file does not exist: " + asmFile.FullName, "asmPath");

        // create domain
        _domain = AppDomain.CreateDomain("ExportedTypesLoaderDomain-" + Guid.NewGuid().ToString("N"));

        // load assembly and exported types
        var asmData = File.ReadAllBytes(asmFile.FullName);

        var asm = _domain.Load(asmData);

        _types = asm.GetExportedTypes();

    }
}

Creating certificates using BouncyCastle

by fkollmann 7/16/2009 10:55:57 AM

For one of our projects we required some code to automatically…

  • generate a self-signed certificate,
  • ensure that it’s trusted, and
  • install it into the IIS webapp https:443.

To do this the following steps are performed – the following code has been simplified but shows the way:

0) Notes

  • BouncyCastle has been used to generate the key.
  • RandomGenerators is a helper class of us to generate some random data. It’s no big deal to implement them yourselves.
  • ServerManager is a type of "C:\Windows\System32\inetsrv\Microsoft.Web.Administration.dll"

1) Find existing certificate

var keyStore = new X509Store(StoreName.My, StoreLocation.LocalMachine);

keyStore.Open(OpenFlags.OpenExistingOnly | OpenFlags.ReadWrite);

var certs = keyStore.Certificates.Find(
    X509FindType.FindBySubjectDistinguishedName,
    "CN=" + Environment.MachineName,
    true
    );

// find a valid key
X509Certificate2 cert = null;

foreach (var c in certs)
{
    // a private key is required
    if (!c.HasPrivateKey)
    {
        continue;
    }

    return cert;
}

2) Generate new certificate using BouncyCastle (if non was found)

var kpgen = new RsaKeyPairGenerator();

kpgen.Init(new KeyGenerationParameters(
    new SecureRandom(new CryptoApiRandomGenerator()),
    1024
    ));

var kp = kpgen.GenerateKeyPair();

var gen = new X509V3CertificateGenerator();

var certName = new X509Name("CN=" + Environment.MachineName);
var serialNo = BigInteger.ProbablePrime(120, RandomGenerators.CreateRandom());

gen.SetSerialNumber(serialNo);
gen.SetSubjectDN(certName);
gen.SetIssuerDN(certName);
gen.SetNotAfter(DateTime.Now.AddYears(1));
gen.SetNotBefore(DateTime.Now.Subtract(new TimeSpan(7, 0, 0, 0)));
gen.SetSignatureAlgorithm("MD5WithRSA");
gen.SetPublicKey(kp.Public);

gen.AddExtension(
    X509Extensions.AuthorityKeyIdentifier.Id,
    false,
    new AuthorityKeyIdentifier(
        SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(kp.Public),
        new GeneralNames(new GeneralName(certName)),
        serialNo
    ));

gen.AddExtension(
    X509Extensions.ExtendedKeyUsage.Id,
    false,
    new ExtendedKeyUsage(new ArrayList()
    {
        new DerObjectIdentifier("1.3.6.1.5.5.7.3.1")
    }));

var newCert = gen.Generate(kp.Private);

3) Import key to Windows keystore

private static X509Certificate2 ConvertToWindows(X509Certificate newCert, AsymmetricCipherKeyPair kp)
{
    var tempStorePwd = RandomGenerators.GetRandomString(50, 75);
    var tempStoreFile = new FileInfo(Path.GetTempFileName());

    try
    {
        // store key
        {
            var newStore = new Pkcs12Store();

            var certEntry = new X509CertificateEntry(newCert);

            newStore.SetCertificateEntry(
                Environment.MachineName,
                certEntry
                );

            newStore.SetKeyEntry(
                Environment.MachineName,
                new AsymmetricKeyEntry(kp.Private),
                new[] { certEntry }
                );

            using (var s = tempStoreFile.Create())
            {
                newStore.Save(
                    s,
                    tempStorePwd.ToCharArray(),
                    new SecureRandom(new CryptoApiRandomGenerator())
                    );
            }
        }

        // reload key
        return new X509Certificate2(tempStoreFile.FullName, tempStorePwd);
    }
    finally
    {
        tempStoreFile.Delete();
    }
}

4) Ensure the certificate is trusted

if (!cert.Verify())
{
    Console.WriteLine("Enforcing trust on certificate...");

    var keyStore = new X509Store(StoreName.AuthRoot, StoreLocation.LocalMachine);

    keyStore.Open(OpenFlags.OpenExistingOnly | OpenFlags.ReadWrite);

    try
    {
        keyStore.Add(cert);
    }
    finally
    {
        keyStore.Close();
    }
}

5) Bind the certificate to the IIS webapp

using (var sm = new ServerManager())
{
    foreach (var site in sm.Sites)
    {
        foreach (var bnd in site.Bindings)
        {
            if ((bnd.EndPoint.Port == 443) &&
                (bnd.Protocol == "https"))
            {
                site.Bindings.Remove(bnd);
                site.Bindings.Add(bnd.BindingInformation, cert.GetCertHash(), "MY");

                break;
            }
        }
    }

    // commit changes
    sm.CommitChanges();
}

 

UPDATE: Changes certificate serial number length form 64 bit to 120 bit to match Microsoft’s makecert default.
UPDATE2: There is a known issue: The certificate created here cannot be added to a binding after being created (via API and IIS7 Manager). The workaround is to always create a new certificate.

Benutzer für TFS WorkItems einschränken

by fkollmann 5/11/2009 11:52:17 AM

Die Einschränkung der WorkItem Benutzer (insb. System.AssignedTo) ist relativ einfach; Willy-Peter Schaub beschreibt in seinem Blog, wie es geht.

PS: Er selbst nutzt hier die Standardgruppen. In meinem Fall habe ich eine neue Gruppe “Ticket Owners” erstellt, um dies besser konfigurieren zu können.

ARTIKEL

ORM Performance

by fkollmann 4/15/2009 3:31:28 PM

Dariusz Parys hat sich mit der Performance von ORMs unter .NET auseinander gesetzt, und hat ein interessantes Ergebnis erzielt:

image

Das für mich überrraschende war, dass NHibernate so gut abgeschnitten hat – Man lernt halt nie aus.

Q: http://blogs.msdn.com/dparys/archive/2009/04/06/improving-entity-framework-performance.aspx
Q: http://toomanylayers.blogspot.com/2009/01/entity-framework-and-linq-to-sql.html

Using Windows Home Server Wizards

by fkollmann 3/8/2009 11:31:40 PM

Today I implemented a wizard on the Windows Home Server Console. Honestly, since the wizard mechanism of WHS is not compatible with the designer, it took me and Reflector a long time to figure out how it works and which members are important.

I ended up with creating some wrapper classes which allow to actually create the wizard pages using the designer:

  image2   image 

 

Note: The implementation of the wrappers are part of the RouterControl.Whs assembly under the namespace RouterControl.Whs.Wizards. A full code example can be found in the WHS add-in code: RouterControl.WhsAddin.Wizards.

The wizard consists of two object types: the wizard itself and one or more wizard pages. The wizard is just a few lines of code and does nothing more than to register the pages to use (example). The wizard pages are then simply user controls which inherit WizardPageClientBase or WizardPageClientBannerTop to be precise (example).

To run the wizard, the wizard class is instanced and its Run() metod called:

        private void createNewLink_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            try
            {
                var wiz = new Wizards.EditPortForwarding();

                wiz.Run();
            }
            catch (Exception ex)
            {
                _log.Error("Failed to run edit-port-forwarding wizard", ex);
            }
        }

I do not want to end up in details because all the source is open. You can either download the source or browse the changeset directly.

Windows 7 Desktop Integration for .NET

by fkollmann 2/10/2009 5:57:37 PM

Hüseyin Tüfekçilerli started a project on CodePlex to bring the new Windows 7 API extensions to .NET. There are yet some features left to implement but it’s a good start. I think it is however unclear if the new features will be integrated into Vista Bridge, too, or not – I felt like starting a thread here.

http://www.codeplex.com/Windows7TaskbarExt

UPDATE: Microsoft released an own implementation for this (including Vista Bridge):

http://code.msdn.microsoft.com/Windows7Taskbar

UPDATE2: There is a new project from Microsoft providing Multi Touch support:

http://code.msdn.microsoft.com/WindowsTouch

UPDATE3: There is a new project available from Microsoft called Windows API Code Pack:

http://code.msdn.microsoft.com/WindowsAPICodePack

Globale Ressourcendateien in SharePoint nutzen

by fkollmann 10/29/2008 4:58:28 PM

An einigen Stellen kommt man nicht umher eigene globale Ressourcendateien zu nutzen, z.B. wenn man diese in Systemseiten einbinden muss oder will.

Nehmen wir als Beispiel die application.master und nehmen wir an dort soll z.B. ein sprachabhängiger Copyright-Text erscheinen. Ein sauberer Weg wäre eine eigene Control zu machen, und die Übersetzung über deren Assembly zu machen. Wenn der Text selbst aber nur Parameter in einer fremden Control ist, oder man aus anderen Gründen unbedingt eine Ressource einbinden möchte, dann erfolg dies so:

<%$Resources:myresfile,myStringEntry%>

Achtung: myresfile ist nur der Dateiname der Ressourcendatei ohne Endung. myStringEntry ist ganz normal der Eintrag in der Ressourcendatei.

Die dazugehörige Ressourcendatei lässt sich einfach über Visual Studio erzeugen; Die Einträge kommen dann in den Strings-Bereich; Abschalten der Codegenerierung nicht vergessen.

Natürlich muss diese Datei in den App_GlobalResources Ordner der Webapplikation(!). Problem ist nur, dass jede Webapplikation ihren eigenen Ordner hat. Daher gibt es beim Deployment drei Fälle, welche abfangen werden müssen:

1) Deployment in vorhandene Webapplikationen

Eigentlich ist dieser Punkt nicht sonderlich kompliziert, kann aber nicht Teil des Delpoyments per .wsp-Datei sein.

Alle Webappliationen befinden sich unter C:\inetpub\wwwroot\wss\VirtualDirectories . Entsprechend muss die Ressourcendatei “nur” in das App_GlobalResources Verzeichnis jedes Unterverzeichnisses kopiert werden; Also quasi nach C:\inetpub\wwwroot\wss\VirtualDirectories\*\App_GlobalResources .

2) Deployment in zukünftige Webapplikationen

Dies geht recht einfach. Hierzu deployed man die Resourcendatei einfach in das \12\CONFIG\Resources Verzeichnis. Alle Ressourcendateien dort werden beim erzeugen einer neuen Webapplikation in deren App_GlobalResources Verzeichnis kopiert.

3) Entfernen der Ressourcendatei beim undeployen

Dieser Fall ist ähnlich dem ersten Punkt. Aber eine Datei zuviel schadet ja im Zweifelsfall auch nicht…

Eigenen std::allocator implementieren

by fkollmann 8/29/2008 10:55:40 AM

Für diejenigen, die in C++ einen eigenen STL allocator schreiben wollen oder müssen hat Stephan T. Lavavej ein schön erklärtes Beispiel erstellt, bei dem er einen einfachen malloc()/free() std::allocator implementiert, und zwar ohne von diesem zu erben.

ZUM BEISPIEL