posts filed under "September 2007 Entries"
(.)

Den Preis für die wahrscheinlich peinlichste Übersetzung ins Deutsche könnte die Deutsche Ausgabe des an sich hervorragenden englischen Originals des Buches von Alex Homer und Dave Sussmann erhalten.

ASP.NET 2.0 Illustrated (Microsoft .NET Development Series)

Im Ernst: Aus Erfahrung kaufe ich in der Regel Fachliteratur in der Sprache der Autoren. Für den Kauf der Lektüre für meinen heute zu ende gegangen Herbsturlaub in der Toscana blieb mir allerdings nicht mehr genug Zeit, so dass ich mit der Deutschen Ausgabe von "ASP.NET 2.0 Illustrated" vorlieb nehmen musste. Mühselig habe ich mich in der vergangenen Woche durch die knapp 600 Seiten gequält und mich dabei an manchen Stellen gefragt, ob das Buch maschinell übersetzt wurde.

Hier ein paar Highlights:

Skins sind steuerelementspezifisch, demnach könnte es für gegebene Designdateien ein separates Skin für jedes Steuerelement innerhalb dieser Designdateien geben.

Wie bitte? Noch schöner wird es hier:

Das Nutzer-Interface ist nicht der einzige Zugang, um sich in eine Seite einzuloggen. Man benötigt auch den Code, der den Nutzer gegenüber der Datenbank für gültig erklärt.

Ob man sich "in eine Seite einlogged" oder eher "an einer Anwendung anmeldet" mag noch Geschmackssache sein, ich habe allerdings in meiner ganzen Entwicklungslaufbahn in noch keinem Projekt einen Benutzer gegenüber einer Datenbank "für gültig" erklärt. (In der Regel gibt es dazu einen Data Layer, der mit dem Benutzer im Internet recht wenig zu tun hat.)

Hier ein weiteres Highlight:

Einer der Bereiche, die Veränderungen im Internet initiieren, sind die Communities. Menschen mögen es, dazuzugehören, und das Internet ist ein großer einsamer Ort.

Man kann den zugrundeliegenden englischen Satz fast herauslesen, so wörtlich wurde hier übersetzt; allerdings funktioniert die Wort-für-Wort Übersetzung im Deutschen nicht mehr - der Charme des Originals geht vollständig verloren.

Wenig später erfahren wir:

Die Nutzerinstanz löst dieses Problem, indem eine Instanz auf Anforderung erstellt wird. Anstatt den Standardnutzer zu benutzen, verwendet eine Nutzerinstanz die Benutzerkennung als Servicekennung. [...] Auch benötigt man für das automatische Anhängen keine zusätzlichen Genehmigungen - der Besitzer des Verfahrens hat automatisch die vollständigen administrativen Rechte bezüglich der Datenbank, auch wenn der Nutzer nicht der Administrator auf dem Rechner ist.

Genau verstanden habe ich das nicht. Anstatt also den Standardnutzer zu benutzen - wofür auch immer der Benutzer benutzt werden soll - wird von der Nutzerinstanz (von wem genau?) die Kennung als Servicekennung verwendet; aha. Vielleicht fragen wir einfach mal den "Besitzer des Verfahrens".. .

Im Kapitel über ASP.NET Steuerelemente lese ich:

Dieses Steuerelement ermöglicht einfaches mehrstufiges aufgabenbasiertes Datensammeln.

Ich bin für kreative Vorschläge was ein "aufgabenbasiertes Datensammeln" ist, jederzeit offen!

Ich könnte mehrere Hundert Zitate anführen, hölzerne Wort-für-Wort Übersetzungen wie die hier aufgeführten finden sich auf nahezu jeder Seite mehrfach. Sie machen das flüssige Lesen des Werkes nahezu unmöglich.

Jedem, der sich mit ASP.NET 2.0 beschäftigt und darüber nachdenkt, ein gutes Fachbuch zum Thema zu kaufen, sei die englische Originalausgabe wärmstens empfohlen. Die Deutsche Ausgabe wandert bei mir direkt ins Kellerarchiv.

 


Neulich trug es sich zu, dass der Mitarbeiter eines Geschäftspartners in einem ganztägig geplanten Kundenmeeting kund tat, er würde sich gerne am frühen Nachmittag ausklinken.

Ins Englische übersetzt bedeutet “Ausklinken” – “Logout”.

Was genau plante der Business Kasper also, als er die Idee seiner arbeitsvertraglichen Verpflichtung auch an einem Freitag acht Stunden zu leisten nicht nachzukommen, damit zum Ausdruck brachte, dass er sich mitten in einem Kundentermin ausloggen würde.

War diese Information wichtig?

 


I recently needed to download Silverlight 1.0 as a binary installer. My machine already had it installed so Microsoft's default Silverlight installation page did not offer me to download the .exe, again. For those who need Silverlight 1.0 installers, this is the direct link, thanks to the official Silverlight forums.

 


