August 29, 2003
@ 01:38 AM

With TechEd Malaysia done, Patricia and I now have a bit more than 2 weeks of vacation! Today we fly to Saigon (Vietnam) and tomorrow from there for 4 days to Siem Reap (Cambodia) to see the temples of the sunken capital of the Khmer empire in Angkor. Then we’ll fly back to Thailand to spend 1 ½ weeks in a beach resort and finally we fly home after another one night stop in Bangkok. This is going to be great fun.

Categories: Other Stuff

Although we had an excessive first night here in Kuala Lumpur (getting strangers drunk on arrival seems to be some sort of tradition around here), that wasn't the reason for me showing up 15 minutes late for my first talk about "Building Distributed .NET Applications" this morning at 9:00am (then 9:15am) here at TechEd Malaysia. The notification about session slot change somehow either just didn't find its way into my inbox or it fell victim to the Sobig.F mail sweeping. Whatever happened... it seems all people in a full room did indeed patiently wait for me while I rushed from the hotel to the session room. Thank you! Being late to a session at a conference was definitely a (bad) "first" for me and is doubleplusungood to happen to a German. The session ended up going really well and I will post the related samples tomorrow together with the sample for the session on aspects.

The second session was a fun chalk talk with Tim Huckaby about the same topic area. As the lead example for a loosely-coupled, distributed system I used dasBlog and its interactions with other blog engines and moved on to explain how the architectural mesaures taken there could be used for more "traditional" enterprise software scenarios. Core message: asynchronous is good!

Categories: TechEd Malaysia

August 21, 2003
@ 12:15 PM

The Sobig.F worm is hitting massively. My inbox. While we have all shields up at newtelligence for virus-protection, a bunch of people who have my email in their contacts obviously don't. Since yesterday evening I had to clean out at least 300-400 mails from my inbox that were generated by the worm. By average, I am currently getting a (formerly, pre-scan) infected email every 4-5 minutes. It's f***ing annoying.

Categories: Other Stuff

August 20, 2003
@ 01:43 PM

While I wasn't looking, Doug Purdy, who is the PM for the team in charge of the XmlSerializer has posted this little cryptic answer to my initial question:

String serializedDateTime = XmlConvert.ToString( someDateTime );

DateTime deserializedDateTime = XmlConvert.ToDateTime( serializedDateTime );

What Doug is showing is really what the serializer is doing with dates under the hood and that I am incorrectly blaming the XmlSerializer for the lack of UTC support. [XmlConvert.ToString() also does nothing more than calling DateTime.ToString() with the appropriate format string]. As I was already saying in yesterday's post, but what I want to make a bit clearer here again is that the actual problem is the lack of time-zone awareness in DateTime.

So the proper thing more me to do is to ask the base-class library team for time-zone support in the base-class library for Whidbey so that Doug can fix this for us ;)

Categories: XML | CLR

August 19, 2003
@ 06:41 PM

I posted a little question here, just asking "Why?". For your reading convenience, I pull the code in here once more:

DateTime issued;

[XmlIgnore]
public DateTime IssuedUtc
{ get { return issued; } set { issued = value; } }

[XmlElement("issued")]
public DateTime IssuedLocalTime
{ get { return Issued.ToLocalTime(); } set { Issued = value.ToUniversalTime(); } }

So, indeed, why am I doing this? Well, when I decided to normalize all times handled by the backend engine of dasBlog into the UTC timezone, I really didn't think of the XML Serializer being a problem at first. It turned out to be one.

The reason why I wanted all times to be handled internally as UTC is quite simple: Too many time zones to deal with and I need to have a proper reference to do forward and backward time calculations. dasBlog deals with four time-zones:

  • "Reader Time": The "<%userWhen%> macro emits a block of script that will cause the browser to emit the time of a post local to the reader's time zone. That one is easy, because the calculation happens on the client, but I need to feed it UTC (GMT).
  • "Display Time": This is the time zone the blog owner selects for his/her blog. All times displayed on the weblog pages are shown in that time zone (complete with the TZ name and the GMT offset). This also applies to the "admin pages" such as referrals and events (which both roll over in synch with the display time zone). Display time is calculated dynamically and you will notice that it also automatically adjusts for daylight savings time. The display time zone is also by no means fixed. If the blog author travels (and you will see this on my blog starting next week), he/she can adjust the blog to his/her present time zone. When I am going to be at TechEd Malaysia, my blog will show UTC+0800. To make this time-zone shifting work, the absolute time must be stored in UTC.
  • "Engine Time": This is UTC. All of the dasBlog runtime handles everything in UTC.
  • "Server Time": Now were getting to the point. The engine runs on a server that has it's own local time zone setting: "server local time". That's something that the user who's running his engine at some ISP can't control and that's the one of all the time zones that really nobody is ever interested in. You shouldn't care whether your blog is hosted in Germany, the U.S. East Coast or Singapore. That's even more of an issue because one could expect that hosted sites may get moved around between ISP locations. The only little thing we're interested in is that the server knows its offset to UTC.

So ... I was thinking.... ask for DateTime.Now.ToUniversalTime(), handle everything in UTC from there on and everything's good. (Btw, I know about DateTime.UtcNow, but I like the expressiveness of this better).

What I wasn't considering is the way the XmlSerializer works, which I am using both for storage and for the various web services (including the Atom feed). What I also found is that the DateTime class in the framework isn't time-zone aware.

The workaround above is used because the XML Serialization infrastructure always assumes local time ("Server time") for serialization and will always emit ISO 8601 dates with a time-zone suffix like this: 2003-08-19T15:15:58.0781250+02:00. So when you are handling UTC times internally and use them blindly with XML serialization for both storage and web services, the serializer will assume you are using local time and throw you off by your own time-zone difference to UTC.

