Blog

posts from 2008

Silverlight 2.0 Cross Domain Policy File Checker

0 Comments
By Fons Sonnemans, 18-12-2008

In order to make Cross Domain calls in Silverlight 2 applications, the server you wish to download data from must have a Policy File in place that allows access to your site. I have created a Silverlight Application in which you can check the content of the Policy Files (if exists).

Click on the image below to try the application

Try application

Silverlight 2.0 Locator for Objectmap

0 Comments
By Fons Sonnemans, 10-11-2008

I have created a new Silverlight 2 Control which is used in the Objectmap website. This control makes it easy for the customers of accounts to find their nearest object (branch, offices or sales outlet). They can also immediately retrieve dynamic directions to this location or link to a more info page.

Have a look at this demopage, sorry in Dutch only.

This control uses: Cross Domain WCF networking, Data Binding, Isolated Storage Settings, Google Maps API calls, Cross Domain HTML Bridge and Styling.

Silverlight 2.0 Minesweeper

0 Comments
By Fons Sonnemans, 23-10-2008

Earlier I have created a WPF and a Windows Forms version of Minesweeper. Today I proud to show you my Silverlight 2.0 (RTW) version. Click on the image below to play this version.

You can download the C# source code and the example website here.

SQL Server 2008 HierarchyID Data Type

0 Comments
By Fons Sonnemans, 15-10-2008

The Dutch Microsoft .NET magazine #22 (September 2008) contains an article I have written an Introduction to the SQL Server 2008 HierarchyID Data Type. You can download the complete source of the article here. In this source I also fixed the problem with the IsDescendant() method. This method was renamed in RC0, my article was based on a Beta. The method is renamed to IsDescendantOf() and the argument has also changed.

The article is available online in PDF format on download.microsoft.com. Please note that the article is in Dutch. The complete .NET magazine #22 is available online here.

Tags: SQL

Hello World in Silverlight 2 using Visual Studio 2008 SP1 Video

0 Comments
By Fons Sonnemans, 9-10-2008

Dit is mijn eerste Silverlight 2 instructie video. In deze video toon ik hoe je een eenvoudige Hello World applicatie kunt opzetten met behulp van Silverlight 2 (RC0) en Visual Studio 2008 met Service Pack 1.

Toon Video

Download de HelloWorld.zip sourcecode. Zorg er wel voor dat je alle benodigde software geinstalleerd hebt.

Fix the ASP.NET Themes with IE8’s X-UA-Compatible header problem

0 Comments
By Fons Sonnemans, 26-9-2008

If you’ve got a page that doesn’t render correctly in IE8’s new standards mode, you can add a meta tag to the page which requests that IE8 render it in IE7 mode. IE8 only recognizes the X-UA-Compatible header if it’s the first META tag, appearing immediately after the tag.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head id="Head1" runat="server"> <meta http-equiv="X-UA-Compatible" content="IE=7" /> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <link rel="shortcut icon" href="favicon.ico" /> <title>Test</title> </head> <body>[...]</body></html>

The Problem

The ASP.NET Theme system writes out the theme CSS reference immediately after the <HEAD> tag. This makes it impossible to set the X-UA-Compatible header or to use Stylesheets in your theme folder.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head id="Head1"> <link href="App_Themes/Default/Stylesheet.css" type="text/css" rel="stylesheet" /> <meta http-equiv="X-UA-Compatible" content="IE=7" /> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <link rel="shortcut icon" href="favicon.ico" /> <title>Test</title> </head> <body>[...]</body></html>

The Solution

To fix this problem I have added an implementation for the Application_PreRequestHandlerExecute event in the Global.asax. This method will sort the controls inside the header. It places the X-UA-Compatible metatag on top. I use an anonymous method which is subscribed to the PreRenderComplete event of page. This method uses LINQ to find the metatag. Then removes it from the header and add it again on top.

void Application_PreRequestHandlerExecute(object src, EventArgs e) {
    Page p = this.Context.Handler as Page;
    if (p != null) {
        p.PreRenderComplete += (sender, ee) => {
            // I can't use p, it has no Header set (strange), use sender instead
            Page page = sender as Page; 
            if (page.Header != null) {
                // Find the Compatible Meta tag
                var ctrl = page.Header.Controls.Cast<Control>().FirstOrDefault(
                    c => c is HtmlMeta && ((HtmlMeta)c).HttpEquiv == "X-UA-Compatible");

                // If found remove it and add it on top
                if (ctrl != null) {
                    page.Header.Controls.Remove(ctrl);
                    page.Header.Controls.AddAt(0, ctrl);
                }
            }
        };
    }
}