Today my installation of the Blend 2 September Preview stopped using Visual Studio 2008 Beta 2 when I select "Edit in Visual Studio..." in the Files palette but instead chose to use Visual Studio 2005. I never had the 2005 version installed on the machine but it came via the SQL Server 2005 Developer Edition install. SQL Server 2005 uses Visual Studio 2005 for its Business Intelligence Development Studio.

Currently Blend 2 does not offer any built-in way to configure which version of Visual Studio should be used. The Blend Configurator tool published by the Expression Blend team does not help with the September preview, even though it shows a success dialog should you run it.

The only working way to force Blend 2 to use VS 2008 Beta 2 again was to completely uninstall all VS 2005 components, the Blend 2 preview, all VS 2008 components and reinstall in the correct order. So I reinstalled

1. SQL Server 2005 (which includes VS 2005 components)

2. Visual Studio 2008 Beta 2

3. Blend 2

It seems as if Blend 2 always uses the version of Visual Studio that has been installed latest. So should you for whatever reason happen to install a VS 2005 component while you already have VS 2008 installed, this is potentially going to break the Blend 2 - VS 2008 integration.

I have posted this to the Silverlight Forums and asked Scott Guthrie to forward this issue to the Blend team. Maybe the final release will give us a nice version selector in the Options section.

 


Recently I complained about the current preview of Expression Blend 2 no longer containing the Fabrikam tutorials, which came with one of the earlier previews. I just noticed that the tutorials have been moved to the Expression Blend's team site. Here they are - enjoy!

 


In the first part of this series I introduced the basic concepts of Subtext skinning which will allow you to accomplish most of the routine tasks required to personalize your blog's look. As said before most design aspects can be achieved by a combination of rearranging custom tags (ASP.NET tags and Subtext tags) in the user controls located in a skin's Controls folder and extensive use of cascading style sheet rules.

While the first part was pretty hands on and there are many great tutorials for topics like CSS and ASP.NET user controls available already, this part will dive a bit deeper into the plumbing and inner workings of Subtext. You don't necessarily need to understand those, to create exciting skins for Subtext, however, I always found it extremely helpful to understand what's going on behind the scenes. At least this provides for a more comfortable feeling when I touch and change parts. It eliminates some of the guessing...

Before we start here is my obligatory note: Currently the official available Subtext documentation is pretty weak. Therefore all of the content I provide in my series is subject to my own research. The ideas I promote might not necessarily be best-practices and chances are that my understanding of Subtext's inner workings might be partially wrong. I encourage all readers to submit their comments to help improve and spread the word!

Prerequisites

To follow along with the contents of this part I'd recommend to download the Subtext solution including the source code. To understand the complete picture we will dive into parts of the Subtext source code. I am currently using Visual Studio 2008 Beta 2 but it is not required to follow my instructions. Feel free to use any other text editor. (The free open source SharpDevelop will be just fine).

Understanding the rendering life-cycle

One of the aspects which many Subtext users who come from a PHP background find difficult is understanding how the final rendering output (the final HTML markup which is send to the browser) gets assembled and which components are involved in the process. This is only partially a Subtext specific issue. It's mainly caused by Microsoft ASP.NET's page request and life-cycle model. Because the ASP.NET way differs quite a bit from those implemented by traditional CGI/scripting solutions like PHP it might take a bit of time until you get familiar with it and recognize it's many great benefits.

Let's get hands on!

While you might have come to my blog through a direct link to any of my Subtext articles, the default location to access this blog is http://www.talentgrouplabs.com/blog/.

Standard ASP.NET looks for a file named default.aspx (not case sensitive) and there is a default.apsx file in the root of your Subtext installation. However, if you open that file you will most likely find default content written by the Subtext project lead Phil Haack and not any placeholders which would be replaced by your blog posts. Welcome to the ASP.NET world!

So what's going on when somebody visits the main URL of a Subtext blog?

The secret is in Web.config (located in your Subtext root directory). First of all, the following line

image

defines DTP.aspx as the default page for your blog. (Note: HandlerConfiguration is not a standard ASP.NET element - it refers to the HandlerConfiguration type in the Subtext.Framework.UrlManager namespace.)

Setting the defaultPageLocation to DTP.aspx defines this file as being the default template for all of your Subtext pages. If you for example would like to add meta tags to every of your blog pages, this is the place you were looking for. Future versions of Subtext might provide a means to set meta tags via the admin control panel - today except for the "author" meta tag you would have to add them manually to the DTP.aspx default template. I added a couple of meta tags to my DTP.aspx:

image

Scroll a bit further down and you might be surprised there's not too much else in the default template. The <body> tag comprises just a couple of lines:

image

The key here is that at runtime the <asp:PlaceHolder> will be replaced by the actual body content. But how does Subtext determine what to replace the placeholder with? Again the answer lays in Web.config. The last <HttpHandler> element in Web.config defines the control which will be used to replace the placeholder if a request for default.aspx is recognized:

image

Subtext will replace the placeholder in DTP.aspx with the contents of the homepage.ascx, another control in the Controls folder of your skin directory. This is a pretty powerful mechanism and Subtext makes a lot of use of it. It also facilitates the ability to further extend Subtext in future releases.

Let's investigate another example: If you navigate to http://www.talentgrouplabs.com/blog/tags/ you will get a full tag cloud of my blog. A quick look into Web.config reveals the control which is used:

image

Control deep diving

Before we move on, let's recap:

DTP.aspx is the default template as defined via the defaultPageLocation attribute of the HandlerConfiguration element in Web.config. While DTP.aspx provides the <head> section of the final document the main contents will be rendered by user controls. The first user control is again configured on a per URL pattern base in Web.config. For the main URL of a Subtext blog (the implicit /default.aspx page) it's the homepage.ascx user control which renders the home page contents.

Open the file HomePage.ascx in your skin's Controls directory. Here's mine:

image

Hmm. Seems as if the HomePage.ascx control is just there to include yet another user control: DayCollection.ascx. Before we look into DayCollection.ascx let's stick for a minute with HomePage.ascx. Looking into the .ascx file does not reveal the full user control story, though. Take a second look and you'll find out that HomePage.ascx extends a base control defined as part of the Subtext system controls:

image

ASP.NET brings object oriented programing concepts to the web world. User controls can be based on other controls, inherit their behavior and extend it. In order to find out the implementation of the base control (Subtext.Web.UI.Controls.HomePage) you do need to download the Subtext distribution including the source code.

If you've opened up the Visual Studio solution file (SubtextSolution.sln) use your IDE of choice to navigate to the Homepage.cs file, which is the C# source code file from which the concrete HomePage.ascx residing in your skin's directory derives. For your convenience here is an excerpt of Homepage.cs:

image 

While the HomePage.ascx seems to just include the DayCollection.ascx user control from this source code snippet you learn that the base user control does some initializing work once the control is loaded (the initialization is hooked to the OnLoad event). Via some helper classes this control finally calls the GetBlogPosts() method to read the posts to be rendered on the homepage from the database.

In the next part of this series we move on with our journey and learn how the DayCollections.ascx with the help of yet some other user controls renders the list of posts. We will learn about ASP.NET Repeaters and understand how they get bound to Subtext content.

Stay tuned!

A remark on Subtext MasterPages