This isn't "too bad" when you store stuff in local XML files, because when you write something wrong from the same place you read it back into and your time-zones don't change you are in ok in memory, but you are nevertheless wrong on disk. What happened to me in dasBlog version 1.1 was that I was thinking that I stored UTC, but in fact I stored everything in local time. My UTC time 2003-08-19T15:15:58 always turned into 2003-08-19T15:15:58+02:00, because the DateTime class doesn't keep time-zone information around that the serializer could use. Therefore the serializer must always assume local time and that causes the offset to be emitted. That's of course much worse for UTC+12.

The fix:

The field  DateTime issued; holds the "engine time", which is always UTC. 

The property

[XmlIgnore]
public DateTime IssuedUtc
{ get { return issued; } set { issued = value; } }

wraps this value and is the property that the engine works with internally. The XmlSerializer is instructed to ignore this value in the serialization process by declaration of the [XmlIgnore] attribute. Instead, we tell the serializer to look at the following property, which is not used by the engine itself and also indicates that by its name suffix "LocalTime", which essentially declares it as "off limits" for direct access to everyone knowing the project:


[XmlElement("issued")]
public DateTime IssuedLocalTime
{ get { return Issued.ToLocalTime(); } set { Issued = value.ToUniversalTime(); } }

This property is the one that the serializer grabs and it does the proper conversion to and from server local time that the serializer requires. The actual dasBlog code is using a variant of this property that is a bit larger in code size because it also checks for DateTime.MinValue and DateTime.MaxValue occurrences, which, depending on the server time zone, would cause the time zone shifting to fail with an overflow/underflow exception (and no, I am not checking near MinValue and MaxValue):

[XmlElement("Date")]
public DateTime DateLocalTime
{
   
get
    {
      
return (DateUtc==DateTime.MinValue||DateUtc==DateTime.MaxValue)?
               DateUtc:DateUtc.ToLocalTime();
    }
   
set
    {
        DateUtc = (
value==DateTime.MinValue||value==DateTime.MaxValue)?
                  value
:value.Date.ToUniversalTime();
    }
}

So, that's why.

Be aware that all of this applies to ASP.NET Web Services, too, and if you are dealing with multiple time zones are you are using UTC normalized times in your app, you will have to deal with this. If "server time" makes you happy, you won't need to worry.

Categories: XML | CLR

Ok, I couldn't resist getting the Arabic support (mostly) right. Malek helped me and by what he tells me, we've succeeded mostly. There are a few things left to do around wildly wrapping symbol characters, but that'll be worked out eventually.

So, this little patch updates dasBlog with French, Russian and Arabic, including full right-to-left reading support, which the engine injects appropriately into the <body> tag (dir="RTL") based on a hint in the Arabic resource table.

Categories: dasBlog

August 18, 2003
@ 10:28 PM

On the download site I posted add-on packs for French language support and the first steps toward Arabic language support, which are the string tables. My friend Malek Kemmou from Morocco wants to help me figuring out how we can make right-to-left reading work "magically" and without having to rework all the templates. He also did those two translations. Thanks!

Update: I added a first attempt at generic RTL support to my private build and installed it here. If the primary language is set to any of the Arabic language variants, the page will flip into RTL reading. There are some issues around formatting to be worked out, though.

Categories: dasBlog

August 18, 2003
@ 08:36 PM

The workspace is maxed out at the current 20 users. I already submitted the form to ask for more users (the largest decimal number it takes is 99 so I went for that) and I really hope that there's someone at the other end of that form. GDN team, are you listening?

Update: Fixed.

Categories: dasBlog

I just posted newtelligence dasBlog version 1.2.3230.0 to the GotDotNet workspace and to the download section on the dasBlog site.

With this drop, I now have a feature set that makes me happy for my own blog and which some of you out there hopefully find useful for your own blogs. It’s been 5 weeks that were a lot of fun and I learned a lot about other user’s requirements through the feedback that I’ve gotten in the three weeks that the code has been public now.

And with this drop, I will therefore also stop the feature rush and likely not post more than fixes or updates to the language files and templates. Don’t expect significant new features from me in the upcoming weeks. What that means is clearly that I expect that something happens in the GotDotNet workspace from people other than me. There’s been a lot of complaining in the BlogX workspace about BlogX being stalled in terms of features and that the code-base has been locked and checked out the whole time. So, there you go: dasBlog is not checked out and open for all workspace members to change. I am going to be on the road for 3 1/2 weeks starting Wednesday, so don’t expect me to organize anything in the workspace or watch it. It’s yours. I’ll delegate accepting new members and begging to Microsoft for more workspace resources to someone around here, but that’s about it.

That also means that my private copy I am carrying around on my notebook is now forked off from the main code base and is going to be my own private little playground for new things to try.

Even if you are not at all interested in running the software as-is, you may want to go and grab the code base, because I am sure there’s a lot of useful little things in there if you are developing ASP.NET apps. It turned out to be so much new code and so many new little utilities and tricks that I could hardly keep track of the “new new” things, let alone document them. There’s a lot of fodder for articles, tips and tricks columns or for highlighting aspects here on the blog.

One thing you’ll find digging into the code-base is that almost always when there’s something that doesn’t need to be done synchronously, I don’t do it synchronously. Every referral gets queued up in an in memory queue and is written to the referrer-log on a secondary thread. All mail notifications, pingbacks, trackbacks and the pining of weblogs.com and blo.gs are also done on secondary threads.