This results in the correct HTML.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head id="Head1"> <meta http-equiv="X-UA-Compatible" content="IE=7" /> <link href="App_Themes/Default/Stylesheet.css" type="text/css" rel="stylesheet" /> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <link rel="shortcut icon" href="favicon.ico" /> <title>Test</title> </head> <body>[...]</body></html>
Tags: Web, ASP.NET

PEAK-IT Summer DevNight 2008

0 Comments
By Fons Sonnemans, 4-7-2008

On Juny 3, I did a Visual Studio 2008 presentation on the PEAK-IT Summer DevNight 2008 at the Fulcotheater in IJsselstein.

You can download the slide deck here.

I had a good time presenting this sessions. I hope it was a useful for you as well.

Silverlight 2.0 RollMenu

0 Comments
By Fons Sonnemans, 24-6-2008

I have created a RollMenu control in Silverlight 2 Beta 2. It uses an Xml file to configure the menu items.

Click on following image for a live demo.

Live Demo

You can download the C# source code and the example website here.

Update 16-Oct-2008: Upgraded to the RTW version of Silverlight.

Hot Technologies Day

0 Comments
By Fons Sonnemans, 18-6-2008

On June 17, I did two sessions on the Hot Technologies Day for Achmea (Interpolis) in Tilburg. I have given many trainings (C#, ASP.NET 2.0, AJAX, SQL2005, VS2008) at Achmea the last year. It is a very innovative company and very fun to work for.

This Hot Technologies Day was a mini seminar with 4 sessions: Silverlight 2, VSTS DB Pro, LINQ + Entity Framework, Microsoft Office SharePoint Server. Here is a picture of me taken during the Silverlight 2 session:

In the Silverlight 2 session I gave an overview of Silverlight 2 Beta 2. You can download the slide deck here.

In the LINQ + Entity Framework session I gave an overview of C# 3.0, LINQ, LINQ to SQL and Entity Framework. You can download the slide deck here.

I had a good time presenting these sessions. I hope it was a useful for you as well.

Generic BidirectionalAssociationCollection

0 Comments
By Fons Sonnemans, 25-3-2008

Bidirectional associations are easy to design but difficult to program. You must write lot's of synchronization code with the risk of making mistakes. Have a look at the following example in which there is a bidirectional association between Employee (Employer) and Company (Employees).

The synchronization code is implemented in the AddEmployee(), RemoveEmployee() and the (Set)Employer methods.

public class Employee {

    public string Name { get; set; }
    public decimal Salary { get; set; }

    private Company _employer;

    public Company Employer {
        get {
            return _employer;
        }
        set {
            if (Employer != value) {
                
                // Remove from 'old' Employer
                if (Employer != null) {
                    Company old = _employer;
                    this._employer = null;
                    old.RemoveEmployee(this);
                }

                // Set the Employer    
                this._employer = value;
                
                // Add to 'new' Employer
                if (Employer != null) {
                    Employer.AddEmployee(this);
                }
            }
        }
    }
}

public class Company {

    public string Name { get; set; }

    private readonly List<Employee> _employees = new List<Employee>();

    public void AddEmployee(Employee emp) {
        if (!_employees.Contains(emp)) {
            _employees.Add(emp);
            emp.Employer = this;  // Synchronize
        }
    }

    public void RemoveEmployee(Employee emp) {
        if (_employees.Contains(emp)) {
            _employees.Remove(emp);
            emp.Employer = null; // Synchronize
        }
    }
}

In the following example Employee 'fons' is added to Company 'Reflection IT'. The Employer property of Employee 'Jim' is set to Company 'Dummy inc'.

Employee fons = new Employee { Name = "Fons", Salary = 2000 };
Employee jim = new Employee { Name = "Jim", Salary = 3000 };

Company r = new Company { Name = "Reflection IT" };
Company d = new Company { Name = "Dummy Inc" };

r.AddEmployee(fons);

jim.Employer = d;

This solution has some limitations. The employees collection in Company is private and the AddEmployee() and RemoveEmployee() methods are necessary but not business related. I have tried to solve this by creating an extra EmployeeList class which solves these problems.

The Employees property is now a readonly public field of the type EmployeeList. The AddEmployee() and RemoveEmployee() methods are removed. This synchonisation logic is now implemented in the InsertItem() and RemoveItem() methods of the EmployeeList class. These methods override the base class (Collection) implementation and are automatically called when an item is added or removed.

public class Company {

    public string Name { get; set; }

    public readonly EmployeeList Employees;

    public Company() {
        this.Employees = new EmployeeList(this);
    }

}

public class EmployeeList : Collection<Employee> {

    private Company _owner;

    public EmployeeList(Company owner) {
        _owner = owner;
    }

    protected override void InsertItem(int index, Employee item) {
        if (!this.Contains(item)) {
            base.InsertItem(index, item);
            item.Employer = _owner;
        }
    }

    protected override void RemoveItem(int index) {
        Employee emp = this[index];
        base.RemoveItem(index);
        emp.Employer = null;
    }
}

Employees are added to a Company using the Add() method of the Employees property. Or you can set the Employer of an Employee.

Employee fons = new Employee { Name = "Fons", Salary = 2000 };
Employee jim = new Employee { Name = "Jim", Salary = 3000 };

Company r = new Company { Name = "Reflection IT" };
Company d = new Company { Name = "Dummy Inc" };

r.Employees.Add(fons);

jim.Employer = d;

The design is now much better but the implementation still sucks. The risk of making mistakes is still too high. I have created a Generic BidirectionalAssociationCollection class which solves this.

The EmployeeList class now derives from the abstract BidirectionalAssociationCollection class. In it's overriden SyncChild() method the synchronisation is implemented by setting the Employer property of the child to the parent.

The Employee class is now also simplified a lot, reducing the risk of mistakes. The setter of the Employee property is now only 1 line of code. This code uses the static SyncParent() method to synchronize the Employees and the Employer. A Lambda expression is used to retrieve the Employees property of a Company.

Note: I had to introduce a PauseSync field to avoid call stack overflows. This solution is not thread safe (yet).

public class Employee {

    public string Name { get; set; }
    public decimal Salary { get; set; }

    private Company _employer;

    public Company Employer {
        get {
            return _employer;
        }
        set {
            _employer = EmployeeList.SyncParent(this, _employer, value, p => p.Employees);
        }
    }
}

public class Company {

    public string Name { get; set; }

    public readonly EmployeeList Employees;

    public Company() {
        this.Employees = new EmployeeList(this);
    }
}

public abstract class BidirectionalAssociationCollection<TChild, TParent> : Collection<TChild> {

    public static TParent SyncParent(TChild child, TParent oldParent, TParent newParent, 
             Func<TParent, BidirectionalAssociationCollection<TChild, TParent>> getCollection) {
        if (!object.ReferenceEquals(oldParent, newParent)) {

            // Remove from 'old' Employer
            if (oldParent != null) {
                var oldList = getCollection(oldParent);
                try {
                    if (!oldList.PauseSync) {
                        oldList.PauseSync = true;
                        oldList.Remove(child);
                    }
                } finally {
                    oldList.PauseSync = false;
                }
            }

            // Add to 'new' Employer
            if (newParent != null) {
                var newList = getCollection(newParent);
                try {
                    if (!newList.PauseSync) {
                        newList.PauseSync = true;
                        newList.Add(child);
                    }
                } finally {
                    newList.PauseSync = false;
                }
            }
        }
        return newParent;
    }

    private bool PauseSync;
    protected TParent Owner { get; private set; }

    protected BidirectionalAssociationCollection(TParent owner) {
        this.Owner = owner;
    }

    protected override void InsertItem(int index, TChild item) {
        if (!this.Contains(item)) {
            base.InsertItem(index, item);
            if (!PauseSync) {
                SyncChild(item, Owner);
            }
        }
    }

    protected override void RemoveItem(int index) {
        var item = this[index];
        base.RemoveItem(index);
        if (!PauseSync) {
            SyncChild(item, default(TParent));
        }
    }

    protected override void ClearItems() {
        var list = this.ToArray();
        base.ClearItems();
        foreach (var item in list) {
            SyncChild(item, default(TParent));
        }
    }

    protected override void SetItem(int index, TChild item) {
        this.PauseSync = true;
        var old = this[index];
        SyncChild(old, default(TParent));
        this.PauseSync = false;

        base.SetItem(index, item);

        this.PauseSync = true;
        SyncChild(item, Owner);
        this.PauseSync = false;
    }

    protected abstract void SyncChild(TChild child, TParent parent);
}

public class EmployeeList : BidirectionalAssociationCollection<Employee, Company> {

    public EmployeeList(Company parent) : base(parent) {
    }

    protected override void SyncChild(Employee child, Company parent) {
        child.Employer = parent;
    }
}

You can download the final solution written in C# 3.0 and a Visual Studio 2008 Test project here

Tags: CSharp

All postings/content on this blog are provided "AS IS" with no warranties, and confer no rights. All entries in this blog are my opinion and don't necessarily reflect the opinion of my employer or sponsors. The content on this site is licensed under a Creative Commons Attribution By license.