While you investigate Subtext you occasionally might run into the term "Master Page". This can be quite confusing as the concept of Master Pages was officially introduced with ASP.NET version 2.0. The current version (1.9.5) of Subtext does not make use of the ASP.NET 2.0 Master Page concept. In fact the lack of a generic Master Page / Template concept in ASP.NET 1.0 has often been criticized. As Subtext also runs on older versions than ASP.NET 2.0 it implements its own Master Page concept from scratch. (Well, not entirely from scratch but based on Paul Wilson's excellent demo.) So whenever you read about Subtext and Master Pages bear in mind it's not ASP.NET 2.0 Master Pages, yet.

 


Auf der offiziellen Website der jüngst selbst in Verdacht geratenen McCanns findet sich seit Kurzem folgender Hinweis des National Center for Missing and Exploited Children:

The advice of the National Center for Missing and Exploited Children is that high visibility of a missing child through posters, car stickers etc increases the chances of finding that child. The friends and family of Kate and Gerry urge everyone to please keep looking for Madeleine. Our greatest fear has always been that Madeleine would somehow be forgotten about and that our efforts to bring her back safely would run out of support. We know in our hearts that Madeleine is still out there, alive, confused and aching to be returned to her family where she belongs. Whatever happens, please don't forget that. Don't forget about Madeleine.

Damit möchten die McCanns wahrscheinlich dem Eindruck mancher Beobachter, Art und Umfang öffentlichkeitswirksamer Auftritte der McCanns wären ungewöhnlich übertrieben, entgegentreten. So war die Familie nach dem Verschwinden Madeleines zu einer bislang beispiellosen Reise durch Europa angetreten, bei derem Höhepunkt sie unter anderem Papst Benedikt besuchte.

Die Empfehlungen des National Center for Missing and Exploited Children sind sicherlich uneingeschränkt nachvollziehbar. Warum aber glaubt Familie McCann sie müsse sich für den Webauftritt überhaupt rechtfertigen?

Vielleicht liegt es daran, dass den geneigten Besucher die Aufklärungsaktivitäten rund um das sehr persönliche Blog von Gregg McCann in Teilen eher wie eine gekonnte PR Aktion anmuten, als der Hilferuf verzweifelter Eltern.

Zugegeben, das Thema ist brisant und niemand möchte an Stelle der Eltern treten, trotzdem darf es erlaubt sein zu fragen, wie beispielsweise der reißerisch aufgemachte Verkauf von Madeleine Armbändern das Auffinden des Kindes fördert:

image

Die Freude des Shopbetreibers unter http://store.findmadeleine.com/ über den aktuellen "Best Selling Item" mag man so recht nicht teilen:

image

Der eigene Wiki-Eintrag hält sich recht nüchtern an die Fakten, die über die öffentliche Berichterstattung jedermann zugänglich sind. Die gesponserten Links von Google

image

wiederum demonstrieren wie unsensibel die Algorithmen des Werbegiganten sich unter Umständen zeigen. Eine einfache Suche nach "Madeleine" führt zu folgendem Ergebnis:

image

Um jedem Mißverständnis vorzubeugen: Um Opfer eines Verbrechens zu helfen und erst Recht, wenn es sich dabei um Kinder handelt, ist jedes Mittel Recht. Ob Wallpaper für den Desktop und ein Internet Shop mit Madeleine Armbändern allerdings nützlich sind, oder eher vom Wesentlichen ablenken, sei dahingestellt.

image

Das aktuelle Zitat des NCMEC auf der Website der McCanns jedoch deutet zumindest darauf hin, dass die Frage nach der Angemesenheit der gewählten Mitteln durchaus auch anderenorts gestellt wird.

Luis Alves hat es wahrscheinlich am Besten auf den Punkt gebracht, in seinem Feedback zu Daniel Finkelsteins's hervorragendem Kommentar in der Times Online:

We are all detectives merely because we have been spoon-fed this entire circus from the beginning.

It is a grim soap opera, played out to the gratification of a voyueristic world!
It is no longer a case about a missing child..in fact, madeline has taken a back seat...noticeably because her parents are now the 'Hot News' story!

The website just seems like a shopping channel too....with this 'Buy a Bangle'

Quite revolting!

 

tags: ,

Jetzt ist es also "offiziell": Ein kostenfreier, rein Software basierter "Hack" zur Entsperrung des NetLocks des iPhones ist frei verfügbar und wurde ausführlich getestet. Interessant an dieser Meldung ist insbesondere, dass das Wettrennen der "Community" gegen die durchaus zweifelhaften Interessen eines Konzerns wieder einmal von der Community gewonnen wurde.

Interessant ist auch, dass es offensichtlich selbst Apple schwer fällt, sichere Sicherheitsverfahren in die eigenen Geräte einzubauen, die nicht innerhalb kürzester Zeit ausgehebelt werden können. Ein universelles Problem, für das es noch keine universelle Antwort gibt.

 


Microsoft's Windows Live Messenger (WLM) - formerly known as MSN Messenger - is pretty popular (over 280 million accounts using it). Recently I looked into ways to extend its functionality. While I know Microsoft as being extremely good in evangelizing developers I was surprised that a prominent application like WLM is supported so poorly.

For example the last post related to extending WLM on the team blog has been published long time ago. The two primary SDKs (WLM Activity SDK and the WLM Add-In API) currently only provide a hand full of methods and due to security constraints (they run in a sandbox or your code needs to be certified by Microsoft) fail to help you implement the most common extensions. By the way: An attempt to contact Microsoft to discuss details about the certification of a custom WLM Activity failed - the mail I've sent to their alias never got responded.

I always wondered that given the enormous reach of Windows Live Messenger, why there is no vital third party and open source community providing rich extensions. The lack of a good developer support might be the explanation.

 


Last year Technorati introduced the Link Count Widget which provides the ability to add a link to your blog's posts which dynamically indicates how many other (Technorati listed) blogs link back to each of your own posts.

By simply adding two lines of HTML and JavaScript markup you would end up indicating links to your posts like that:

image

I could not find any prepared code for Subtext on the Technorati website, so I had to do it myself.

So if you want to show Technorati blog reactions with your posts, here is what you could do:

I assume that your homepage uses the Day.ascx user control to render individual posts and all other lists user ViewPost.ascx. Because Day.ascx makes use of an ASP.NET Repeater the mechanisms are slightly different.

Please note that the code markup below might display line breaks when viewed in a browser. Unless explicitly indicated there are obviously no line breaks in the middle of any code.

Day.ascx

In Day.ascx wherever you want to display the Technorati blog reactions link add the following markup:

 1: <script src="http://embed.technorati.com/linkcount" type="text/javascript"></script>
 2: <a class="tr-linkcount" href="http://technorati.com/search/<%= Config.CurrentBlog.Host %><%# DataBinder.Eval(Container.DataItem, "url") %>">
 3: View blog reactions</a>

Essentially this links back to the Technorati URL http://technorati.com/search/ and adds the hostname of your blog (Config.CurrentBlog.Host) without the preceding "www" and the friendly URL of the current post (DataBinder.Eval(Container.Datatem, "url")).

Please note that in order to use Config.CurrentBlog.Host you've got to register the appropriate namespace within the user control. Simply add the following ASP.NET directive below the last Register directive in Day.ascx:

 1: <%@ Import namespace="Subtext.Framework.Configuration" %>

ViewPost.ascx

This user control is a bit more straight forward as we are not bound to the context of an ASP.NET Repeater. Let's first add the Subtext.Framework.Configuration namespace as we did for Day.ascx, too:

 1: <%@ Import namespace="Subtext.Framework.Configuration" %>
 
Wherever you want the Technorati blog reactions link, add the following piece of code:
 1: <script src="http://embed.technorati.com/linkcount" type="text/javascript"></script>
 2: <a class="tr-linkcount" href="http://technorati.com/search/<%= Config.CurrentBlog.Host %>

      
 3: <%= this.TitleUrl.NavigateUrl %>"
>View blog reactions</a>
That's it!

A behind the scenes note

What does the DataBinder.Eval(Container.DataItem, "url") in Day.ascx do, and why do we have to use it? The Day user control uses an ASP.NET Repeater to iterate through the elements of a list. ASP.NET Repeaters make use of data binding in order to bind a set of data to a collection. The Repeater iterates through the bound data. The previous statement uses reflection to resolve the value of the "Url" field bound to the Repeater. In case you downloaded the source code of Subtext, you can take a look at Entry.cs to find other helpful fields which you can evaluate, like Title, Id and FeedBackCount.

Note: I am pretty new to Subtext and there might be a much easier way to accomplish the same. If you know about a more elegant way, feel free to comment!

 

 


I have been playing with "content publishing" engines for a couple of years. Most of them were based on the LAMP technology stack: Linux, Apache, MySQL and PHP. My personal blog has been driven by Textpattern for over a year and my teams has used the Exponent Content Management System to create websites and allow customers to change content on the fly.

In my professional life I am in charge of designing standard software solutions for large enterprises and almost solely deal with .NET and Java. Therefore it's only been a matter of time and I recently migrated my blog to a more robust stack which also allows me to extend it using C#.

After conducting some research I decided to go for Subtext, a free open-source blogging engine written to run on Microsoft Internet Information Server and currently supporting ASP.NET 2.0. Subtext installation worked like a charm, following the simple installation steps provided in the online docs. Working with Subtext was pure fun from installation, via customization to publishing my first post via Windows Live Writer. From my personal perception Subtext is better than all other engines I have been using so far. It's speedy, it's clean and because it's ASP.NET it can be easily extended.

The only thing that is currently behind is the available documentation. This, however, is a real problem when you want to start skinning Subtext to give your blog a personal look. In addition the programing model of ASP.NET is very different from PHP so it's not all that easy to intuitively gather the big picture.

While I can in no way provide a full Subtext documentation, I decided to post my experiences during the creation of the skin you're currently watching (unless you read through a syndication service). Please note that the content which follows might contain errors or misconceptions and should not be considered as official Subtext documentation. It's provided "as is" and hopefully gets you started.

Before we start a word on tools: I am using Dreamweaver CS3 for most of my web design work so most of the screenshots depict Dreamweaver in action. Feel free to use your tool of choice! Along with Dreamweaver I heavily use Firebug, a plug-in for the Firefox browser which lets you inspect any HTML document. I highly recommend to get Firefox and Firebug before you start creating your own skins.

This introduction is based on the current version of Subtext which is 1.9.5.

Phil Haack project lead for Subtext has a good introductory post about Subtext skinning which you might want to read first. Let's recap the essentials:

  • Subtext skins are stored in the Skins folder. A sub folder in Skins points to a group of similar skins (called skin templates) not to a single skin.
  • Subtext uses the Skins.config file in the Admin folder in order to get the list of skins from which you can then select in your blog's control panel.

To create your own skin and learn the details of Subtext skinning I highly recommend to not start with any other skin than the "Naked" one, which comes with Subtext. The "Naked" skin essentially is a skin which is not styled in any way but implements most of Subtext's features. It also comes with an almost empty style sheet which you will customize heavily to give your blog an individual look and feel. By the way: While other blogging engines might require massive changes and rearrangement of (PHP) code, lots of things in Subtext can be done purely by using CSS. For almost all parts of the content Subtext provides CSS class or ID wrappers, so before you might want to touch ASP.NET code, double-check whether what you want cannot be achieved via CSS!

Creating a new skin

Start implementing your own skin by creating a new folder in the Skins folder and giving it a unique name. For this blog I have named the folder 24100. Copy the entire contents from Skins/Naked into the newly created folder. After this step your folders should look similar to this:

image

In the next step open the Skins.config file from the Admin folder. Anywhere within the <Skins> element add the following XML:

<Skins>
<SkinTemplate Name="24100.net" TemplateFolder="24100">
 <Styles>
 <Style href="~/skins/_System/commonstyle.css" />
 <Style href="~/skins/_System/commonlayout.css" />
 <Style href="style.css" />
 </Styles>
</SkinTemplate>

I simply copied the XML from the definition of the Naked skin within Skins.config and just changed the name and TemplateFolder attributes of the SkinTemplate element. Note: It is not important where in Skins.config you put the definition of your new skin as long as it is a direct child of the <Skins> element. Subtext's control panel lists the skins in order of their appearance inside Skins.config so I added mine to the top.

The above XML snippet tells Subtext that the files for your new skin with the name 24100.net reside in the Skins/24100 folder. In addition when Subtext renders this skin, it'll automatically generate <link> tags including two system CSS files (commonstyle.css and commonlayout.css) and the style.css which is inside the Skins/24100 folder. The style.css is where you will apply most of the modifications.

In the Configure section of the Subtext control panel Options menu activate your newly created skin:

image

Navigate to your blog. What you will see is an almost completely "unstyled" version of your blog. This is why the skin from which we created the copy is named Naked, I guess.

 

Understanding the base structure

The Web.config file

Before we move along let's dive a bit into the structure of a Subtext skin. Understanding the "execution chain" during rendering will later help us to quickly find components which we have to touch to achieve a specific look.

IIS and ASP.NET handle requests quite differently from the Apache and PHP stack. One thing to understand is that the URL's which get requested can be mapped to pages and handlers in arbitrary folders via the Web.config file in Subtext's root folder. I recommend to take a closer look at Web.config, more specifically to the <HandlerConfiguration> section.

One of the problems I faced was that at the time of this writing there was no complete overview as to which "part" of Subtext renders what. For example, to me it was not intuitively clear what gets rendered if a visitor selects the "Archives" link. The handler configuration inside Web.config is a good place to look for answers. To stick with the "Archives" example, in Web.config you find the following line:

<HttpHandler pattern="(?:/archives\.aspx)$" controls="SingleColumn.ascx"/>
 
Without getting into the details of ASP.NET handler configuration what this line does is, it instructs ASP.NET to use the SingleColumn.ascx control whenever a page with the .aspx extension in a archives folder is requested. SingleColumn.ascx is an ASP.NET user control. User controls are reusable components which can be embedded as a custom tag into an ASP.NET page in order to render parts of a page. A brief but clear introduction can be found here. (By the way: The SingleColumn.ascx user control sits within the Controls folder of your skin. Do not open it at this point as it is a pretty disappointing user control which just embeds yet another user control.)
 
Note: Should your Web.config file not contain the above HttpHandler configuration, chances are you did not open the Web.config file in the root folder of your Subtext installation. In fact ASP.NET allows Web.config files in every folder of an ASP.NET application and Subtext has various Web.config files in sub folders. Make sure you take the one in Subtext's root for the overall HttpHandler configuration lookup!

The PageTemplate.ascx user control

At the heart of every skin is the PageTemplate user control. Open the PageTemplate.ascx file in your skins root folder (Skins/24100). At the beginning of the user control you'll find a couple of Register directives. These directives instruct ASP.NET to recognize custom tags within the following markup and also configures which user controls will be used to generate the output which gets rendered where the custom tag is placed.

If you've followed these instructions you'll see that the following 10 user controls get registered:

<%@ Register TagPrefix="DT" Namespace="Subtext.Web.UI.WebControls" Assembly="Subtext.Web" %> 
<%@ Register TagPrefix="uc1" TagName="Header" Src="Controls/Header.ascx" %>
<%@ Register TagPrefix="uc1" TagName="Footer" Src="Controls/Footer.ascx" %>
<%@ Register TagPrefix="uc1" TagName="News" Src="Controls/News.ascx" %>
<%@ Register TagPrefix="uc1" TagName="SingleColumn" Src="Controls/SingleColumn.ascx" %>
<%@ Register TagPrefix="uc1" TagName="BlogStats" Src="Controls/BlogStats.ascx" %>
<%@ Register TagPrefix="uc1" TagName="MyLinks" Src="Controls/MyLinks.ascx" %>
<%@ Register TagPrefix="uc1" TagName="RecentComments" Src="Controls/RecentComments.ascx" %>
<%@ Register TagPrefix="uc1" TagName="RecentPosts" Src="Controls/RecentPosts.ascx" %>
<%@ Register TagPrefix="uc1" TagName="TagCloud" Src="Controls/TagCloud.ascx" %>
<%@ Register TagPrefix="uc1" TagName="SubtextSearch" Src="Controls/SubtextSearch.ascx" %>
 
So, for example whenever the following tag is rendered
 
<uc1:header id="Header1" runat="server" />

the Header.ascx control in Skins/24100/Controls will be executed.

If you open Skins/24100/Controls/Header.ascx you'll find the following markup:

<%@ Control Language="C#" EnableTheming="false" Inherits="Subtext.Web.UI.Controls.Header" %>
<%@ Register TagPrefix="uc1" TagName="SubtextSearch" Src="SubtextSearch.ascx" %>
 
<div class="title">
 <asp:HyperLink id="HeaderTitle" runat="server" />
</div>
<div class="subtitle">
 <asp:Literal id="HeaderSubTitle" runat="server" />
</div>
<uc1:SubtextSearch id="search" runat="server" />

So effectively the <uc1:header> custom tag will end up being rendered into three HTML <div> tags and yet another user control, the SubtextSearch.ascx.

You might think this is way overcomplicated but you will quickly recognize the beauty of this approach. It promotes reusability and a breaks your design into discrete components which drive maintainability of your code!

The main Cascading Style Sheet

The next thing you would like to inspect is the style.css file in your skins root directory. If you started based on the "Naked" skin it'll contain lots of empty selectors and a float:right directive for the #navigation ID selector.

You don't need to go through all the styles at this moment, just keep in mind that most of the customization can be achieved by defining CSS rules within this file. With that said, let's start customizing our skin!

Let the customizing begin

In case you're reading this post from my blog you see that my skin displays an image at the very top, sometimes called a header image:

image

I recommend to you to follow the next steps carefully. In fact I used this method over and over again with existing Subtext driven blogs in order to understand the structure of a Subtext blog better. I can not emphasize enough how much you learn from investigating what others have done before you!

1. Open my blog in Firefox and activate Firebug via Tools > Firebug > Open Firebug.

2. Select the Inspect button on Firebugs toolbar:

image

Once you've activated the Inspect mode Firebug allows you to mouse over the current web page and while you do so it puts a blue frame around distinct elements of the DOM tree. At the same time it highlights the underlying HTML code which created a specific DOM element. If you navigate to my blog's header image Firebug reveals that it is rendered via the <div> tag with the element ID "header":

image

So how did I achieve this? And what happened to the SubtextSearch user control which we saw in the Header.ascx a moment ago?

Well, it turns out that I customized the skin to create this effect. Let's review step by step:

First I opened Skins/24100/Controls/Header.ascx knowing that this user control will render the header of any of my blog's pages. (Please note: By writing "header" I do not refer to the <head> part of the HTML markup. There currently is no easy way to change the way this part gets rendered in Subtext.)

I deleted everything from Header.ascx except the first line. So the final version of my Header.ascx looks like this:

<%@ Control Language="C#" EnableTheming="false" Inherits="Subtext.Web.UI.Controls.Header" %>

Recall that in PageTemplate.ascx the header user control is rendered in between <div> tags with the "header" ID:

<div id="header">
 <uc1:header id="Header1" runat="server" />
</div>

With Header.ascx no longer outputting anything the final markup will only contain a <div id="header"> HTML tag. (Subtext is smart enough to omit a second closing </div> statement and generate the short form automatically.)

The final step to show my header image is to define the CSS rules in style.css for the header ID:

#header
{
 background-image:url(Images/header.jpg);
 height: 94px;
 border: 5px solid #fff;
}

With this done, all my pages will now show header.jpg at the very top.

Note: If you take a closer look at PageTemplate.ascx you'll notice that the entire content is wrapped by a <div> tag with the "container" ID. The next thing you would like to do is set some general CSS rules for this tag. For example in my skin the #container rules are as follows:

#container
{
 text-align: left;
 width: 934px;
 background-color: #fff;
 margin-top: 0px;
 margin-right: auto;
 margin-bottom: 0px;
 margin-left: auto;
 border: 1px solid #000;
}

The most important ones are defining the overall width of everything inside the container as being 934px and by setting margin-right and margin-left to auto centering the container on the page. My header.jpg image is 934px wide so everything aligns nicely.

At this point I'd like to encourage you to investigate the <div id="navigation"> section by yourself. Note how the

<uc1:mylinks id="MyLinks1" runat="server" />
<uc1:blogstats id="BlogStats1" runat="server" />
<uc1:news id="News1" runat="server" />
<uc1:RecentComments id="RecentComments1" runat="server" />
<uc1:RecentPosts id="RecentPosts1" runat="server" />
<uc1:singlecolumn id="SingleColumn1" runat="server" />
<uc1:TagCloud ID="tagCloud" runat="server" ItemCount="20" />

custom tags in PageTemplate.ascx correspond to the actual .ascx files in Skins/24100/Controls as registered at the beginning of PageTemplate.ascx. Feel free to open the corresponding .ascx controls and compare to what Firebug shows you until you get a pretty good feeling of what gets rendered and why.

This is it for the first part of this post. I am planning to write the second part Thursday evening, so stay tuned for more on Subtext skinning. In the next part we will focus on the <dt:contentregion id="MPMain" runat="server" /> section of PageTemplate.ascx, further style the skin and explain some more complex concepts of Subtext.

Any feedback is very welcomed!

 

tags: , , ,

Dieser Artikel ist eine freie Übersetzung meines ursprünglich in englischer Sprache verfassten Berichtes über die schlechte Kundenservice-Erfahrung mit T-Mobile Deutschland. Aufgrund des überwältigenden Feedbacks, dass ich unter anderem von zahlreichen Betroffenen in Deutschland erhalten habe, erscheint der Artikel nun auch in der deutschen Fassung.

T-Mobile Deutschland verkauft wie viele andere Mobilfunkanbieter weltweit PCMCIA Datenkarten als OEM Produkte der Option Wireless Technology um Nutzern mobilen Highspeed Zugriff ins Internet via UMTS und GPRS zu ermöglichen.

T-Mobile Data Card - Not working in Windows Vista, yet...

Telcos sind nicht gerade bekannt dafür, schnell auf sich verändernde Märkte zu reagieren und so gibt es für Windows Vista zurzeit keine Treiber für die PCMCIA Karte, die sich im Gerätemanager als Fusion UMTS GPRS WLAN – 3G Modem identifiziert.

Dies ist insbesondere deshalb sehr ärgerlich, weil Microsoft seit über 18 Monaten das Technology Adaption Program (TAP) für Windows Vista promotet – Zeit genug also, um die eigene Software einem sorgfältigen Check zu unterziehen.

Während der Kundenservice versucht die Schuld auf Microsoft zu schieben – vollkommener Unsinn, den Microsoft hat noch nie Treiber für Fremdhersteller selbst produziert – ist dies kein reines T-Mobile Problem. Auf der ganzen Welt suchen Mobile Worker bereits seit einiger Zeit nach einer Lösung. Spuren finden sich in zahlreichen Foren.

Weil auch ich von dem exakt gleichen Problem betroffen bin, habe ich den Hardware Hersteller- Option – direkt kontaktiert.

Während die E-Mail an den T-Mobile Deutschland Geschäftskunden-Support nach 48 Stunden noch immer auf ein Lebenszeichen wartet, antwortete Option Wireless Technology innerhalb von fünf Stunden. (Vielleicht sollte jemand bei T-Mobile einmal generell darüber nachdenken, wie mit Kunden umgegangen wird, aber das ist eine andere Geschichte.)

Option’s Antwort brachte leider auch keine Lösung, allerdings einige Hinweise auf den Stand der Dinge:

Hier ist die übersetzte Antwort von Option:

Sehr geehrte Damen und Herren,

Technischer Support und Treiber für Ihre Karte müssen tatsächlich über T-Mobile erfolgen. Wir können Ihnen allerdings mitteilen, dass Vista Treiber während wir Ihnen diese Antwort schreiben WHQL’ed und released werden.

Sehr bald präsentieren wir die Treiber allen Mobilfunkanbietern (inklusive T-Mobile Deutschland) die dann entscheiden, ob sie ihren jeweiligen Kunden zur Verfügung gestellt werden.

Da Ihre Karte ein OEM Produkt ist, können wir Ihnen nicht direkt helfen. Es ist eine Vorschrift bei Option, keine beta Treiber an Kunden auszuhändigen.

Mit den besten Grüßen

Nadim Saeed
OPTION Wireless Technology
Customer Support

Nun, ich hoffe T-Mobile gibt die Treiber möglichst bald weiter. Ansonsten muss sich mein Unternehmen nach einem alternativen Provider für mobile Datendienste umsehen.

Update 13. Januar 2007

In der Zwischenzeit sind einige E-Mails von T-Mobile eingetroffen.

In der ersten E-Mail wurde behauptet, man habe die hauseigene Software erfolgreich unter Windows Vista getestet. Dennoch habe man mir freundlicherweise eine Word-Datei angehängt, die beschreibt, wie man manuell eine Verbindung herstellt – unter Windows XP ServicePack 2. Ich antwortete, dass die T-Mobile Treiber definitiv nicht unter Windows Vista RTM (Release to Manufacturing) funktionieren. Einige Tage später gab man dann zu, dass die hausinternen Tests wohl mit Windows Vista Release Candidate 1 durchgeführt wurden. Nun, im RC 1 war die Treiberarchitektur natürlich nicht das, was sie heute in Windows Vista ist.

Zurzeit lautet die unschöne endgültige Antwort von T-Mobile also, dass die Treiber auf der T-Mobile Homepage zum Download angeboten werden, wenn sie verfügbar sind. Wann dies der Fall sein wird, möchte mir niemand verraten.

Warten wir weiter – es ist bereits jetzt eine Schande für T-Mobile.

Update 24. Januar, 2007

Eine neue E-Mail von T-Mobile. Es gibt gute Nachrichten: Zur Verfügbarkeit von Treibern für Windows Vista äußert sich T-Mobile auf der CeBIT im März 2007. Nein, ich scherze nicht. Windows Vista wird am 30. Januar ausgeliefert und T-Mobile hat keine bessere Antwort, als zwei Monate zu warten bis sie ihren Kunden wieder erlaubt, das mobile Internet zu nutzen. Das Drama geht weiter!

 

tags: , , ,

I have spent a couple of nights and weekends to migrate my blog away from