You’ll also find that the little drop-shadows on the configuration page for the content-filter are neither rendered by IE, not will you be able to find the displayed images anywhere in your site’s directories. Instead, the drop shadows are all dynamically rendered. The magic is done by the “ShadowBox” control that’s in the newtelligence.Web.UI.WebControls assembly. You can configure the shadow depth, the background color onto which the shadow is to be rendered, etc.

The DHTML editor is also a reusable component from that assembly. It loads its toolbar from an embedded resource using the same technique: The ControlImageHandler class is an IHttpHandler which is capable of redirecting requests for images back to the controls that rendered the image links. So, in essence, you get something similar to Windows Forms’ OnPaint() support for WebControls.

There’s a complete (and working) implementation of a class WindowsTimeZone, derived from System.TimeZone and a matching WindowsTimeZoneCollection that grabs all the time zone information known to Windows and exposes that in a .NET Framework compatible way, including daylight savings time and all that.

The UrlMapper is a generic component that lets you use regular expressions to filter incoming URLs and map them to internal URLs, which comes very handy if you change a site’s structure around, MailToWeblog contains a five-liner showing how to create thumbnails from images, …

…. many things to explain in more detail and so little time. Stay tuned. ;)

Categories: dasBlog

August 17, 2003
@ 12:48 PM

I am sure it's a coindicence, but every once in a while I get referrals from some invisible site inside www.iaea.org.

Therefore, I hereby declare that I support only "Atom the XML format" and not "Atom the bomb". My house is open for inspections, if you guys think that's necessary.

I hope that keeps me out of trouble. 

Categories: Other Stuff

The language list is growing; Tom Mertens and Bart Vermeersch both sent me Dutch string tables for inclusion in dasBlog 1.2. One is going to be the default for Dutch and Dutch (Netherlands) and the other is going to be the default for Dutch (Belgium).

Bedankt! Site updated.

Categories: dasBlog

Consider Norwegian-Bokmal (NO and nb-NO) done. Christian did it. Already installed here; best seen in the comment view if you’ve got Norwegian as the most preferred language.

Categories: dasBlog

August 16, 2003
@ 07:07 PM

Note: For visitors of your site, this entry is only displayed for users with the preselected language English/English (en)

Error:
System.ArgumentException: Culture name en;q=1.0 is not supported.
Parameter name: name
at System.Globalization.CultureInfo..ctor(String name, Boolean useUserOverride)
at System.Globalization.CultureInfo.CreateSpecificCulture(String name)
at newtelligence.DasBlog.Web.Core.SharedBasePage.SetupPage(Object o, EventArgs e)
at System.EventHandler.Invoke(Object sender, EventArgs e)
at System.Web.UI.Control.OnInit(EventArgs e)
at newtelligence.DasBlog.Web.HomePage.OnInit(EventArgs e)
at System.Web.UI.Control.InitRecursive(Control namingContainer)
at System.Web.UI.Page.ProcessRequestMain()
while processing ht tp://staff.newtelligence.net/clemensv/default.aspx?external_referrer=ht tp://newtelligence.com/.

To whoever caused this event log entry to show up 10 minutes ago .... thanks, should be fixed now ;)

Categories: dasBlog

So.... dasBlog 1.2 nears completion and this will then also conclude the “feature rush“ for a while, because the allocated time for this “summer project” (5 weeks) is up and I have to shift gears. The last step for 1.2 is localization. Based on the user’s top preference in the Accept-Language header, dasBlog 1.2 presents all “hard coded” strings for publicly visible elements like the “Comment” link and the entire administrator interface in the preferred language, if the respective resources are available.

There’s now also an additional macro “localString” that you can use to define a multilingual expression in your templates: <%localString(“This is the English default|DE:Das ist die deutsche Alternative|IT:Questo e in italiano”)%>. This will resolve into German or Italian if that’s on the user’s language preferences list (Accept-Language header, again) and fall back to the default expression before the first delimiter if there’s no proper mapping. And, yes, you could also differentiate between “en-GB”, “en-US” and “en-CA”.

On the posting side, all posts are posted with the “invariant culture” (empty identifier) by default and will therefore show up on the blog independent of the user’s language preference. However, you can also select a language/culture pair when posting (for instance either “de” for German in general or “de-AT” for Austria, specifically) and then the post will only show up for users who have this language/culture listed in their browser’s language preferences. In the RSS feeds, the <item> tag will then carry the proper xml:lang designation (which propagates down to all its children as per XML 1.0).

By now, I have two complete language sets for the localized resources for English (en-US) and German (de-DE), but that’s as far as my “active” language skills take me. So if any of you folks out there (especially dasBlog users – hint, hint) have some 20 minutes of time and want to help me with localization into languages other than those two, grab the three files below (it’s just XML), translate the stuff between the <value> tags (except the topmost four) and send them, with the filenames reflecting the culture (such as Web.StringTables.ES.resx for Spanish), back to me at clemensv@newtelligence.com 

Of course, I will have to figure out how trust the correctness if I am getting translations into languages that aren’t from Latin or Germanic descent (most of those I can usually figure out), but that’s something to determine if and when it happens. For now, this is also a great experiment to see whether this little call for help yields any results. You’ll definitely get a permanent link and mention prominently on the dasBlog website and I can also put your blog into the blogroll that is included the setup archives, how’s that for a “payment”?

Download: Web.StringTables.resx
Download: WebControls.StringTables.resx
Download: WebCore.StringTables.resx

Categories: dasBlog

August 16, 2003
@ 05:12 PM

Since the backend stores all times in UTC, the engine can also adjust for daylight savings time when rendering. Check out the April 1st page and compare the timezone info below the entries with the following March 30th.

(BTW, I've done the whole time handling stuff mostly because I've seen that being only on GMT is a bit painful if you are a Fast Chicken in NZ. Nic, you get your timezone back.)

Categories: dasBlog

August 16, 2003
@ 03:55 PM

Don't be surprised to see this Weblog showing you Russian day and month names if your browser's preferred language is set to Russian or talks to you in Spanish or Italian. Also, don't be surprised if even more things (like the "Comments" link or all the field names on the Comment page) show up in German, if your preferred language is German. That's a feature. 

Categories: dasBlog

August 16, 2003
@ 03:40 PM

This is a split entry consisting of two posts. Everyone can see this post, but you will not see (2/2) on the website, if your browser's "Languages" setting doesn't have German as an acceptable language.

Categories: dasBlog

August 15, 2003
@ 06:50 AM

 

Categories: Other Stuff

August 14, 2003
@ 05:51 PM

DateTime issued;

[XmlIgnore]
public DateTime IssuedUtc
{ get { return issued; } set { issued = value; } }

[XmlElement("issued")]
public DateTime IssuedLocalTime
{ get { return Issued.ToLocalTime(); } set { Issued = value.ToUniversalTime(); } }

 

Why?

Categories: XML | CLR

Here's a CERT advisory to check out regarding the vulnerability of other DCE implementations to the Blaster worm. And unless otherwise stated on their site (which isn't the case now), I would assume that Software AG's EntireX DCOM is vulnerable as well.

 

Categories: Other Stuff

In 1.1 (hidden) and in 1.2 (no longer hidden) of dasBlog, you can enable a feature for Mail-To-Weblog that will automatically turn attached pictures (not embedded pictures) into thumbnails in the post and you can also control the maximum height for the thumbnails. The relevant settings in site.config for 1.1 are

<Pop3InlineAttachedPictures>true</Pop3InlineAttachedPictures>
<Pop3InlinedAttachedPicturesThumbHeight>200</Pop3InlinedAttachedPicturesThumbHeight>

In 1.2 the config settings are the same, but I added them to the config page. Here's an example of how it comes out:


Das Blog-splash.jpg

Categories: dasBlog

August 12, 2003
@ 07:52 PM

Can't be referenced too much.... so here's the link: http://www.microsoft.com/security/incident/blast.asp. And here's Symantec's info and the removal tool.

Categories:

August 11, 2003
@ 05:16 AM

Those who are using dasBlog for their own blog and everyone reading my blog on the website or ever looked at my RSS feed may have noticed that all times in version 1.1 now show up as GMT (it's actually UTC, but for all practical purposes, the difference between UTC and GMT matters little here; GMT is the more common designation). 

I am in the GMT+2 time-zone and so is my server, but for a site with apparently global reach in a global medium this doesn't really matter, I think. Most people know their time zone offset from GMT, but do they know their time zone offset from Germany?

Bad examples for using time are the sites of the two most popular "recent blog changes" services. Blo.gs, for instance, uses some undeclared random time zone and Weblogs.com, does at least say that the timezone is "Pacific" (but that's of course PDT now and not PST, or isn't it?). There's a standardized, daylight-savings-time unaffected global time and that's GMT (actually, it's UTC). I know that's a little incovenient for folks in GMT-8 or GMT+12, but it's a standard.

Categories: Blog

Dan Farino, who wrote the CLR based, Regex extended stored procedure on which I put a warning sign yesterday, wrote me an email back (I notified him that I wrote that blog entry) and told me that he just uploaded an unmanaged version. Haven't downloaded it, yet, but it seems to be functionally equivalent. If it's stable and quick, I can think of 2 bazillon uses for this -- including, of course, Regex based XML parsing inside SQL Server (while we wait for Yukon).

Categories: CLR | Technology | XML

August 11, 2003
@ 03:40 AM

My old blog is still on #1 for "Clemens" and my new blog is, surprisingly, already on #4 on Google. For "Vasters", my blogs take #1 and #2 with the Radio blog still on top. I guess that'll turn around within the next few weeks.

Categories: Blog

I guess my next little toy project will be around aggregation. Not that I won't continue adding stuff to "dasBlog", but I am quite happy with the status as of now and once we've got Stephen's caching work in the project, we'll make it a 1.2 .

So, the other bigger chunk of code that I have sitting around here from the blogging infrastructure that I wrote but didn't get done in the first quarter of this year (and from which the rendering engine made it into dasBlog) is a pretty serious, extensible syndication engine based on Enterprise Services and SQL Server. Pulling in RSS feeds is, in my view, a background server task. A common infrastructure for subscribing, queuing, requesting, transforming, filtering, caching and pushing out results (via LCE) is something that could be very handy, makes a great demo and there's lots of sample data to gather in a short time ;)

I am not at all interested in writing yet another aggregation GUI. I may grab one of the available aggregators like SharpReader or RSS Bandit and hook it up for demo purposes, but that's about it.

So ... while looking around for tools I could use, I found this cool extended stored procedure for using .NET Framework regular expressions straight from within SQL Server. Hold! What I also found (and I actually looked for it) was this Microsoft KB article (Q322884) that states that extended stored procs written in managed code "is not supported". 

Based on some discussions I had with members of the SQL team about the next release of SQL Server (Yukon) earlier this year about their work around incorporating the CLR (the fact that they're doing that is public so I am not violating any of the papers I signed), this absolutely doesn't come as a surprise to me and the bottom line is: This stored procedure looks cool, but shouldn't get near a SQL Server 2000 production server, ever.

The reason for that is that SQL Server is essentially an operating system by itself. It does its own memory management, can do its own thread scheduling (it makes use of  fibers, which are self-scheduled threads) and has, of course, its own I/O system sitting on low-level OS functions. The CLR doesn't know about any of that and SQL Server 2000 doesn't know about the CLR. If you are writing a stored procedure in unmanaged C/C++, you create just a DLL that runs on top of Win32 and if you follow a couple of rules, you should be ok. If you are writing in C# or VB.NET, you are bringing along an environment that doesn't know anything about these rules around SQL's use of threading and thread local storage, probably wants to launch additional threads under the covers and whose garbage collector hasn't been designed to cooperate with SQL's memory management. Yes, it may run, but what happens under stress or low memory conditions? How does it affect transactions? What's the story around performance once the CLR is present in the process and is probably used in only one of 500 queries?  I know that putting the CLR into Yukon is nothing that a someone at Microsoft does in a day or two and therefore I doubt that putting the CLR into SQL 2000 within half a day is a good idea for a real system. Things are different if you are running inside what essentially is an OS kernel.

Categories: CLR

August 10, 2003
@ 09:51 AM

Jon Udell found  (and Stefan Tilkov did too) that my new design doesn’t (didn’t) work in Mozilla Firebird.

The issues were inconsistencies in the behavior of the "float" and "clear" CSS properties between Opera, IE and Mozilla and, on top of it all, the rustiness of my CSS skills. All the "side-bar" elements on the left side of the page (calendar, navigator links, category list and blogroll) were "width:220px", "float:left" and "clear:both", saying "show this thing on the left hand side of any content that is rendered with regular layout and put the box under all other left floating boxes". So that causes all of these boxes to come out vertically aligned.

Now, the content section was also "float:left" but with "clear:right" and "width:70%". Opera and IE were showing the content as I intended it, to the right of the side-bar. As per the words of the spec, that indeed seems to be proper behavior for "clear:right", because it says that "The top margin of the generated box is increased enough that the top border edge is below the bottom outer edge of any right-floating boxes that resulted from elements earlier in the source document."  In other words, since all other elements rendered before this element were "float:left" and there isn't any "float:right" up to this point, the top margin for the new float is should be at relative/top:0px. Opera and IE are right, Mozilla is wrong.

Now... I fixed this for all by simply removing the float/clear properties from the content box and not making the content floating anymore. ... and tripped over another problem: widths.

I set the content box's size to 78%. In IE, that turned out to be 78% of the available horizontal <body> space excluding the width of the already rendered side-bar boxes (now all set to 18% width). In Mozilla and Opera, that's simply 78% of the available horizontal <body> space (in effect, the available page width). So, 78% of 82% of the page width are roughly 64% (63.96%). Measuring pixels of what IE renders and taking the margins of the item boxes into account, I indeed got 64.3% for the content boxes. In Opera, measuring pixels yielded 78.6% of the page width and Mozilla came in at 78.1%.

Since I couldn’t find anything supporting IE's behavior reading the spec section on the width property and the definition of the containing block, I concluded Mozilla and Opera are doing this right and IE is doing it wrong. This was a bit surprising to me, because (a) I don't do web design for a living and would know otherwise and (b) because IE actually needs to perform extra work to get to these numbers, so that behavior is surely no accident.

Switching IE into “standards-compliant mode” by injecting <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN"> ultimately fixed the width calculation problem, but who would know that intuitively?

This left the problem that Mozilla doesn’t get the clear property right. So, I settled on an absolute horizontal positioning for the content box using “position:absolute;left:22%;width:73%” . Now with that, the footer (yet another <div> at the <body> level) was getting confused, because now I had only floating and absolutely positioned elements and therefore I wouldn’t know where the bottom is. Moving the footer into the content box below the content placeholder fixed that, too. Now it looks good for Mozilla and Opera and IE6.0. If you use an earlier version of IE, upgrade.

Categories: Blog

August 10, 2003
@ 07:21 AM

Tim Bray, author of the Namespace spec, enlightens us here that I am technically wrong by using the term "empty namespace". Yes. Absolutely. But the "not member of any namespace" vs. "member of the empty namespace" distinction becomes meaningless once you start coding against an XML infrastructure, because in the programming models, there is pretty much always a namespace qualifier. In the .NET Framework, for instance, the NamespaceURI is an empty string in such cases (... and it should really be null).

Categories: Technology | XML

Jon Udell writes in his most recent column that some think that there is a "controversy" about the use of XML namespaces. This seems to stem from the sad fact that RSS never got a proper namespace assigned to it and is one of the hottest schemas specs in the XML space right now. Sorry, there may people in disbelief, but the XML Namespaces spec is normative and referenced in the current XML 1.0 (Second Edition) spec. The empty namespace is a namespace.

Some notable experts — including Sean McGrath, CTO of Propylon in Dublin, Ireland — argue that namespaces should be avoided for that reason.

You can't avoid namespaces, they are automatic if you use XML today. If you don't declare one for your vocabulary/schema, you are contributing to a large cloud of "stuff" sitting in the "not part of any" namespace. The "empty" namespace (which essentially says "not part of any namespace") is the XML equivalent of a the "these are just some tags" garbage dump.

Categories: Web Services | Technology | XML

My buddy Stephen now also runs dasBlog in "all features enabled" mode. Both of us are now using our Radio subscriptions, while they last, just to upstream our RSS feeds to the Userland cloud from dasBlog. His Radio feed is in sync with the new feed and so is mine.

John Bristowe is also a Radio convert and comments that exuberantly with "Free at last, free at last, thank God Almighty, I'm free at last.".

I guess we can sum this up with:

Dear Userland, for more than year you didn't even bother to try fixing all the substantial problems Radio has around random upstreaming failures, random crashes, losing content, whacky caching effects, broken comments, lack of extensibility with mainstream tools and a lot more things. Radio is stuck at version 8.0.8 in a time when a new blogging tool gets published every other day. This is our answer.

I've written a bunch of features in dasBlog specifically to give myself a clean upgrade path from Radio to my stuff (and some of them I still have to document cleanly). Whenever anyone hits a permalink at my old Radio site, they get redirected to the correct entry here, I can update my rss.xml at the Userland cloud and I can use any available Radio design templates pretty much unchanged. What's funny, for instance, is that my engine pretty much never fails with a timeout when upstreaming the rss.xml to the Userland cloud. These are the real reasons for why dasBlog does what it does. I just got totally fed up with Radio.

John Bristowe wrote me a "Thank you" email saying "I believe a "switch" campaign (a la Apple) is in order. Goodbye, Radio. Hello, DasBlog! :-)". 

There's certainly not going to be a campaign, but I'll happily share my config details with anyone who's asking. Sorry, Userland.

Categories: dasBlog

August 9, 2003
@ 05:00 PM

Today was another day of brutal heat. Nearly impossible to go outside during the afternoon. So I had a very lazy start into the day and then watched football (real football!) and observed the players getting grilled ;)

My team, Borussia Mönchengladbach ended up with a 1:1 tie against Werder Bremen, scoring in the 81st minute to equalize a Bremen penalty goal earlier in that half. Two games, 4 points and rank 5 in the league with ranks 1-4 having the same point score. Not bad at all for this year's start. I rarely ever have time to go to the stadium, but I have been a huge fan ever since I could kick a ball. It's my home city club, so we're talking love here, not just sympathy.

Anyways ... between breakfast and football I played around with CSS and created a new template for my own blog, trying to stop myself from jumping into the code-base and making adjustments. Then I dropped the 5 files onto the server some 15 minutes ago and .. voilá ... works. The theme uses IE filters for the shadows, but otherwise it looks the same in Opera. Haven't checked out other browsers, but, in all reality and honesty, and looking at our server logs .... 'nuff said.

Categories: Blog | dasBlog | Other Stuff

August 8, 2003
@ 12:50 PM

I just had a horrible idea for how to test the mail-to-weblog feature. Don't follow this link.

Categories: dasBlog

August 8, 2003
@ 09:22 AM

Version 1.1 of dasBlog is up for download. Preferred download source is the GotDotNet workspace for the project, the other is on our server here.  

With this drop, we’re also releasing the lock on the source and leave the files checked-in in the workspace. If you want to add stuff, you are invited to do so, but make sure you read the set of simple rules I posted there on how to deal with the source control system.

Categories: dasBlog

He's an author and a great speaker, he was one of the best known technical consultants at Microsoft Germany and he initiated the "MSDN TechTalk" event series. His in-depth knowledge of Win32, COM and COM+ is astonishing and the same goes for the dark corners of the .NET Framework. With this, and a lot more things I could mention here, he's already a "software legend" in the German developer community.

... and now he made a very newtelligent move and joined our team. Welcome on board at newtelligence AG, Michael Willers.

Categories: newtelligence

August 8, 2003
@ 06:52 AM

Jörg ist current checking out dotText. He very much likes the admin interface and says it's very cute. And not only that. I had a glimpse and I have to agree. I think it's fantastic that Scott and us are releasing such big chunks of public code for the same purpose at the same time, but there is no "vs.". I think .Text is cool.

The most striking between the two engines is that .Text sits on SQL and ours uses plain text files. What I found through the email feedback I've gotten is that a lot of people who want to use dasBlog have their stuff sitting at some ISP and either don't have a SQL Server to talk to or the setup is too much of a hassle. So for them, the plain text storage makes more sense. I was about to rip it out and replace the file storage with a SQL backend as well, but now I am quite happy that I didn't.

(Although i have to admit that the transaction-loving architect in me still opposes the whole idea of using plain text files for read/write in a concurrent environment)

The second difference is that I started the whole thing only a bit more than 3 weeks ago from a copy of BlogX.

Categories: dasBlog

August 8, 2003
@ 02:52 AM

James Avery suggests creating something new for topic-based aggregation. His idea is to allow aggregation of blogs by topic and not by person and wants new things invented for this.

I think they exist.

The item-level <category> element of RSS allows for setting a taxonomy on category items and that's sufficient to make James' idea work, if  (a) aggregators were looking for the domain attribute and allowed grouping by it and (b) blog engines would allow you to attribute your categories like that. Then, we "only" need to agree on common categories (or someone just writes some up) and were set. No need to register anywhere or with a central system. Here's an example of how the elements could look for .NET bloggers:

<category domain="urn:msdn-microsoft-com:netframework">ASP.NET</category>
<category domain="urn:msdn-microsoft-com:netframework">Enterprise Services</category>
<category domain="urn:msdn-microsoft-com:netframework">C#</category>
<category domain="urn:msdn-microsoft-com:netframework">VB.NET</category>
<category domain="urn:msdn-microsoft-com:serversystem">SQL Server</category>
<category domain="urn:msdn-microsoft-com:serversystem">BizTalk Server</category>

Categories: Blog | Weblogs | RSS

August 7, 2003
@ 08:19 PM

No, I haven’t built the stuff 3219 times. It’s “3” for 2003 and “219” is today’s day of the year. Here’s the compiled one-liner that sits in my system32 directory and tells me …

 

Download: buildday.zip

Categories: CLR | dasBlog

I can’t myself to write the release notes at this hour (and the folks already running V1.0 would be unhappy without them), but dasBlog 1.1.3219.0 is sitting here all wrapped and packed and ready to go. So expect the zip files to show up at some time Friday at GotDotNet and around here. To start, here’s a bit of new documentation for the themes, templates and macros.

The documentation hero for the macros (and especially for digging up all the CSS classes) is Jörg Freiberger.

Jörg also spend numerous hours figuring out how to trick the ASP.NET calendar control into things it just doesn’t want to do in terms of formatting. No matter what you do, it just keeps injecting style attributes for things it seems are right although nobody ever asked for them. So the calendar control got us annoyed enough that we told it to shut up about formatting by creating a derived control and overriding the Render method like this:

        protected override void Render(HtmlTextWriter writer)
        {
            StringWriter sw = new StringWriter();
            HtmlTextWriter hw = new HtmlTextWriter( sw );

           // Render the calendar by calling the base class' method.
            base.Render(hw);

           // strip all the calendar formatting.
            writer.Write(Regex.Replace( sw.ToString(),"\\s*style=\"(.*?)\"",""));
        }

 

Categories: dasBlog

It is brutally hot here. Mid 90s(F) or always more than 33°C every day. No clouds. For at least 5 days already. Forecasts say that the day temperatures won’t drop for another 4-5 days. This is the middle of Europe but it feels more like North Africa now. It’s rare that people have air-conditioning in their homes, since we usually get like 10 days above 30°C in a whole summer. So everyone’s sweating.

This morning I went to the local Microsoft office in Neuss (some 15km from here) for a customer meeting. They don’t have air-conditioning, either.

newtelligence does ;-)

Categories: Other Stuff

August 6, 2003
@ 05:28 PM

Being cited by Sam Ruby is starting to look like a (much less devastating) version of being Slashdotted. Thanks for helping test my asynchronous, queued referrals processing. ;-)

Categories: Other Stuff

August 6, 2003
@ 05:25 PM
Categories: PDC 03

I absolutely think it is a silly idea blogging this, or even filling out the questionnaire in the first place, but I have quite a few friends and colleagues of whom I just know that they'll agree so wholeheartedly with this oracle's ruling that I must blog the result:

You are HP-UX. You're still strong despite the passage of time.  Though few understand you, those who do love you deeply and appreciate you.
Which OS are You?

Categories: Other Stuff

If you look at the bottom of the webpage of this posting (at least at the time of this posting), you'll see that this is now running on build 1.1.3218. The CSS styles of the templates here haven't been updated fully, so the calendar on the right is a bit ugly and I have disabled all other themes for the moment.

If you compare this (rss.xml at my old Radio weblog) and this (the RSS feed here), you'll notice that they're synchronized now. (Welcome back to my blog to all those folks still subscribed to the Radio feed)

This here :-D was typed as colon-dash-caps-D and is converted to an image link when rendered to the website using a simple content filter. All of you reading this through an aggregator will say "really?!", because all you'll see is colon-dash-caps-D. I don't want all that traffic for the images coming this way.  ;)

Categories: dasBlog

August 6, 2003
@ 09:05 AM

According to InfoWorld, SCO wants to have $699 per processor from everyone who runs Linux on a server, as an “introductory” offer and will ask $1399 after Oct 15 for a single-processor license.

That’s pretty stunning. Even if SCO were right with their allegations that there is SCO-owned IP in Linux (and I am not in the position to make any statement about the rightfulness of that claim), $699 per processor is still well above and beyond what would be their fair share – that pricing scheme looks more like “this is our OS, including everything that ships with it” and that seems just plainly wrong.

This reminds me of a similar high-profile case: the Unisys GIF license. They hold/held the LZW patent and that’s used in GIF. Of course, lots of developers found out after they’ve implemented and shipped GIF support and Unisys probably waited for a critical mass to accumulate before they started enforcing licensing fees for that patent in early 1995. (Side note from the Unisys site: The U.S. LZW patent expires June 20, 2003, the counterpart Canadian patent expires July 7, 2004, the counterpart patents in the United Kingdom, France, Germany and Italy expire June 18, 2004, and the Japanese counterpart patents expire June 20, 2004.). While Unisys certainly didn’t make too many friends with that move, they were initially asking something like ten cents to at most ten dollars per distributed copy of any software package using the GIF format, if I remember right (the pricing information seems to have vanished). I would think that looking at the SCO case, this all of a sudden becomes very fair and reasonable.

[Still, the web-site fee of $5000 per site if you were/are using unlicensed (as in: Unisys’ LZW patent licensing) software to create your GIFs, remains outrageous]

Categories: IT Strategy

August 5, 2003
@ 04:05 PM

Jörg and myself are getting real close to release the new drop of our "summer project", dasBlog, within the next two to three days. It's going to carry a 1.1 version number already, because we've made another set of massive changes, including restructuring the code base and splitting it up into many more files and projects, which should make collaborative work on this much easier (...possible). 

Areas that were worked on specifically:

  • All controls we render inside the macros will get a CSS class assigned to them and we are removing most of the fixed formatting inside the code, so that the appearance of every little thing shall be customizeable. This will have an impact on existing templates and may break some of the Radio templates, but the required changes should be rather minimal.
  • All time expressions are now consistently stored in UTC 
  • Mail-To-Weblog can now deal with RFC2822 dates
  • Nested OPML outlines can be rendered and edited
  • "Content filters" is not a new, but now visible feature that allows to run an arbitrary number of search/replace filters (regex or plain) against content before it is rendered. So, if you want to turn semicolon-dash-closing-parenthesis into a smiley when your page is rendered, you can add a filter that will do so. 
  • dasBlog can post its own RSS feed to any remote storage system supporting the XmlStorageSystem API, including the Radio Userland store.
  • Lots of additional configuration options to switch services on and off.
  • Several bug fixes.

Once we're done with that, Stephen Forte has promised to add some additional caching magic to the stuff.

Categories: dasBlog

My Radio subscription runs for another 11 months and I have some 40MB of webspace there, so why not use it. Also, it seems that it's going to take forever for people to switch their subscriptions from the old RSS feed to the new one. So, I wrote an XML-RPC client for Userland's Radio cloud this weekend and a little command line utility for upstreaming stuff outside of Radio. Of course, the real reason for the client piece is to be able to have my blog engine automatically push changes in the RSS feed up to my old blog location for as long as the Radio subscription runs, so that even the lazy folks get the right stuff. It'll be a switchable option in the next public dasBlog build.

Categories: dasBlog | XSS

(For a change, an entry in German and on something totally different)

Heute abend ab 18:10 Uhr ist die Bundesliga wieder "zu Hause" bei der ARD Sportschau und beim WDR. So sagt zumindest die Werbung. Für mich weckt die Rückkehr der Sportschau zum WDR "nostalgische Erinnerungen". Und zwar nicht nur aus Zuschauersicht, sondern an die Zeit, als ich beim "Machen" der Sportschau (in "tragender Rolle", nämlich als Kabelhilfe) für rund 6 Jahre, von Mitte 1985 bis Ende 1990 als Schüler und dann als Student dabei war.

Mitte der 80er war Fußball für die Volksseele zwar schon so wichtig wie heute, aber im Fernsehen fand Fußball eben lange nicht in dem Ausmass statt wie heute. In der Sportschau gabs drei oder vier Spiele in Ausschnitten zu sehen, und vielleicht noch die Tore von den anderen (wenn man Glück hatte) und an Kameraperspektiven gab's eben auch nicht so viele. Üblicherweise gab's eigentlich nur drei bis vier Kameras bei einem normalen Spiel. Eine "Führungskamera" für die Totale, dann entweder jeweils eine auf der Tribüne auf Höhe der jeweiligen 16 Meter Linie oder eine weitere Kamera unterhalb der Führungskamera und eine Handkamera für Interviews. Und das Zeug war schwer. Damals war das alles noch gute, alte Analogtechnik und wog ein mehrfaches dessen, was die heutigen Digitalkameras wiegen. Und wir mussten das natürlich alles durch die Gegend wuchten und für jedes Spiel kilometerweise Kabel ziehen. Auch war es damals absolut nicht selbstverständlich, dass der fertig geschnittene Beitrag einfach per Richtfunk (oder über Satellit) übertragen wurde. Wenn, und das galt besonders für die Sonntags-Sportschau, genug Zeit zwischen Aufzeichnungsende und Sendung war, ging das Band per Motorradkurier nach Köln.

Alles das war eine fantastische Zeit -- und der beste Studenten-Nebenjob, den ich mir vorstellen kann. Ich war jede Woche bei mindestens einem Bundesliga Spiel, oder mittwochs bei UEFA Cup, Pokal der Pokalsieger, beim DFB Pokal, der Fußball EM 1988, vielen Playoffs der Eishockey-Bundesliga, mehrmals beim World-Team Cup Tennis, Tischtennis WM 1989, diversen Leichtatlethik Meetings, und so ziemlich bei alle anderen Sportarten die man sich vorstellen kann. Und mit 130,- DM pro Tag und 50% Sonntags- und 100% Feiertagzuschlag war der Spass auch noch richtig gut bezahlt (für die damaligen Verhältnisse).

Einige der damaligen Kabelhilfe-Kollegen sind beim Fernsehen geblieben und teilweise auch vor der Kamera zu sehen. Tom Lehel, zum Beispiel, ist momentan in jeder zweiten Comedyserie am Start und Andreas Sauer ist mit der Band Leo Colonia eine grosse Nummer im Kölner Karneval. Und diverse bekannte Sportredakteure haben just damals beim WDR angefangen, waren als Studenten MAZ Redakteure (d.h. haben während der Ausziechnung Timecodes mitgeschrieben) oder haben auch Kisten geschleppt. Und Herr Guten Abend Allerseits war auch schon damals Redaktionsschef.

Categories: Other Stuff

A good deal of yesterday and some of this morning I've been fiddling around with nested ASP.NET DataGrids. Binding nested grids is pretty easy and they show all you want, but editing items in a nested grid just doesn't work as easy as editing in a simple Grid. In fact, it doesn't work at all. What happens is that you can put a nested grid into edit mode, but you never seem to be able to catch any Update/Cancel events from the edited item.

I tried to look for a solution by asking Google, but the answers that I found were very unsatisfactory, since there was no explanation on why exactly it doesn't work. So, here's why ... and it's very, very simple: Nested DataGrids lose all of their ViewState on any roundtrip. That seems to be some sort of problem that's actually related to how the entire TemplateControl infrastructure works, but that's what it is.

Since that's the case, the EditItemIndex isn't preserved across the roundtrip and the DataGrid doesn't know how to dispatch the Update event. Now, how do I work around it? Again, pretty simple: You need to store the EditItemIndex (and SelectedItemIndex, etc.) of the nested data-grid in the Page's ViewState whenever they change (Edit event, Cancel event, etc.), keyed by the UniqueID of the DataGrid and a matching suffix. When you reload the sub-grid on a roundtrip, recover the value(s) from the ViewState of the page and DataBind(). 

I've put the workaround into my current working copy for dasBlog (the OPML editor gets a hierarchical editor now) and it works great. Next build that gets released, you can look at it.

 

 

Categories: Technology | ASP.NET