<?xml version="1.0" encoding="utf-8"?>
<rss xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:pingback="http://madskills.com/public/xml/rss/module/pingback/" version="2.0">
  <channel>
    <title>Clemens Vasters - Technology|ASP.NET</title>
    <link>http://vasters.com/clemensv/</link>
    <description>Cloud Development and Alien Abductions</description>
    <language>en-us</language>
    <copyright>Clemens Vasters</copyright>
    <lastBuildDate>Thu, 21 Dec 2006 18:56:58 GMT</lastBuildDate>
    <generator>newtelligence dasBlog 1.9.7067.0</generator>
    <managingEditor>cvasters@guhhome.com</managingEditor>
    <webMaster>cvasters@guhhome.com</webMaster>
    <item>
      <trackback:ping>http://vasters.com/clemensv/Trackback.aspx?guid=4248ded3-821b-4a37-bbf2-12849f8f2a16</trackback:ping>
      <pingback:server>http://vasters.com/clemensv/pingback.aspx</pingback:server>
      <pingback:target>http://vasters.com/clemensv/PermaLink,guid,4248ded3-821b-4a37-bbf2-12849f8f2a16.aspx</pingback:target>
      <dc:creator>
      </dc:creator>
      <wfw:comment>http://vasters.com/clemensv/CommentView,guid,4248ded3-821b-4a37-bbf2-12849f8f2a16.aspx</wfw:comment>
      <wfw:commentRss>http://vasters.com/clemensv/SyndicationService.asmx/GetEntryCommentsRss?guid=4248ded3-821b-4a37-bbf2-12849f8f2a16</wfw:commentRss>
      <slash:comments>1</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
I've spent the last 1 1/2 weeks doing one of the most fun (seriously) work
assignments that each Program Manager of our team gets to do every once in a while:
Servicing. So until yesterday night (I'm flying home to Germany today) I was in charge
of ASP.NET Web Services and Remoting. An even though these technologies have
been out there for quite a while now, there are still situations where stuff breaks
and people are scratching their heads wondering what's going on. Overall, it was a
very, very quiet time on the bug front though. 
</p>
        <p>
The one issue that we found on my watch is that you can configure ASP.NET Web Forms
in a way that it breaks ASP.NET Web Services (ASMX). We are shipping one ASP.NET Web
Page (.aspx) with ASMX and that unfortunate interaction manages to break that exact
page with an error that's hard to figure out unless you have substantial ASP.NET knowledge
and you have enough confidence in that knowledge to not trust us ;-) 
</p>
        <blockquote dir="ltr" style="MARGIN-RIGHT: 0px">
          <p>
If you globally override the autoEventWireup setting in the &lt;page/&gt; config element
in the ASP.NET web.config and set that to "false", the DefaultWsdlHelpGenator.aspx
page (which sits in the CONFIG directory of the Framework) becomes very unhappy and
fails with a NullReferenceException, stating "Object reference not set to an
instance of an object." and showing you some code that's definitely not yours.
</p>
          <p>
What happened? Well, the file is missing a directive that overrides the override of
the default. The fix is to go edit the DefaultWsdlHelpGenerator.aspx file and
add the line:
</p>
          <p>
&lt;%@ Page AutoEventWireup="true" %&gt;
</p>
          <p>
That will fix the problem. 
</p>
        </blockquote>
        <p>
Now, the big question is: "Will you put that into a service pack?". While there's
obviously a bug here, the answer is, in this particular case, "don't know yet". Replacing
or editing that particular file is a potentially very impactful surgery
done on the patched system given that the file is there in source code and in the
config directory because you are supposed to be able to change it. Could we touch
changed files? Probably not. Could we touch unchanged files? Probably? So how would
you surface the difference and make sure that the systems we couldn't patch would
not suffer from the particular bug? What's the test impact for the code and for the
service pack or patch installer? How many people are actually using that ASP.NET config
directive AND are hosting ASMX services in the same application and/or scope? Is it
actually worth doing that? Making changes in code that has already shipped and
is part of the Framework is serious business, since you are potentially altering the
behavior of millions of machines all at once. So that part is definitely not done
in an "agile" way, but takes quite a bit of consideration, while it takes just
10 seconds and notepad.exe for you.
</p>
        <img width="0" height="0" src="http://vasters.com/clemensv/aggbug.ashx?id=4248ded3-821b-4a37-bbf2-12849f8f2a16" />
      </body>
      <title>ASP.NET's autoEventWireup="false" page config setting breaks ASP.NET Web Services (ASMX): NullReferenceException</title>
      <guid isPermaLink="false">http://vasters.com/clemensv/PermaLink,guid,4248ded3-821b-4a37-bbf2-12849f8f2a16.aspx</guid>
      <link>http://vasters.com/clemensv/2006/12/21/ASPNETs+AutoEventWireupfalse+Page+Config+Setting+Breaks+ASPNET+Web+Services+ASMX+NullReferenceException.aspx</link>
      <pubDate>Thu, 21 Dec 2006 18:56:58 GMT</pubDate>
      <description>&lt;p&gt;
I've spent the last&amp;nbsp;1 1/2&amp;nbsp;weeks doing one of the most fun (seriously) work
assignments that each Program Manager of our team gets to do every once in a while:
Servicing. So until yesterday night (I'm flying home to Germany today) I was in charge
of ASP.NET Web Services and Remoting.&amp;nbsp;An even though these technologies have
been out there for quite a while now, there are still situations where stuff breaks
and people are scratching their heads wondering what's going on. Overall, it was a
very, very&amp;nbsp;quiet time on the bug front though. 
&lt;/p&gt;
&lt;p&gt;
The one issue that we found on my watch is that you can configure ASP.NET Web Forms
in a way that it breaks ASP.NET Web Services (ASMX). We are shipping one ASP.NET Web
Page (.aspx) with ASMX and that unfortunate interaction manages to break that exact
page with an error that's hard to figure out unless you have substantial ASP.NET knowledge
and you have enough confidence in that knowledge to not trust us ;-) 
&lt;/p&gt;
&lt;blockquote dir=ltr style="MARGIN-RIGHT: 0px"&gt; 
&lt;p&gt;
If you globally override the autoEventWireup setting in the &amp;lt;page/&amp;gt; config element
in the ASP.NET web.config and set that to "false", the DefaultWsdlHelpGenator.aspx
page (which sits in the CONFIG directory of the Framework) becomes very unhappy and
fails with a NullReferenceException, stating&amp;nbsp;"Object reference not set to an
instance of an object." and showing you some code that's definitely not yours.
&lt;/p&gt;
&lt;p&gt;
What happened? Well, the file is missing a directive that overrides the override of
the default. The fix is to go&amp;nbsp;edit the DefaultWsdlHelpGenerator.aspx file and
add the&amp;nbsp;line:
&lt;/p&gt;
&lt;p&gt;
&amp;lt;%@ Page AutoEventWireup="true" %&amp;gt;
&lt;/p&gt;
&lt;p&gt;
That will fix the problem. 
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
Now, the big question is: "Will you put that into a service pack?".&amp;nbsp;While there's
obviously a bug here, the answer is, in this particular case, "don't know yet". Replacing
or editing that particular file is a&amp;nbsp;potentially very&amp;nbsp;impactful surgery
done on the patched system given that the file is there in source code and in the
config directory because you are supposed to be able to change it.&amp;nbsp;Could we touch
changed files? Probably not. Could we touch unchanged files? Probably? So how would
you surface the difference and make sure that the systems we couldn't patch would
not suffer from the particular bug? What's the test impact for the code and for the
service pack or patch installer? How many people are actually using that ASP.NET config
directive AND are hosting ASMX services in the same application and/or scope? Is it
actually worth doing that?&amp;nbsp;Making changes in code that has already shipped and
is part of the Framework is serious business, since you are potentially altering the
behavior of millions of machines all at once. So that part is definitely not done
in an "agile" way, but takes quite a bit of consideration, while it takes&amp;nbsp;just
10 seconds and notepad.exe for you.
&lt;/p&gt;
&lt;img width="0" height="0" src="http://vasters.com/clemensv/aggbug.ashx?id=4248ded3-821b-4a37-bbf2-12849f8f2a16" /&gt;</description>
      <comments>http://vasters.com/clemensv/CommentView,guid,4248ded3-821b-4a37-bbf2-12849f8f2a16.aspx</comments>
      <category>Technology/ASP.NET</category>
      <category>Technology/Web Services</category>
    </item>
    <item>
      <trackback:ping>http://vasters.com/clemensv/Trackback.aspx?guid=57b03894-e197-4512-b9ea-648105890103</trackback:ping>
      <pingback:server>http://vasters.com/clemensv/pingback.aspx</pingback:server>
      <pingback:target>http://vasters.com/clemensv/PermaLink,guid,57b03894-e197-4512-b9ea-648105890103.aspx</pingback:target>
      <dc:creator>
      </dc:creator>
      <wfw:comment>http://vasters.com/clemensv/CommentView,guid,57b03894-e197-4512-b9ea-648105890103.aspx</wfw:comment>
      <wfw:commentRss>http://vasters.com/clemensv/SyndicationService.asmx/GetEntryCommentsRss?guid=57b03894-e197-4512-b9ea-648105890103</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
I was sad when "Indigo" and "Avalon" went away. It'd be great if we'd have
a pool of cool legal-approved code-names for which we own the trademark rights and
which we could stick to. Think Delphi or Safari. "Indigo" was cool insofar as
it was very handy to refer to the technology set, but was removed far enough
from the specifics that it doesn't create a sharply defined, product-like island
within the larger managed-code landscape or has legacy connotations like "ADO.NET".
 Also, my talks these days could be 10 minutes shorter if I could refer to Indigo
instead of "Windows Communications Foundation". Likewise, my job title wouldn't have
to have a line wrap on the business card of I ever spelled it out in full.
</p>
        <p>
However, when I learned about the WinFX name going away (several weeks before the
public announcement) and the new "Vista Wave" technologies (WPF/WF/WCF/WCS) being rolled
up under the <a href="http://msdn.microsoft.com/winfx/">.NET Framework</a> brand,
I was quite happy. Ever since it became clear in 2004 that the grand plan to put
a complete, covers-all-and-everything managed API on top (and on quite a
bit of the bottom) of everything Windows would have to wait until siginificantly after
Vista and that therefore the Win16&gt;Win32&gt;WinFX continuity would not
tell the true story, that name made only limited sense to stick to. The .NET Framework
is the #1 choice for business applications and a well established brand. People refer
to themselves as being "dotnet" developers. But even though the .NET Framework covers
a lot of ground and "Indigo", "Avalon", "InfoCard", and "Workflow" are overwhelmingly
(or exclusively) managed-code based, there are still quite a few things in Windows
Vista that still require using P/Invoke or COM/Interop from managed code or unmanaged
code outright. That's not a problem. Something has to manage the managed code
and there's no urgent need to rewrite entire subsystems to managed code if you
only want to add or revise features. 
</p>
        <p>
So now all the new stuff is now part of the .NET Framework. That is a good, good,
good change. This says what it all is. 
</p>
        <p>
Admittedly confusing is the "3.0" bit. What we'll ship is a Framework 3.0 that rides
on top of the 2.0 CLR and includes the 2.0 versions of the Base-Class Library, Windows
Forms, and ASP.NET. It doesn't include the formerly-announced-as-to-be-part-of-3.0
technologies like VB9 (there you have the version number consistency flying out
the window outright), C# 3.0, and LINQ. Personally, I think that it might be
a tiny bit less confusing if the Framework had a version-number neutral name such
as ".NET Framework 2006" which would allow doing what we do now with less potential
for confusion, but only a tiny bit. Certainly not enough to stage a war
over "2006" vs. "3.0".
</p>
        <p>
It's a matter of project management reality and also one of platform predictability
that the ASP.NET, or Windows Forms teams do not and should not ship a full
major-version revision of their bits every year. They shipped Whidbey (2.0) in late
2005 and hence it's healthy for them to have boarded the scheduled-to-arrive-in-2007
boat heading to Orcas. We (the "WinFX" teams) subscribed to the Vista ship docking later
this year and we bring great innovation which will be preinstalled on every copy of
it. LINQ as well as VB9 and C# incorporating it on a language-level are
very obviously Visual Studio bound and hence they are on the Orcas ferry as well.
The .NET Framework is a steadily growing development platform that spans technologies
from the Developer Division, Connected Systems, Windows Server, Windows Client, SQL
Server, and other groups, and my gut feeling is that it will become the norm that
it will be extended off-cycle from the Developer Division's Visual Studio and
CLR releases. Whenever a big ship docks in the port, may it be Office, SQL, BizTalk,
Windows Server, or Windows Client, and as more and more of the still-unmanaged Win32/Win64
surface area gets wrapped, augmented or replaced by managed-code APIs over time and
entirely new things are added, there might be bits that fit into and update the
Framework.  
</p>
        <p>
So one sane way to think about the .NET Framework version number is that it merely
labels the overall package and not the individual assemblies and components included
within it. Up to 2.0 everything was pretty synchronized, but given the ever-increasing
scale of the thing, it's good to think of that being a lucky (even if intended) coindicence
of scheduling. This surely <a href="http://en.wikipedia.org/wiki/Microsoft_BackOffice">isn't
the first time</a> that packages were versioned independently of their components.
There was and is no reason for the ASP.NET team to gratuitously recompile their existing
bits with a new version number just to have the GAC look pretty and to create the
illusion that everything is new - and to break Visual Studio compatibility in the
process.
</p>
        <p>
Of course, once we cover 100% of the Win32 surface area, we can rename it all into
WinFX again ;-)  (just kidding)
</p>
        <p>
[All the usual "personal opinion" disclaimers apply to this post]
</p>
        <p>
          <font size="1">
            <em>Update:</em> Removed reference to "Win64".</font>
        </p>
        <img width="0" height="0" src="http://vasters.com/clemensv/aggbug.ashx?id=57b03894-e197-4512-b9ea-648105890103" />
      </body>
      <title>Code-Name WinFX vs .NET Framework 3.0</title>
      <guid isPermaLink="false">http://vasters.com/clemensv/PermaLink,guid,57b03894-e197-4512-b9ea-648105890103.aspx</guid>
      <link>http://vasters.com/clemensv/2006/06/18/CodeName+WinFX+Vs+NET+Framework+30.aspx</link>
      <pubDate>Sun, 18 Jun 2006 12:39:48 GMT</pubDate>
      <description>&lt;p&gt;
I was sad when "Indigo" and "Avalon" went away. It'd be great&amp;nbsp;if we'd&amp;nbsp;have
a pool of cool legal-approved code-names for which we own the trademark rights and
which we could stick to.&amp;nbsp;Think Delphi or Safari. "Indigo" was cool insofar as
it was very handy to refer to the technology set, but&amp;nbsp;was removed&amp;nbsp;far&amp;nbsp;enough
from the specifics that it doesn't&amp;nbsp;create a sharply defined, product-like island
within the larger managed-code landscape or has legacy connotations&amp;nbsp;like "ADO.NET".
&amp;nbsp;Also, my talks these days could be 10 minutes shorter if I could refer to Indigo
instead of "Windows Communications Foundation". Likewise, my job title wouldn't have
to&amp;nbsp;have a line wrap on the business card of I ever spelled it out in full.
&lt;/p&gt;
&lt;p&gt;
However, when I learned about the WinFX name going away (several weeks before the
public announcement) and the new "Vista Wave" technologies (WPF/WF/WCF/WCS) being&amp;nbsp;rolled
up&amp;nbsp;under the&amp;nbsp;&lt;a href="http://msdn.microsoft.com/winfx/"&gt;.NET Framework&lt;/a&gt;&amp;nbsp;brand,
I was&amp;nbsp;quite happy. Ever since it became clear in 2004 that the grand plan to&amp;nbsp;put
a complete,&amp;nbsp;covers-all-and-everything&amp;nbsp;managed API on top (and on quite a
bit of the bottom) of everything Windows would have to wait until siginificantly after
Vista and that&amp;nbsp;therefore&amp;nbsp;the Win16&amp;gt;Win32&amp;gt;WinFX continuity would not
tell the true story, that name made only limited sense to stick to. The .NET Framework
is the #1 choice for business applications and a well established brand. People refer
to themselves as being "dotnet" developers. But even though the .NET Framework covers
a lot of ground and "Indigo", "Avalon", "InfoCard", and "Workflow" are&amp;nbsp;overwhelmingly
(or exclusively) managed-code based, there are still quite a few things in Windows
Vista that still require using P/Invoke or COM/Interop from managed code or unmanaged
code outright. That's not a problem.&amp;nbsp;Something has to manage the managed code
and there's no urgent need to rewrite entire subsystems to managed code if&amp;nbsp;you
only want to add or revise features.&amp;nbsp;
&lt;/p&gt;
&lt;p&gt;
So now all the new stuff is now part of the .NET Framework. That is a good, good,
good&amp;nbsp;change. This says what it all is. 
&lt;/p&gt;
&lt;p&gt;
Admittedly confusing is the "3.0" bit. What we'll ship is a Framework 3.0 that rides
on top of the 2.0 CLR and includes the 2.0 versions of the Base-Class Library, Windows
Forms,&amp;nbsp;and ASP.NET. It doesn't include the formerly-announced-as-to-be-part-of-3.0
technologies like VB9 (there&amp;nbsp;you have the version number consistency flying out
the window outright), C# 3.0, and&amp;nbsp;LINQ. Personally, I think&amp;nbsp;that it might&amp;nbsp;be
a tiny bit less confusing if the Framework had a version-number neutral name such
as ".NET Framework 2006" which would allow&amp;nbsp;doing what we do now with less potential
for confusion, but only a tiny bit.&amp;nbsp;Certainly not enough to&amp;nbsp;stage a war
over "2006" vs. "3.0".
&lt;/p&gt;
&lt;p&gt;
It's a matter of project management&amp;nbsp;reality and also one of platform predictability
that the ASP.NET, or Windows Forms&amp;nbsp;teams&amp;nbsp;do not and should not ship a full
major-version revision of their bits every year. They shipped Whidbey (2.0) in late
2005 and hence&amp;nbsp;it's healthy for them&amp;nbsp;to&amp;nbsp;have boarded the scheduled-to-arrive-in-2007
boat heading to Orcas. We (the "WinFX" teams) subscribed to the Vista ship&amp;nbsp;docking&amp;nbsp;later
this year and we bring great innovation which will be preinstalled on every copy of
it. LINQ&amp;nbsp;as well as&amp;nbsp;VB9 and C# incorporating it on a language-level are
very obviously Visual Studio bound and hence they are on the Orcas ferry as well.
The .NET Framework is a steadily growing development platform that spans technologies
from the Developer Division, Connected Systems, Windows Server, Windows Client, SQL
Server, and other groups, and my gut feeling is that it will become the norm that
it will be extended off-cycle from the Developer Division's&amp;nbsp;Visual Studio and
CLR releases. Whenever a big ship docks in the port, may it be Office, SQL, BizTalk,
Windows Server, or Windows Client, and as more and more of the still-unmanaged Win32/Win64
surface area gets wrapped, augmented or replaced by managed-code APIs over time and
entirely new things are added, there might be bits that&amp;nbsp;fit into and update the
Framework. &amp;nbsp;
&lt;/p&gt;
&lt;p&gt;
So one sane way to think about the .NET Framework version number is that&amp;nbsp;it merely
labels the overall package and not the individual assemblies and components included
within it. Up to 2.0&amp;nbsp;everything was pretty synchronized, but&amp;nbsp;given the ever-increasing
scale of the thing, it's good to think of that being a lucky (even if intended) coindicence
of scheduling. This surely &lt;a href="http://en.wikipedia.org/wiki/Microsoft_BackOffice"&gt;isn't
the first time&lt;/a&gt; that&amp;nbsp;packages were versioned independently of their components.
There was and is no reason for the ASP.NET team to gratuitously recompile their existing
bits with a new version number just to have the GAC look pretty and to create the
illusion that everything is new - and to break Visual Studio compatibility in the
process.
&lt;/p&gt;
&lt;p&gt;
Of course, once we cover 100% of the Win32 surface area, we can rename it all into
WinFX again ;-)&amp;nbsp; (just kidding)
&lt;/p&gt;
&lt;p&gt;
[All the usual&amp;nbsp;"personal opinion" disclaimers apply to this post]
&lt;/p&gt;
&lt;p&gt;
&lt;font size=1&gt;&lt;em&gt;Update:&lt;/em&gt; Removed reference to "Win64".&lt;/font&gt; 
&lt;/p&gt;
&lt;img width="0" height="0" src="http://vasters.com/clemensv/aggbug.ashx?id=57b03894-e197-4512-b9ea-648105890103" /&gt;</description>
      <comments>http://vasters.com/clemensv/CommentView,guid,57b03894-e197-4512-b9ea-648105890103.aspx</comments>
      <category>IT Strategy</category>
      <category>Technology</category>
      <category>Technology/ASP.NET</category>
      <category>Technology/Avalon</category>
      <category>Technology/CLR</category>
      <category>Technology/Indigo</category>
      <category>Technology/Longhorn</category>
      <category>Technology/WCF</category>
      <category>Technology/Windows</category>
    </item>
    <item>
      <trackback:ping>http://vasters.com/clemensv/Trackback.aspx?guid=84227eea-d685-4f0b-bc7b-1b0e3637666d</trackback:ping>
      <pingback:server>http://vasters.com/clemensv/pingback.aspx</pingback:server>
      <pingback:target>http://vasters.com/clemensv/PermaLink,guid,84227eea-d685-4f0b-bc7b-1b0e3637666d.aspx</pingback:target>
      <dc:creator>
      </dc:creator>
      <wfw:comment>http://vasters.com/clemensv/CommentView,guid,84227eea-d685-4f0b-bc7b-1b0e3637666d.aspx</wfw:comment>
      <wfw:commentRss>http://vasters.com/clemensv/SyndicationService.asmx/GetEntryCommentsRss?guid=84227eea-d685-4f0b-bc7b-1b0e3637666d</wfw:commentRss>
      <slash:comments>2</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
The stack trace below (snapshot taken at a breakpoint in [WebMethod] "HelloWorld") shows
that I am having quite a bit of programming fun these days. Server-side ASP.NET hooked
up to a MSMQ listener.  
</p>
        <p>
          <font size="1">
            <em>
              <strong>simpleservicerequestinweb.dll!SimpleServiceRequestInWeb.Hello.HelloWorld()
Line 53 C#<br /></strong>
            </em>system.web.services.dll!System.Web.Services.Protocols.LogicalMethodInfo.Invoke(System.Object
target, System.Object[] values) + 0x92 bytes <br />
system.web.services.dll!System.Web.Services.Protocols.WebServiceHandler.Invoke() +
0x9e bytes <br />
system.web.services.dll!System.Web.Services.Protocols.WebServiceHandler.CoreProcessRequest()
+ 0x142 bytes <br />
system.web.services.dll!System.Web.Services.Protocols.SyncSessionlessHandler.ProcessRequest(System.Web.HttpContext
context) + 0x6 bytes <br />
system.web.dll!CallHandlerExecutionStep.System.Web.HttpApplication+IExecutionStep.Execute()
+ 0xb4 bytes <br />
system.web.dll!System.Web.HttpApplication.ExecuteStep(System.Web.HttpApplication.IExecutionStep
step, bool completedSynchronously) + 0x58 bytes <br />
system.web.dll!System.Web.HttpApplication.ResumeSteps(System.Exception error) + 0xfa
bytes <br />
system.web.dll!System.Web.HttpApplication.System.Web.IHttpAsyncHandler.BeginProcessRequest(System.Web.HttpContext
context, System.AsyncCallback cb, System.Object extraData) + 0xe3 bytes <br />
system.web.dll!System.Web.HttpRuntime.ProcessRequestInternal(System.Web.HttpWorkerRequest
wr) + 0x1e7 bytes <br />
system.web.dll!System.Web.HttpRuntime.ProcessRequest(System.Web.HttpWorkerRequest
wr) + 0xb0 bytes <br /></font>
          <em>
            <font size="1">
              <strong>newtelligence.enterprisetools.dll!newtelligence.EnterpriseTools.Msmq.MessageQueueAsmxDispatcher.MessageReceived(System.Object
sender = {newtelligence.EnterpriseTools.Msmq.MessageQueueListener}, newtelligence.EnterpriseTools.Msmq.MessageReceivedEventArgs
ea = {newtelligence.EnterpriseTools.Msmq.MessageReceivedEventArgs}) Line 33 C#<br />
newtelligence.enterprisetools.dll!newtelligence.EnterpriseTools.Msmq.MessageQueueListener.ReceiveLoop()
Line 305 + 0x2b bytes C#<br /></strong>
            </font>
          </em>
        </p>
        <img width="0" height="0" src="http://vasters.com/clemensv/aggbug.ashx?id=84227eea-d685-4f0b-bc7b-1b0e3637666d" />
      </body>
      <title>A Fun Stack Trace</title>
      <guid isPermaLink="false">http://vasters.com/clemensv/PermaLink,guid,84227eea-d685-4f0b-bc7b-1b0e3637666d.aspx</guid>
      <link>http://vasters.com/clemensv/2004/12/11/A+Fun+Stack+Trace.aspx</link>
      <pubDate>Sat, 11 Dec 2004 14:35:43 GMT</pubDate>
      <description>&lt;p&gt;
The stack trace below (snapshot taken at a breakpoint in [WebMethod] "HelloWorld")&amp;nbsp;shows
that I am having quite a bit of programming fun these days. Server-side ASP.NET hooked
up to a MSMQ listener.&amp;nbsp;&amp;nbsp;
&lt;/p&gt;
&lt;p&gt;
&lt;font size=1&gt;&lt;em&gt;&lt;strong&gt;simpleservicerequestinweb.dll!SimpleServiceRequestInWeb.Hello.HelloWorld()
Line 53&amp;nbsp;C#&lt;br&gt;
&lt;/strong&gt;&lt;/em&gt;system.web.services.dll!System.Web.Services.Protocols.LogicalMethodInfo.Invoke(System.Object
target, System.Object[] values) + 0x92 bytes&amp;nbsp;&lt;br&gt;
system.web.services.dll!System.Web.Services.Protocols.WebServiceHandler.Invoke() +
0x9e bytes&amp;nbsp;&lt;br&gt;
system.web.services.dll!System.Web.Services.Protocols.WebServiceHandler.CoreProcessRequest()
+ 0x142 bytes&amp;nbsp;&lt;br&gt;
system.web.services.dll!System.Web.Services.Protocols.SyncSessionlessHandler.ProcessRequest(System.Web.HttpContext
context) + 0x6 bytes&amp;nbsp;&lt;br&gt;
system.web.dll!CallHandlerExecutionStep.System.Web.HttpApplication+IExecutionStep.Execute()
+ 0xb4 bytes&amp;nbsp;&lt;br&gt;
system.web.dll!System.Web.HttpApplication.ExecuteStep(System.Web.HttpApplication.IExecutionStep
step, bool completedSynchronously) + 0x58 bytes&amp;nbsp;&lt;br&gt;
system.web.dll!System.Web.HttpApplication.ResumeSteps(System.Exception error) + 0xfa
bytes&amp;nbsp;&lt;br&gt;
system.web.dll!System.Web.HttpApplication.System.Web.IHttpAsyncHandler.BeginProcessRequest(System.Web.HttpContext
context, System.AsyncCallback cb, System.Object extraData) + 0xe3 bytes&amp;nbsp;&lt;br&gt;
system.web.dll!System.Web.HttpRuntime.ProcessRequestInternal(System.Web.HttpWorkerRequest
wr) + 0x1e7 bytes&amp;nbsp;&lt;br&gt;
system.web.dll!System.Web.HttpRuntime.ProcessRequest(System.Web.HttpWorkerRequest
wr) + 0xb0 bytes&amp;nbsp;&lt;br&gt;
&lt;/font&gt;&lt;em&gt;&lt;font size=1&gt;&lt;strong&gt;newtelligence.enterprisetools.dll!newtelligence.EnterpriseTools.Msmq.MessageQueueAsmxDispatcher.MessageReceived(System.Object
sender = {newtelligence.EnterpriseTools.Msmq.MessageQueueListener}, newtelligence.EnterpriseTools.Msmq.MessageReceivedEventArgs
ea = {newtelligence.EnterpriseTools.Msmq.MessageReceivedEventArgs}) Line 33&amp;nbsp;C#&lt;br&gt;
newtelligence.enterprisetools.dll!newtelligence.EnterpriseTools.Msmq.MessageQueueListener.ReceiveLoop()
Line 305 + 0x2b bytes&amp;nbsp;C#&lt;br&gt;
&lt;/strong&gt;&lt;/font&gt;
&lt;/p&gt;
&gt;&lt;img width="0" height="0" src="http://vasters.com/clemensv/aggbug.ashx?id=84227eea-d685-4f0b-bc7b-1b0e3637666d" /&gt;</description>
      <comments>http://vasters.com/clemensv/CommentView,guid,84227eea-d685-4f0b-bc7b-1b0e3637666d.aspx</comments>
      <category>Technology/ASP.NET</category>
      <category>Technology/MSMQ</category>
      <category>Technology/Web Services</category>
    </item>
    <item>
      <trackback:ping>http://vasters.com/clemensv/Trackback.aspx?guid=514bac78-5c4e-4c57-9c15-e7736c83aa1d</trackback:ping>
      <pingback:server>http://vasters.com/clemensv/pingback.aspx</pingback:server>
      <pingback:target>http://vasters.com/clemensv/PermaLink,guid,514bac78-5c4e-4c57-9c15-e7736c83aa1d.aspx</pingback:target>
      <dc:creator>
      </dc:creator>
      <wfw:comment>http://vasters.com/clemensv/CommentView,guid,514bac78-5c4e-4c57-9c15-e7736c83aa1d.aspx</wfw:comment>
      <wfw:commentRss>http://vasters.com/clemensv/SyndicationService.asmx/GetEntryCommentsRss?guid=514bac78-5c4e-4c57-9c15-e7736c83aa1d</wfw:commentRss>
      <slash:comments>6</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
I was a little off when I compared <a href="http://staff.newtelligence.net/clemensv/CommentView.aspx?guid=1214e26d-674e-4a5c-b716-eaa07d327705">my
problem here</a> to a tail call. <a href="http://www.eighty-twenty.net/blog/urn:www-eighty-twenty-net:1250.html">Gordon
Weakliem</a> corrected me with the term "continuation".
</p>
        <p>
The fact that the post got 28 comments shows that this seems to be an interesting
problem and, naming aside, it is indeed a tricky thing to implement in a
framework when the programming language you use (C# in my case) doesn't support the
construct. What's specifically tricky about the concrete case that I have
is that I don't know where I am yielding control to at the time when I make the
respective call. 
</p>
        <p>
I'll recap. Assume there is the following call
</p>
        <p>
          <font size="4">
            <font face="Courier New">
              <font size="2">CustomerService cs = <font color="#0000ff">new</font></font>
            </font>
            <font face="Courier New" size="2"> CustomerService();<br /></font>
            <font size="2">
              <font face="Courier New">cs.FindCustomer(customerId);</font>
            </font>
          </font>
        </p>
        <p>
          <em>FindCustomer </em>is a call that will not return any result as a return value.
Instead, the invoked service comes back into the caller's program at some
completely different place such this:
</p>
        <p>
          <font size="4">
            <font face="Courier New">
              <font size="2">[WebMethod]<br />
public<font color="#000000"></font><font color="#0000ff">void</font></font>
            </font>
            <font face="Courier New">
              <font size="2">
                <font color="#000000"> FindCustomerReply(Customer[]
result)<br /></font>{<br />
   ...<br /></font>
            </font>
            <font size="2">
              <font face="Courier New">}</font>
            </font>
          </font>
        </p>
        <p>
So what we have here is a "duplex" conversation. The result of an operation initiated
by an outbound message (call) is received, some time later, through an inbound
message (call), but not on the same thread and not on the same "object". You
could say that this is a callback, but that's not precisely what it is, because a
"callback" usually happens while the initiating call (as above <em>FindCustomer</em>)
has not yet returned back to its scope or at least while the initiating object (or
an object passed by some sort of reference) is still alive. Here, instead, processing
of the <em>FindCustomer</em> call may take a while and the initiating thread and the
initiating object may be long gone when the answer is ready.
</p>
        <p>
Now, the additional issue I have is that at the time when the <em>FindCustomer</em> call
is made, it is not known what "<em>FindCustomerReply</em>" message handler it
going to be processing the result and it is really not know what's happening next.
The decision about what happens next and which handler is chosen is dependent on several
factors, including the time that it takes to receive the result. If the <em>FindCustomer</em> is
called from a web-page and the service providing <em>FindCustomer</em> drops
a result at the caller's doorstep within 2-3 seconds [1], the <em>FindCustomerReply</em> handler can
go and hijack the initial call's thread (and HTTP context) and render a page
showing the result. If the reply takes longer, the web-page (the caller) may lose
its patience [2] and choose to continue by rendering a page that says "We are sending
the result to your email account." and the message handler with not throw HTML into
an HTTP response on an open socket, but rather render it to an email and send
it via SMTP and maybe even alert the user through his/her Instant Messenger when/if
the result arrives.
</p>
        <p>
          <font size="4">
            <font face="Courier New">
              <font size="2">[1] HTTP Request =&gt; </font>
            </font>
            <font size="2">
              <font face="Courier New">FindCustomer()
=?&gt; "<font color="#000000">FindCustomerReply" =&gt; yield to CustomerList.aspx
=&gt; HTTP Response<br /><font color="#003300">[2] HTTP Request =&gt; </font><font size="2"><font face="Courier New"><font color="#003300">FindCustomer()
=?&gt; </font><font color="#000000">Timeout!           
=&gt; yield to YouWillGetMail.aspx =&gt; HTTP Response<br />
                               T+n =?&gt;
"FindCustomerReply" =&gt; SMTP Mail<br />
                                                          
=&gt; IM Notification</font></font></font></font></font>
            </font>
          </font>
        </p>
        <p>
So, in case [1] I need to correlate the reply with the request and continue processing
on the original thread. In case [2], the original thread continues on a
"default path" without an available reply and the reply is processed on (possibly
two) independent threads and using two different notification channels.
</p>
        <p>
A slightly different angle. Consider a workflow application environment in a bank,
where users are assigned tasks and simply fetch the next thing from the to-do
list (by clicking a link in an HTML-rendered list). The reply that results from "<em>LookupAndDoNextTask</em>" is
a message that contains the job that the user is supposed to do.  
</p>
        <p>
          <font face="Courier New">[1] HTTP Request =&gt; LookupAndDoNextTask<font size="2">()
=?&gt; Job: "<font color="#000000">Call Customer" =&gt; yield to CallCustomer.aspx =&gt;
HTTP Response<br /></font></font></font>
          <font face="Courier New">[2] HTTP Request =&gt; LookupAndDoNextTask<font size="2">()
=?&gt; Job: "<font color="#000000">Review Credit Offer" =&gt; yield to ReviewCredit.aspx =&gt;
HTTP Response<br /><font color="#003300">[3] HTTP Request =&gt; LookupAndDoNextTask</font><font size="2"><font color="#003300">()
=?&gt; Job: "</font><font color="#000000">Approve Mortgage" =&gt; yield to ApproveMortgage.aspx =&gt;
HTTP Response<br /><font color="#003300">[4] HTTP Request =&gt; LookupAndDoNextTask</font><font size="2"><font color="#003300">()
=?&gt; No Job / Timeout</font><font color="#000000"> =&gt; yield to Solitaire.aspx =&gt;
HTTP Response</font></font></font></font></font></font></font>
        </p>
        <p>
In all of these cases, calls to "FindCustomer()" and "LookupAndDoTask()" that are
made from the code that deals with the incoming request will (at least in the theoretical
model) never return to their caller and the thread will continue to execute in a different
context that is "TBD" at the time of the call. By the time the call stack is
unwound and the initiating call (like FindCustomer) indeed returns, the request
is therefore fully processed and the caller may not perform any further
actions. 
</p>
        <p>
So the issue at hand is to make that fact clear in the programming model. In ASP.NET,
there is a single construct called "Server.Transfer()" for that sort of continuation,
but it's very specific to ASP.NET and requires that the caller knows where you want
to yield control to. In the case I have here, the caller knows that it is surrendering
the thread to some other handler, but it doesn't know to to whom, because this is
dynamically determined by the underlying frameworks. All that's visible and should
be visible in the code is a "normal" method call.
</p>
        <p>
          <font size="4">
            <font size="2">
              <font face="Courier New">cs.FindCustomer(customerId) </font>
              <font face="Verdana">might
therefore not be a good name, because it looks "too normal". And of course I
don't have the powers to invent a new statement for the C# language
like </font>
              <font face="Courier New">
                <strong>continue(</strong>cs.FindCustomer(customerId)<strong>)</strong></font>
              <font face="Verdana"> that
would result in a continuation that simply doesn't return to the call location. Since
I can't do that, there has to be a different way to flag it. Sure, I could put an
attribute on the method, but Intellisense wouldn't show that, would it? So it seems
the best way is to have a convention of prefixing the method name.</font>
            </font>
          </font>
        </p>
        <p>
There were a bunch of ideas in the comments for method-name prefixes. Here is a selection: 
</p>
        <ul>
          <li>
            <font face="Courier New">cs.InitiateFindCustomer(customerId)</font>
          </li>
          <li>
            <font face="Courier New">cs.YieldFindCustomer(customerId)</font>
          </li>
          <li>
            <font face="Courier New">cs.YieldToFindCustomer(customerId)</font>
          </li>
          <li>
            <font face="Courier New">cs.InjectFindCustomer(customerId)</font>
          </li>
          <li>
            <font face="Courier New">cs.PlaceRequestFindCustomer(customerId)</font>
          </li>
          <li>
            <font face="Courier New">cs.PostRequestFindCustomer(customerId)</font>
          </li>
        </ul>
        <p>
I've got most of the underlying correlation and dispatch infrastructure
sitting here, but finding a good programming model for that sort of behavior
is quite difficult. 
</p>
        <p>
          <em>[Of course, this post won't make it on Microsoft Watch, eWeek or The
Register]</em>
        </p>
        <img width="0" height="0" src="http://vasters.com/clemensv/aggbug.ashx?id=514bac78-5c4e-4c57-9c15-e7736c83aa1d" />
      </body>
      <title>Naming and Continuations (continued)</title>
      <guid isPermaLink="false">http://vasters.com/clemensv/PermaLink,guid,514bac78-5c4e-4c57-9c15-e7736c83aa1d.aspx</guid>
      <link>http://vasters.com/clemensv/2004/07/21/Naming+And+Continuations+Continued.aspx</link>
      <pubDate>Wed, 21 Jul 2004 08:24:16 GMT</pubDate>
      <description>&lt;p&gt;
I&amp;nbsp;was a little off&amp;nbsp;when I&amp;nbsp;compared&amp;nbsp;&lt;a href="http://staff.newtelligence.net/clemensv/CommentView.aspx?guid=1214e26d-674e-4a5c-b716-eaa07d327705"&gt;my
problem here&lt;/a&gt; to a tail call. &lt;a href="http://www.eighty-twenty.net/blog/urn:www-eighty-twenty-net:1250.html"&gt;Gordon
Weakliem&lt;/a&gt; corrected me with the term "continuation".
&lt;/p&gt;
&lt;p&gt;
The fact that the post got 28 comments shows that this seems to be an interesting
problem and, naming aside, it&amp;nbsp;is indeed a tricky thing to&amp;nbsp;implement in a
framework when the programming language you use (C# in my case) doesn't support the
construct.&amp;nbsp;What's specifically tricky about the&amp;nbsp;concrete case that I have
is that I don't&amp;nbsp;know where I am yielding control to at the time when I make the
respective call. 
&lt;/p&gt;
&lt;p&gt;
I'll recap. Assume there is the following call
&lt;/p&gt;
&lt;p&gt;
&lt;font size=4&gt;&lt;font face="Courier New"&gt;&lt;font size=2&gt;CustomerService&amp;nbsp;cs = &lt;font color=#0000ff&gt;new&lt;/font&gt;&lt;/font&gt;&lt;/font&gt;&lt;font face="Courier New" size=2&gt; CustomerService();&lt;br&gt;
&lt;/font&gt;&lt;font size=2&gt;&lt;font face="Courier New"&gt;cs.FindCustomer(customerId);&lt;/font&gt;&lt;/font&gt;&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;em&gt;FindCustomer &lt;/em&gt;is a&amp;nbsp;call that will not return any result as a return value.
Instead,&amp;nbsp;the invoked service&amp;nbsp;comes back into the caller's program at some
completely different place such this:
&lt;/p&gt;
&lt;p&gt;
&lt;font size=4&gt;&lt;font face="Courier New"&gt;&lt;font size=2&gt;[WebMethod]&lt;br&gt;
public&lt;font color=#000000&gt; &lt;/font&gt;&lt;font color=#0000ff&gt;void&lt;/font&gt;&lt;/font&gt;&lt;/font&gt;&lt;font face="Courier New"&gt;&lt;font size=2&gt;&lt;font color=#000000&gt; FindCustomerReply(Customer[]
result)&lt;br&gt;
&lt;/font&gt;{&lt;br&gt;
&amp;nbsp;&amp;nbsp; ...&lt;br&gt;
&lt;/font&gt;&lt;/font&gt;&lt;font size=2&gt;&lt;font face="Courier New"&gt;}&lt;/font&gt;&lt;/font&gt;&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
So what we have here is a "duplex" conversation. The result of an operation initiated
by an outbound&amp;nbsp;message (call) is received, some time later,&amp;nbsp;through an inbound
message&amp;nbsp;(call), but not on the same thread and not on the same "object".&amp;nbsp;You
could say that this is a callback, but that's not precisely what it is, because&amp;nbsp;a
"callback" usually happens&amp;nbsp;while the&amp;nbsp;initiating call (as above &lt;em&gt;FindCustomer&lt;/em&gt;)
has not yet returned back to its scope or at least while the initiating object (or
an object passed by some sort of reference) is still alive.&amp;nbsp;Here, instead,&amp;nbsp;processing
of the &lt;em&gt;FindCustomer&lt;/em&gt; call may take a while and the initiating thread and the
initiating object may be long gone when the answer is ready.
&lt;/p&gt;
&lt;p&gt;
Now, the additional issue I have is that at the time when the &lt;em&gt;FindCustomer&lt;/em&gt; call
is made, it is not&amp;nbsp;known what "&lt;em&gt;FindCustomerReply&lt;/em&gt;" message handler it
going to be processing the result and it is really not know what's happening next.
The decision about what happens next and which handler is chosen is dependent on several
factors, including the time that it takes to receive the result. If the &lt;em&gt;FindCustomer&lt;/em&gt; is
called from a web-page and the service providing &lt;em&gt;FindCustomer&lt;/em&gt;&amp;nbsp;drops
a result at the caller's doorstep within 2-3 seconds [1], the &lt;em&gt;FindCustomerReply&lt;/em&gt; handler&amp;nbsp;can
go and&amp;nbsp;hijack the initial call's thread (and HTTP context) and render a page
showing the result. If the reply takes longer, the web-page (the caller) may lose
its patience [2] and choose to continue by rendering a page that says "We are sending
the result to your email account." and the message handler with not throw HTML into
an&amp;nbsp;HTTP response on an open socket, but rather render it to an email and send
it via SMTP and maybe even alert the user through his/her Instant Messenger&amp;nbsp;when/if
the result arrives.
&lt;/p&gt;
&lt;p&gt;
&lt;font size=4&gt;&lt;font face="Courier New"&gt;&lt;font size=2&gt;[1] HTTP Request =&amp;gt; &lt;/font&gt;&lt;/font&gt;&lt;font size=2&gt;&lt;font face="Courier New"&gt;FindCustomer()
=?&amp;gt; "&lt;font color=#000000&gt;FindCustomerReply" =&amp;gt; yield to CustomerList.aspx =&amp;gt;
HTTP Response&lt;br&gt;
&lt;font color=#003300&gt;[2] HTTP Request =&amp;gt; &lt;/font&gt;&lt;font size=2&gt;&lt;font face="Courier New"&gt;&lt;font color=#003300&gt;FindCustomer()
=?&amp;gt; &lt;/font&gt;&lt;font color=#000000&gt;Timeout!&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
=&amp;gt; yield to YouWillGetMail.aspx =&amp;gt; HTTP Response&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;T+n&amp;nbsp;=?&amp;gt;
"FindCustomerReply" =&amp;gt; SMTP Mail&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
=&amp;gt; IM Notification&lt;/font&gt;&lt;/font&gt;&lt;/font&gt;&lt;/font&gt;&lt;/font&gt;&lt;/font&gt;&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
So, in case [1] I need to correlate the reply with the request and&amp;nbsp;continue processing
on the original thread. In&amp;nbsp;case [2], the original thread continues&amp;nbsp;on&amp;nbsp;a
"default path"&amp;nbsp;without an available reply and the reply is processed on (possibly
two) independent threads and using two different notification channels.
&lt;/p&gt;
&lt;p&gt;
A slightly different angle. Consider a workflow application environment in a bank,
where users are assigned tasks and simply fetch the next thing&amp;nbsp;from the to-do
list (by clicking a link in an HTML-rendered list). The reply that results from "&lt;em&gt;LookupAndDoNextTask&lt;/em&gt;"&amp;nbsp;is
a message that contains the job that the user is supposed to do. &amp;nbsp;
&lt;/p&gt;
&lt;p&gt;
&lt;font face="Courier New"&gt;[1] HTTP Request =&amp;gt; LookupAndDoNextTask&lt;font size=2&gt;()
=?&amp;gt; Job: "&lt;font color=#000000&gt;Call Customer" =&amp;gt; yield to CallCustomer.aspx&amp;nbsp;=&amp;gt;
HTTP Response&lt;br&gt;
&lt;/font&gt;&lt;/font&gt;&lt;/font&gt;&lt;font face="Courier New"&gt;[2] HTTP Request =&amp;gt; LookupAndDoNextTask&lt;font size=2&gt;()
=?&amp;gt; Job: "&lt;font color=#000000&gt;Review Credit Offer" =&amp;gt; yield to ReviewCredit.aspx&amp;nbsp;=&amp;gt;
HTTP Response&lt;br&gt;
&lt;font color=#003300&gt;[3] HTTP Request =&amp;gt; LookupAndDoNextTask&lt;/font&gt;&lt;font size=2&gt;&lt;font color=#003300&gt;()
=?&amp;gt; Job: "&lt;/font&gt;&lt;font color=#000000&gt;Approve Mortgage" =&amp;gt; yield to ApproveMortgage.aspx&amp;nbsp;=&amp;gt;
HTTP Response&lt;br&gt;
&lt;font color=#003300&gt;[4] HTTP Request =&amp;gt; LookupAndDoNextTask&lt;/font&gt;&lt;font size=2&gt;&lt;font color=#003300&gt;()
=?&amp;gt;&amp;nbsp;No Job / Timeout&lt;/font&gt;&lt;font color=#000000&gt;&amp;nbsp;=&amp;gt; yield to Solitaire.aspx&amp;nbsp;=&amp;gt;
HTTP Response&lt;/font&gt;&lt;/font&gt;&lt;/font&gt;&lt;/font&gt;&lt;/font&gt;&lt;/font&gt;&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
In all of these cases, calls to "FindCustomer()" and "LookupAndDoTask()" that are
made from the code that deals with the incoming request will (at least in the theoretical
model) never return to their caller and the thread will continue to execute in a different
context that is&amp;nbsp;"TBD" at the time of the call. By the time the call stack is
unwound and the&amp;nbsp;initiating call (like FindCustomer) indeed returns, the request
is therefore fully processed and the caller&amp;nbsp;may not&amp;nbsp;perform any further
actions.&amp;nbsp;
&lt;/p&gt;
&lt;p&gt;
So the issue at hand is to make that fact clear in the programming model. In ASP.NET,
there is a single construct called "Server.Transfer()" for that sort of continuation,
but it's very specific to ASP.NET and requires that the caller knows where you want
to yield control to.&amp;nbsp;In the case I have here, the caller knows that it is surrendering
the thread to some other handler, but it doesn't know to to whom, because this is
dynamically determined by the underlying frameworks. All that's visible and should
be visible in the code is a "normal" method call.
&lt;/p&gt;
&lt;p&gt;
&lt;font size=4&gt;&lt;font size=2&gt;&lt;font face="Courier New"&gt;cs.FindCustomer(customerId)&amp;nbsp;&lt;/font&gt;&lt;font face=Verdana&gt;might
therefore not be a good name, because&amp;nbsp;it looks "too normal". And of course I
don't have the powers to&amp;nbsp;invent a new&amp;nbsp;statement&amp;nbsp;for the C# language
like&amp;nbsp;&lt;/font&gt;&lt;font face="Courier New"&gt;&lt;strong&gt;continue(&lt;/strong&gt;cs.FindCustomer(customerId)&lt;strong&gt;)&lt;/strong&gt;&lt;/font&gt;&lt;font face=Verdana&gt;&amp;nbsp;that
would result in a continuation that simply doesn't return to the call location. Since
I can't do that, there has to be a different way to flag it. Sure, I could put an
attribute on the method, but Intellisense wouldn't show that, would it? So it seems
the best way is to have a convention of prefixing the method name.&lt;/font&gt;&lt;/font&gt;&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
There were a bunch of ideas in the comments for method-name prefixes. Here is a selection: 
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;font face="Courier New"&gt;cs.InitiateFindCustomer(customerId)&lt;/font&gt; 
&lt;li&gt;
&lt;font face="Courier New"&gt;cs.YieldFindCustomer(customerId)&lt;/font&gt; 
&lt;li&gt;
&lt;font face="Courier New"&gt;cs.YieldToFindCustomer(customerId)&lt;/font&gt; 
&lt;li&gt;
&lt;font face="Courier New"&gt;cs.InjectFindCustomer(customerId)&lt;/font&gt; 
&lt;li&gt;
&lt;font face="Courier New"&gt;cs.PlaceRequestFindCustomer(customerId)&lt;/font&gt; 
&lt;li&gt;
&lt;font face="Courier New"&gt;cs.PostRequestFindCustomer(customerId)&lt;/font&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
I've got most of the&amp;nbsp;underlying&amp;nbsp;correlation and dispatch infrastructure
sitting here, but finding a good&amp;nbsp;programming model for that sort of behavior
is quite difficult. 
&lt;/p&gt;
&lt;p&gt;
&lt;em&gt;[Of course, this post won't make it on Microsoft Watch,&amp;nbsp;eWeek&amp;nbsp;or The
Register]&lt;/em&gt;
&lt;/p&gt;
&lt;img width="0" height="0" src="http://vasters.com/clemensv/aggbug.ashx?id=514bac78-5c4e-4c57-9c15-e7736c83aa1d" /&gt;</description>
      <comments>http://vasters.com/clemensv/CommentView,guid,514bac78-5c4e-4c57-9c15-e7736c83aa1d.aspx</comments>
      <category>Architecture</category>
      <category>Architecture/SOA</category>
      <category>Technology</category>
      <category>Technology/ASP.NET</category>
      <category>Technology/CLR</category>
    </item>
    <item>
      <trackback:ping>http://vasters.com/clemensv/Trackback.aspx?guid=2639bfcf-a32a-4326-b49e-0ebd919d1675</trackback:ping>
      <pingback:server>http://vasters.com/clemensv/pingback.aspx</pingback:server>
      <pingback:target>http://vasters.com/clemensv/PermaLink,guid,2639bfcf-a32a-4326-b49e-0ebd919d1675.aspx</pingback:target>
      <dc:creator>
      </dc:creator>
      <wfw:comment>http://vasters.com/clemensv/CommentView,guid,2639bfcf-a32a-4326-b49e-0ebd919d1675.aspx</wfw:comment>
      <wfw:commentRss>http://vasters.com/clemensv/SyndicationService.asmx/GetEntryCommentsRss?guid=2639bfcf-a32a-4326-b49e-0ebd919d1675</wfw:commentRss>
      <slash:comments>3</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
Microsoft urgently needs to consolidate all the APIs that are required for provisioning
services or sites. The amount of knowledge you need to have and the number APIs you
need to use in order to lock down a Web service or Enterprise Services application
programmatically at installation time in order to have it run under an isolated
user account (with a choice of local or domain account) that has the precise rights
to do what it needs to do (but nothing else) is absolutely insane. 
</p>
        <p>
You need to set ACLs on the file system and the registry, you need to modify the local
machine's security policy, you need to create accounts and add them to local groups,
you must adhere to password policies with your auto-generated passwords, you need
to conbfigure identities on Enterprise Services applications and IIS application pools,
you need to set ACLs on Message Queues (if you use them), and you need to write WS-Policy
documents to secure your WS front. Every single of these tasks uses a different API
(and writing policies has none) and most of these jobs require explicit Win32
or COM interop. I have a complete wrapper for that functionality for my app now (which
took way too long to write), but that really needs to be fixed on a platform level.
</p>
        <img width="0" height="0" src="http://vasters.com/clemensv/aggbug.ashx?id=2639bfcf-a32a-4326-b49e-0ebd919d1675" />
      </body>
      <title>Secure deployment is just too hard, Microsoft</title>
      <guid isPermaLink="false">http://vasters.com/clemensv/PermaLink,guid,2639bfcf-a32a-4326-b49e-0ebd919d1675.aspx</guid>
      <link>http://vasters.com/clemensv/2004/06/07/Secure+Deployment+Is+Just+Too+Hard+Microsoft.aspx</link>
      <pubDate>Mon, 07 Jun 2004 09:45:52 GMT</pubDate>
      <description>&lt;p&gt;
Microsoft urgently needs to consolidate all the APIs that are required for provisioning
services or sites. The amount of knowledge you need to have and the number APIs you
need to use in order to lock down a Web service or Enterprise Services application
programmatically at installation time&amp;nbsp;in order to&amp;nbsp;have it run under an isolated
user account (with a choice of local or domain account) that has the precise rights
to do what it needs to do (but nothing else) is absolutely insane.&amp;nbsp;
&lt;/p&gt;
&lt;p&gt;
You need to set ACLs on the file system and the registry, you need to modify the local
machine's security policy, you need to create accounts and add them to local groups,
you must adhere to password policies with your auto-generated passwords, you need
to conbfigure identities on Enterprise Services applications and IIS application pools,
you need to set ACLs on Message Queues (if you use them), and you need to write WS-Policy
documents to secure your WS front. Every single of these tasks uses a different API
(and writing policies has none) and most of these jobs&amp;nbsp;require explicit Win32
or COM interop. I have a complete wrapper for that functionality for my app now (which
took way too long to write), but that really needs to be fixed on a platform level.
&lt;/p&gt;
&lt;img width="0" height="0" src="http://vasters.com/clemensv/aggbug.ashx?id=2639bfcf-a32a-4326-b49e-0ebd919d1675" /&gt;</description>
      <comments>http://vasters.com/clemensv/CommentView,guid,2639bfcf-a32a-4326-b49e-0ebd919d1675.aspx</comments>
      <category>Technology</category>
      <category>Technology/ASP.NET</category>
      <category>Technology/Enterprise Services</category>
    </item>
    <item>
      <trackback:ping>http://vasters.com/clemensv/Trackback.aspx?guid=896f4b48-2189-49f6-83b1-1b9d0e691ef8</trackback:ping>
      <pingback:server>http://vasters.com/clemensv/pingback.aspx</pingback:server>
      <pingback:target>http://vasters.com/clemensv/PermaLink,guid,896f4b48-2189-49f6-83b1-1b9d0e691ef8.aspx</pingback:target>
      <dc:creator>
      </dc:creator>
      <wfw:comment>http://vasters.com/clemensv/CommentView,guid,896f4b48-2189-49f6-83b1-1b9d0e691ef8.aspx</wfw:comment>
      <wfw:commentRss>http://vasters.com/clemensv/SyndicationService.asmx/GetEntryCommentsRss?guid=896f4b48-2189-49f6-83b1-1b9d0e691ef8</wfw:commentRss>
      <slash:comments>10</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
          <a href="http://www.neward.net/ted/weblog/index.jsp?date=20040601#1086154951687">Ted
Neward</a> has a crusade against DataSets going on on his blog. At this point in time,
I really only ever use them <strong>inside a service</strong> and only at times when
I am horribly lazy or when I code under the influence. Otherwise I just go through
the rather quick and mostly painless process of mapping plain data structures (generated
from schema) to and from stored procedure calls myself. More control, more interoperability,
less weight. I really like when my code precisely states how my app interacts
with one of the most important components: the data store.
</p>
        <p>
I don't even use DataSets on ASP.NET web pages anymore. The data binding logic allows
to bind against <em>anything</em> and if I have a public or protected property
"Customer" on my page class that is a data structure, I can simply have an expression
like &lt;%# Customer.Name %&gt; on my page and all is good. Likewise, a DataGrid
happily binds against anything that is an ICollection (Array, ArrayList, ...) and
the DataGridItem.DataItem property will then contain the individual element.  It's
just that the design-time support in VS.NET is very DataSet focused and messes
things up when you click the wrong things. 
</p>
        <p>
DataSets are really cool for Windows Forms apps. By now I've reached a point
where I simply conclude that the DataSet class should be banned from the server-side.
</p>
        <img width="0" height="0" src="http://vasters.com/clemensv/aggbug.ashx?id=896f4b48-2189-49f6-83b1-1b9d0e691ef8" />
      </body>
      <title>DataSet -- Taking a stance.</title>
      <guid isPermaLink="false">http://vasters.com/clemensv/PermaLink,guid,896f4b48-2189-49f6-83b1-1b9d0e691ef8.aspx</guid>
      <link>http://vasters.com/clemensv/2004/06/02/DataSet+Taking+A+Stance.aspx</link>
      <pubDate>Wed, 02 Jun 2004 08:46:07 GMT</pubDate>
      <description>&lt;p&gt;
&lt;a href="http://www.neward.net/ted/weblog/index.jsp?date=20040601#1086154951687"&gt;Ted
Neward&lt;/a&gt; has a crusade against DataSets going on on his blog. At this point in time,
I really only ever use them &lt;strong&gt;inside a service&lt;/strong&gt; and only at times when
I am horribly lazy or when I code under the influence. Otherwise I just go through
the rather quick and mostly painless process of mapping plain data structures (generated
from schema) to and from stored procedure calls myself. More control, more interoperability,
less weight. I really like when my code precisely states&amp;nbsp;how my app interacts
with one of the most important components: the data store.
&lt;/p&gt;
&lt;p&gt;
I don't even use DataSets on ASP.NET web pages anymore. The data binding logic allows
to bind against &lt;em&gt;anything&lt;/em&gt;&amp;nbsp;and if I have a public or protected property
"Customer" on my page class that is a data structure, I can simply have an expression
like &amp;lt;%# Customer.Name %&amp;gt;&amp;nbsp;on my page and all is good. Likewise, a DataGrid
happily binds against anything that is an ICollection (Array, ArrayList, ...) and
the DataGridItem.DataItem property will then contain the&amp;nbsp;individual element.&amp;nbsp;&amp;nbsp;It's
just that the design-time support in VS.NET is very DataSet focused and&amp;nbsp;messes
things up when you click the wrong things.&amp;nbsp;
&lt;/p&gt;
&lt;p&gt;
DataSets are really cool for&amp;nbsp;Windows Forms apps. By now I've reached a point
where I simply conclude that the DataSet class should be banned from the server-side.
&lt;/p&gt;
&lt;img width="0" height="0" src="http://vasters.com/clemensv/aggbug.ashx?id=896f4b48-2189-49f6-83b1-1b9d0e691ef8" /&gt;</description>
      <comments>http://vasters.com/clemensv/CommentView,guid,896f4b48-2189-49f6-83b1-1b9d0e691ef8.aspx</comments>
      <category>Technology</category>
      <category>Technology/ASP.NET</category>
    </item>
    <item>
      <trackback:ping>http://vasters.com/clemensv/Trackback.aspx?guid=0c0d98b1-fb37-4c2f-a39c-36ed9a2fe853</trackback:ping>
      <pingback:server>http://vasters.com/clemensv/pingback.aspx</pingback:server>
      <pingback:target>http://vasters.com/clemensv/PermaLink,guid,0c0d98b1-fb37-4c2f-a39c-36ed9a2fe853.aspx</pingback:target>
      <dc:creator />
      <wfw:comment>http://vasters.com/clemensv/CommentView,guid,0c0d98b1-fb37-4c2f-a39c-36ed9a2fe853.aspx</wfw:comment>
      <wfw:commentRss>http://vasters.com/clemensv/SyndicationService.asmx/GetEntryCommentsRss?guid=0c0d98b1-fb37-4c2f-a39c-36ed9a2fe853</wfw:commentRss>
      <slash:comments>1</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
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 <em>Update</em>/<em>Cancel</em> events
from the edited item.
</p>
        <p>
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 <em>why</em> 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.
</p>
        <p>
Since that's the case, the EditItemIndex isn't preserved across the roundtrip and
the DataGrid doesn't know how to dispatch the <em>Update</em> 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 <em>Page's </em>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(). 
</p>
        <p>
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.
</p>
        <p>
 
</p>
        <p>
 
</p>
        <img width="0" height="0" src="http://vasters.com/clemensv/aggbug.ashx?id=0c0d98b1-fb37-4c2f-a39c-36ed9a2fe853" />
      </body>
      <title>One of the big ASP.NET DataGrid mysteries -- solved.</title>
      <guid isPermaLink="false">http://vasters.com/clemensv/PermaLink,guid,0c0d98b1-fb37-4c2f-a39c-36ed9a2fe853.aspx</guid>
      <link>http://vasters.com/clemensv/2003/08/01/One+Of+The+Big+ASPNET+DataGrid+Mysteries+Solved.aspx</link>
      <pubDate>Fri, 01 Aug 2003 12:47:53 GMT</pubDate>
      <description>&lt;p&gt;
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 &lt;em&gt;Update&lt;/em&gt;/&lt;em&gt;Cancel&lt;/em&gt; events
from the edited item.
&lt;/p&gt;
&lt;p&gt;
I tried to look for a solution by asking Google, but the answers that I found&amp;nbsp;were
very unsatisfactory, since&amp;nbsp;there was no explanation on &lt;em&gt;why&lt;/em&gt; exactly it
doesn't work.&amp;nbsp;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.
&lt;/p&gt;
&lt;p&gt;
Since that's the case, the EditItemIndex isn't preserved across the roundtrip and
the DataGrid doesn't know how to dispatch the &lt;em&gt;Update&lt;/em&gt; event. Now, how do I
work around it? Again, pretty simple:&amp;nbsp;You need to store the EditItemIndex (and
SelectedItemIndex, etc.) of the nested data-grid in the &lt;em&gt;Page's &lt;/em&gt;ViewState
whenever they change (Edit event, Cancel event, etc.), keyed by the UniqueID of the
DataGrid and a matching suffix. When you reload the&amp;nbsp;sub-grid on a roundtrip,
recover the&amp;nbsp;value(s) from the ViewState of the page and DataBind().&amp;nbsp;
&lt;/p&gt;
&lt;p&gt;
I've put&amp;nbsp;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.
&lt;/p&gt;
&lt;p&gt;
&amp;nbsp;
&lt;/p&gt;
&lt;p&gt;
&amp;nbsp;
&lt;/p&gt;
&lt;img width="0" height="0" src="http://vasters.com/clemensv/aggbug.ashx?id=0c0d98b1-fb37-4c2f-a39c-36ed9a2fe853" /&gt;</description>
      <comments>http://vasters.com/clemensv/CommentView,guid,0c0d98b1-fb37-4c2f-a39c-36ed9a2fe853.aspx</comments>
      <category>Technology</category>
      <category>Technology/ASP.NET</category>
    </item>
    <item>
      <trackback:ping>http://vasters.com/clemensv/Trackback.aspx?guid=03f772b3-1c97-4445-be54-6074472a60ec</trackback:ping>
      <pingback:server>http://vasters.com/clemensv/pingback.aspx</pingback:server>
      <pingback:target>http://vasters.com/clemensv/PermaLink,guid,03f772b3-1c97-4445-be54-6074472a60ec.aspx</pingback:target>
      <dc:creator />
      <wfw:comment>http://vasters.com/clemensv/CommentView,guid,03f772b3-1c97-4445-be54-6074472a60ec.aspx</wfw:comment>
      <wfw:commentRss>http://vasters.com/clemensv/SyndicationService.asmx/GetEntryCommentsRss?guid=03f772b3-1c97-4445-be54-6074472a60ec</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <div class="entryBody">
          <a href="http://www.vsdotnet.be/blogs/tommer/PermaLink.aspx/8bac79e6-39a0-41ef-8592-ea0e0185e3e9">Tom
Mertens noticed</a> that I dropped Radio: 
</div>
        <blockquote dir="ltr" style="MARGIN-RIGHT: 0px">
          <div class="entryBody">
            <em>It seems </em>
            <a href="http://62.138.131.149/clemensv/">
              <em>Clemens</em>
            </a>
            <em> is
dropping </em>
            <a href="http://radio.userland.com/">
              <em>Radio</em>
            </a>
            <em> for </em>
            <a href="http://www.gotdotnet.com/community/workspaces/default.aspx?id=ddc98753-6559-489b-a533-57034790a93a">
              <em>BlogX</em>
            </a>
            <em> and
enhanced BlogX to include features (templates and macro's) offered by Radio. Let's
hope he will share his modifications with </em>
            <a href="http://www.kuro5hin.org/user/Carnage4Life/diary">
              <em>Dare</em>
            </a>
            <em>,
who is the new admin for the BlogX workspace. Interesting fact, Clemens also included </em>
            <a href="http://intertwingly.net/wiki/pie/FrontPage">
              <em>(n)Echo</em>
            </a>
            <em> (Atom?)
support.</em>
          </div>
        </blockquote>
        <p>
I absolutely intend to share the modifications to the BlogX code-base, but given
the amount of changes I made and the structural impact on the BlogX code-base, I will
likely make it available separately from the original BlogX and not ask Dare to integrate
it into the existing code-base. Because ....
</p>
        <p>
By now, every single file in the WeblogX project has basically been massively modified
or (and that's valid for most) entirely rewritten to an extent that only the filename
is left. I refactored the whole BlogXRuntime in a way that all content related actions
and all logging related actions are now defined on two interfaces for which implementing
instances can only be retrieved through factories and for which the current default
implementation being returned is still based on the current backend (although I did
some major changes to the file-handling and introduced a better concurrency strategy).
The endgame is to make the backend configurable/pluggable and provide an Enterprise
Services/Database backend. The BlogXData class and all Save()/Load() methods on the
"data-model" classes are now <em>internal</em> to the BlogXRuntime assembly to
make sure that the new layering is enforced. The backend now spins up an
additional, separate thread and uses a events and a queue to fan out referrals to
the log asynchronously in order to avoid concurrency conflicts. It uses jobs
queued in the thread pool to perform pings to weblogs.com, pingbacks and trackbacks
asynchronously so that the edit page doesn't hang in case one of those services
is slow or unreachable. On top of it all, there's support for the <a href="http://wellformedweb.org/story/9">Comment
API</a>, <a href="http://www.movabletype.org/docs/mttrackback.html">Trackback</a>, <a href="http://www.hixie.ch/specs/pingback/pingback">Pingback</a>, <a href="http://www.movabletype.org/docs/mtmanual_programmatic.html">MoveableType/Blogger/MetaWeblog
API</a>, all tested with a colorful selection of popular aggregators and blogging
tools -- and that works so nicely for me that I removed the somewhat whacky
Windows Forms client from the solution completely.
</p>
        <p>
The bottom line is: it's a new app to a degree that everyone who is currently writing
their own extensions to BlogX would be <em>very</em> unhappy to see the original code-base
change so massively. Once I am happy with the code-base (it's pretty stable already
as you can see) and have found a good name (the current newtelligence.BlogX.* namespaces
seem like name-hijacking), I'll set up a workspace on <a href="http://www.gotdotnet.com">gotdotnet.com</a> for
it.
</p>
        <img width="0" height="0" src="http://vasters.com/clemensv/aggbug.ashx?id=03f772b3-1c97-4445-be54-6074472a60ec" />
      </body>
      <title>Tom Mertens asks for the code</title>
      <guid isPermaLink="false">http://vasters.com/clemensv/PermaLink,guid,03f772b3-1c97-4445-be54-6074472a60ec.aspx</guid>
      <link>http://vasters.com/clemensv/2003/07/21/Tom+Mertens+Asks+For+The+Code.aspx</link>
      <pubDate>Mon, 21 Jul 2003 22:10:05 GMT</pubDate>
      <description>&lt;div class=entryBody&gt;&lt;a href="http://www.vsdotnet.be/blogs/tommer/PermaLink.aspx/8bac79e6-39a0-41ef-8592-ea0e0185e3e9"&gt;Tom
Mertens noticed&lt;/a&gt; that I dropped Radio: 
&lt;/div&gt;
&lt;blockquote dir=ltr style="MARGIN-RIGHT: 0px"&gt; 
&lt;div class=entryBody&gt;&lt;em&gt;It seems &lt;/em&gt;&lt;a href="http://62.138.131.149/clemensv/"&gt;&lt;em&gt;Clemens&lt;/em&gt;&lt;/a&gt;&lt;em&gt; is
dropping &lt;/em&gt;&lt;a href="http://radio.userland.com/"&gt;&lt;em&gt;Radio&lt;/em&gt;&lt;/a&gt;&lt;em&gt; for &lt;/em&gt;&lt;a href="http://www.gotdotnet.com/community/workspaces/default.aspx?id=ddc98753-6559-489b-a533-57034790a93a"&gt;&lt;em&gt;BlogX&lt;/em&gt;&lt;/a&gt;&lt;em&gt; and
enhanced BlogX to include features (templates and macro's) offered by Radio. Let's
hope he will share his modifications with &lt;/em&gt;&lt;a href="http://www.kuro5hin.org/user/Carnage4Life/diary"&gt;&lt;em&gt;Dare&lt;/em&gt;&lt;/a&gt;&lt;em&gt;,
who is the new admin for the BlogX workspace. Interesting fact, Clemens also included &lt;/em&gt;&lt;a href="http://intertwingly.net/wiki/pie/FrontPage"&gt;&lt;em&gt;(n)Echo&lt;/em&gt;&lt;/a&gt;&lt;em&gt; (Atom?)
support.&lt;/em&gt;
&lt;/div&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
I&amp;nbsp;absolutely intend to share the modifications to the BlogX code-base, but given
the amount of changes I made and the structural impact on the BlogX code-base, I will
likely make it available separately from the original BlogX and not ask Dare to integrate
it into the existing code-base. Because ....
&lt;/p&gt;
&lt;p&gt;
By now, every single file in the WeblogX project has basically been massively modified
or (and that's valid for most) entirely rewritten to an extent that only the filename
is left. I refactored the whole BlogXRuntime in a way that all content related actions
and all logging related actions are now defined on two interfaces for which implementing
instances can only be retrieved through factories and for which the current default
implementation being returned is still based on the current backend (although I did
some major changes to the file-handling and introduced a better concurrency strategy).
The endgame is to make the backend configurable/pluggable and provide&amp;nbsp;an&amp;nbsp;Enterprise
Services/Database backend. The BlogXData class and all Save()/Load() methods on the
"data-model" classes are now &lt;em&gt;internal&lt;/em&gt;&amp;nbsp;to the BlogXRuntime assembly to
make sure that the new layering is enforced.&amp;nbsp;The backend now spins up&amp;nbsp;an
additional,&amp;nbsp;separate thread and uses a events and a queue to&amp;nbsp;fan out referrals&amp;nbsp;to
the log asynchronously in order to avoid concurrency conflicts. It uses&amp;nbsp;jobs
queued in the thread pool to perform&amp;nbsp;pings to weblogs.com, pingbacks and trackbacks
asynchronously&amp;nbsp;so that the edit page doesn't hang&amp;nbsp;in case one of those services
is slow or unreachable. On top of it all, there's support for the &lt;a href="http://wellformedweb.org/story/9"&gt;Comment
API&lt;/a&gt;, &lt;a href="http://www.movabletype.org/docs/mttrackback.html"&gt;Trackback&lt;/a&gt;, &lt;a href="http://www.hixie.ch/specs/pingback/pingback"&gt;Pingback&lt;/a&gt;, &lt;a href="http://www.movabletype.org/docs/mtmanual_programmatic.html"&gt;MoveableType/Blogger/MetaWeblog
API&lt;/a&gt;, all tested with a&amp;nbsp;colorful selection of popular aggregators and blogging
tools -- and that works so&amp;nbsp;nicely for me&amp;nbsp;that I removed the somewhat whacky
Windows Forms client from the solution completely.
&lt;/p&gt;
&lt;p&gt;
The bottom line is: it's a new app to a degree that everyone who is currently writing
their own extensions to BlogX would be &lt;em&gt;very&lt;/em&gt; unhappy to see the original code-base
change so massively.&amp;nbsp;Once I am happy with the code-base (it's pretty stable already
as you can see) and have found a good name (the current newtelligence.BlogX.* namespaces
seem like name-hijacking), I'll set up a workspace on &lt;a href="http://www.gotdotnet.com"&gt;gotdotnet.com&lt;/a&gt; for
it.
&lt;/p&gt;
&lt;img width="0" height="0" src="http://vasters.com/clemensv/aggbug.ashx?id=03f772b3-1c97-4445-be54-6074472a60ec" /&gt;</description>
      <comments>http://vasters.com/clemensv/CommentView,guid,03f772b3-1c97-4445-be54-6074472a60ec.aspx</comments>
      <category>Blog</category>
      <category>Technology</category>
      <category>Technology/ASP.NET</category>
    </item>
    <item>
      <trackback:ping>http://vasters.com/clemensv/Trackback.aspx?guid=9b45d383-43c1-405f-ab8a-a5648d669157</trackback:ping>
      <pingback:server>http://vasters.com/clemensv/pingback.aspx</pingback:server>
      <pingback:target>http://vasters.com/clemensv/PermaLink,guid,9b45d383-43c1-405f-ab8a-a5648d669157.aspx</pingback:target>
      <dc:creator />
      <wfw:comment>http://vasters.com/clemensv/CommentView,guid,9b45d383-43c1-405f-ab8a-a5648d669157.aspx</wfw:comment>
      <wfw:commentRss>http://vasters.com/clemensv/SyndicationService.asmx/GetEntryCommentsRss?guid=9b45d383-43c1-405f-ab8a-a5648d669157</wfw:commentRss>
      <slash:comments>1</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
          <strong>BloggerAPI, MT API, MetaWeblog API, Comment API, Pingback API, Trackback  ... 
are you nuts?</strong>
        </p>
        <p>
I must admit that until last week I didn't really pay much close attention to all
the blogging related APIs and specs beyond "keeping myself informed". Today I copied
my weekend's work over to this server and now I have all of them implemented as client
and server versions. <a href="http://www.intertwingly.net/blog/">Sam</a>'s and <a href="http://diveintomark.org/">Mark</a>'s validator
is happy with my <a href="http://feeds.archive.org/validator/check?url=http%3A%2F%2Fstaff.newtelligence.net%2Fclemensv%2Frss.ashx">RSS</a> 2.0
feed and the experimental <a href="http://feeds.archive.org/validator/check?url=http%3A%2F%2Fstaff.newtelligence.net%2Fclemensv%2Fblogxbrowsing.asmx%2FGetAtom">Atom</a> (Pie/Echo)
feed.
</p>
        <p>
I have to say ... the state of affairs in this space is absolutely scary. Most
of the specs, especially for the APIs are lacking proper information detail, are
often too informal with too much room for ambiguities and you need to be lucky
to find a reasonably recent one. Sam <a href="http://www.intertwingly.net/blog/1520.html">laments</a> that
people don't read specs carefully and I agree, but I would argue that the specs need
to be written carefully, too. It also seems that because the documentation on expected
behavior is so thin, everybody implements their own flavor and extensions and
not only do the APIs have huge overlap, but it seems like any
random selection of offline blogging tools will use its own arbitrary selection of
these APIs in any random order. Since my implementation didn't "grow" over time,
but I implemented it all in one shot essentially only since last Thursday and had
to look at this all at once and what I found was just saddening. All of this
has to be consolidated and <a href="http://www.intertwingly.net/wiki/pie/FrontPage">it
will be</a>. 
</p>
        <p>
I am all for the <a href="http://www.intertwingly.net/wiki/pie/FrontPage">Atom
project </a>and creating a consolidated, SOAP-based API for all blogging functions
that the aforementioned APIs offer. XML-RPC was a good thing to start with but its
time is up.  I am also for replacing RSS x.x with a spec that's open
and under the umbrella of a recognized standards body and not of a <a href="http://blogs.law.harvard.edu/tech/rss">law
school</a>, that's XML as of ca. 2003 and not as of ca. 1998, and that's
formally documented (with a proper schema). What's there right now smells all
like "let's hack something up" and not very much like serious software engineering.
Ok, it's proven that it all works, but how about dumping the prototypes now?
</p>
        <p>
 
</p>
        <img width="0" height="0" src="http://vasters.com/clemensv/aggbug.ashx?id=9b45d383-43c1-405f-ab8a-a5648d669157" />
      </body>
      <title>BloggerAPI, MT API, MetaWeblog API, Comment API, Pingback API, Trackback  ...  are you nuts?</title>
      <guid isPermaLink="false">http://vasters.com/clemensv/PermaLink,guid,9b45d383-43c1-405f-ab8a-a5648d669157.aspx</guid>
      <link>http://vasters.com/clemensv/2003/07/21/BloggerAPI+MT+API+MetaWeblog+API+Comment+API+Pingback+API+Trackback+Are+You+Nuts.aspx</link>
      <pubDate>Mon, 21 Jul 2003 14:17:36 GMT</pubDate>
      <description>&lt;p&gt;
&lt;strong&gt;BloggerAPI, MT API, MetaWeblog API, Comment API, Pingback API, Trackback&amp;nbsp;&amp;nbsp;...&amp;nbsp;
are you nuts?&lt;/strong&gt;
&lt;/p&gt;
&lt;p&gt;
I must admit that until last week I didn't really pay much close attention to all
the blogging related APIs and specs beyond "keeping myself informed". Today I copied
my weekend's work over to this server and now I have all of them implemented as client
and server versions.&amp;nbsp;&lt;a href="http://www.intertwingly.net/blog/"&gt;Sam&lt;/a&gt;'s and &lt;a href="http://diveintomark.org/"&gt;Mark&lt;/a&gt;'s&amp;nbsp;validator
is happy with my&amp;nbsp;&lt;a href="http://feeds.archive.org/validator/check?url=http%3A%2F%2Fstaff.newtelligence.net%2Fclemensv%2Frss.ashx"&gt;RSS&lt;/a&gt;&amp;nbsp;2.0
feed and the experimental &lt;a href="http://feeds.archive.org/validator/check?url=http%3A%2F%2Fstaff.newtelligence.net%2Fclemensv%2Fblogxbrowsing.asmx%2FGetAtom"&gt;Atom&lt;/a&gt; (Pie/Echo)
feed.
&lt;/p&gt;
&lt;p&gt;
I have to say ... the state of&amp;nbsp;affairs in this space is absolutely scary. Most
of the specs, especially for the APIs are&amp;nbsp;lacking proper information detail,&amp;nbsp;are
often too informal&amp;nbsp;with too much room for ambiguities and you need to be lucky
to find a reasonably recent one. Sam &lt;a href="http://www.intertwingly.net/blog/1520.html"&gt;laments&lt;/a&gt; that
people don't read specs carefully and I agree, but I would argue that the specs need
to be written carefully, too. It also seems that because the documentation on expected
behavior is so thin, everybody implements their own&amp;nbsp;flavor and extensions and
not only do&amp;nbsp;the APIs&amp;nbsp;have huge overlap, but&amp;nbsp;it seems like&amp;nbsp;any
random selection of offline blogging tools will use its own arbitrary selection of
these APIs in any random order.&amp;nbsp;Since my implementation didn't "grow" over time,
but I implemented it all in one shot essentially only since last Thursday and had
to look at this all at once and what I found was just saddening.&amp;nbsp;All of this
has to be consolidated and &lt;a href="http://www.intertwingly.net/wiki/pie/FrontPage"&gt;it
will be&lt;/a&gt;. 
&lt;/p&gt;
&lt;p&gt;
I am all for&amp;nbsp;the &lt;a href="http://www.intertwingly.net/wiki/pie/FrontPage"&gt;Atom
project &lt;/a&gt;and creating a consolidated, SOAP-based&amp;nbsp;API for all blogging functions
that the aforementioned APIs offer. XML-RPC was a good thing to start with but its
time is up.&amp;nbsp;&amp;nbsp;I am also for replacing RSS&amp;nbsp;x.x with a spec that's open
and under the umbrella of a recognized standards body and not&amp;nbsp;of a &lt;a href="http://blogs.law.harvard.edu/tech/rss"&gt;law
school&lt;/a&gt;, that's XML&amp;nbsp;as of ca. 2003 and not as of ca. 1998, and&amp;nbsp;that's
formally documented (with a proper schema).&amp;nbsp;What's there right now smells all
like "let's hack something up"&amp;nbsp;and not very much like serious software engineering.
Ok, it's proven that it all works, but how about dumping the prototypes now?
&lt;/p&gt;
&lt;p&gt;
&amp;nbsp;
&lt;/p&gt;
&lt;img width="0" height="0" src="http://vasters.com/clemensv/aggbug.ashx?id=9b45d383-43c1-405f-ab8a-a5648d669157" /&gt;</description>
      <comments>http://vasters.com/clemensv/CommentView,guid,9b45d383-43c1-405f-ab8a-a5648d669157.aspx</comments>
      <category>Blog</category>
      <category>Technology</category>
      <category>Technology/ASP.NET</category>
      <category>Technology/Weblogs</category>
      <category>Technology/Weblogs/Atom</category>
    </item>
    <item>
      <trackback:ping>http://vasters.com/clemensv/Trackback.aspx?guid=318767eb-9c65-41ef-b583-b5220b7e3bc3</trackback:ping>
      <pingback:server>http://vasters.com/clemensv/pingback.aspx</pingback:server>
      <pingback:target>http://vasters.com/clemensv/PermaLink,guid,318767eb-9c65-41ef-b583-b5220b7e3bc3.aspx</pingback:target>
      <dc:creator />
      <wfw:comment>http://vasters.com/clemensv/CommentView,guid,318767eb-9c65-41ef-b583-b5220b7e3bc3.aspx</wfw:comment>
      <wfw:commentRss>http://vasters.com/clemensv/SyndicationService.asmx/GetEntryCommentsRss?guid=318767eb-9c65-41ef-b583-b5220b7e3bc3</wfw:commentRss>
      <slash:comments>1</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
        </p>
        <p>
This morning I got up early (I going to be picked to play Paintball in an
hour or so) and implemented image and attachment uploads for the blogging site. This
is the test for the live site. 
</p>
        <p>
[Here's a copy of the SoapExtension Wizard for Visual Studio.NET: <a href="http://staff.newtelligence.net/clemensv/content/binary/ASPNETSoapExtensionWizard.zip">ASPNETSoapExtensionWizard.zip
(53.82 KB)</a>]
</p>
        <p align="left">
          <a href="http://www.microsoft.com/rd">
            <img src="http://staff.newtelligence.net/clemensv/content/binary/msrd_4c.GIF" border="0" />
          </a>
        </p>
        <p>
          <a href="http://staff.newtelligence.net/clemensv/content/binary/ASPNETSoapExtensionWizard.zip">
          </a> 
</p>
        <img width="0" height="0" src="http://vasters.com/clemensv/aggbug.ashx?id=318767eb-9c65-41ef-b583-b5220b7e3bc3" />
      </body>
      <title>Blog work continues ....</title>
      <guid isPermaLink="false">http://vasters.com/clemensv/PermaLink,guid,318767eb-9c65-41ef-b583-b5220b7e3bc3.aspx</guid>
      <link>http://vasters.com/clemensv/2003/07/19/Blog+Work+Continues.aspx</link>
      <pubDate>Sat, 19 Jul 2003 08:39:35 GMT</pubDate>
      <description>&lt;p&gt;
&lt;/p&gt;
&lt;p&gt;
This morning I got up early (I&amp;nbsp;going to be picked to play Paintball&amp;nbsp;in an
hour or so) and implemented image and attachment uploads for the blogging site.&amp;nbsp;This
is the test for the live site. 
&lt;/p&gt;
&lt;p&gt;
[Here's a&amp;nbsp;copy of the SoapExtension Wizard for Visual Studio.NET: &lt;a href="http://staff.newtelligence.net/clemensv/content/binary/ASPNETSoapExtensionWizard.zip"&gt;ASPNETSoapExtensionWizard.zip
(53.82 KB)&lt;/a&gt;]
&lt;/p&gt;
&lt;p align=left&gt;
&lt;a href="http://www.microsoft.com/rd"&gt;&lt;img src="http://staff.newtelligence.net/clemensv/content/binary/msrd_4c.GIF" border=0&gt;&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;a href="http://staff.newtelligence.net/clemensv/content/binary/ASPNETSoapExtensionWizard.zip"&gt;&lt;/a&gt;&amp;nbsp;
&lt;/p&gt;
&lt;img width="0" height="0" src="http://vasters.com/clemensv/aggbug.ashx?id=318767eb-9c65-41ef-b583-b5220b7e3bc3" /&gt;</description>
      <comments>http://vasters.com/clemensv/CommentView,guid,318767eb-9c65-41ef-b583-b5220b7e3bc3.aspx</comments>
      <category>Technology</category>
      <category>Technology/ASP.NET</category>
      <category>Blog</category>
    </item>
    <item>
      <trackback:ping>http://vasters.com/clemensv/Trackback.aspx?guid=a1e55c02-bb9e-4b27-bab9-c8ad51d1b250</trackback:ping>
      <pingback:server>http://vasters.com/clemensv/pingback.aspx</pingback:server>
      <pingback:target>http://vasters.com/clemensv/PermaLink,guid,a1e55c02-bb9e-4b27-bab9-c8ad51d1b250.aspx</pingback:target>
      <dc:creator />
      <wfw:comment>http://vasters.com/clemensv/CommentView,guid,a1e55c02-bb9e-4b27-bab9-c8ad51d1b250.aspx</wfw:comment>
      <wfw:commentRss>http://vasters.com/clemensv/SyndicationService.asmx/GetEntryCommentsRss?guid=a1e55c02-bb9e-4b27-bab9-c8ad51d1b250</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
          <strong>Productivity and ASP.NET<br /></strong>
          <br />
It took me less than an hour to implement, test and deploy pingback support for
this blog here using ASP.NET and <a href="http://xml-rpc.net/">XML-RPC.NET</a> (and
that includes reading the spec). Yesterday and today, it took me less than 2hrs
total (including addressing two comments/suggestions/corrections from <a href="http://www.interwingly.net">Sam
Ruby</a>) to get <a href="http://www.intertwingly.net/wiki/pie/FrontPage">(n)echo/pie/atom </a>support
working so that it can be <a href="http://feeds.archive.org/validator/check?url=http://62.138.131.149/clemensv/BlogXBrowsing.asmx/GetEcho">validated</a>.
</p>
        <img width="0" height="0" src="http://vasters.com/clemensv/aggbug.ashx?id=a1e55c02-bb9e-4b27-bab9-c8ad51d1b250" />
      </body>
      <title>Productivity and ASP.NET</title>
      <guid isPermaLink="false">http://vasters.com/clemensv/PermaLink,guid,a1e55c02-bb9e-4b27-bab9-c8ad51d1b250.aspx</guid>
      <link>http://vasters.com/clemensv/2003/07/18/Productivity+And+ASPNET.aspx</link>
      <pubDate>Fri, 18 Jul 2003 20:28:35 GMT</pubDate>
      <description>&lt;p&gt;
&lt;strong&gt;Productivity and ASP.NET&lt;br&gt;
&lt;/strong&gt;
&lt;br&gt;
It took me&amp;nbsp;less than an hour to implement, test and deploy pingback support for
this blog here using ASP.NET and &lt;a href="http://xml-rpc.net/"&gt;XML-RPC.NET&lt;/a&gt;&amp;nbsp;(and
that includes reading the spec). Yesterday and today, it took me&amp;nbsp;less than&amp;nbsp;2hrs
total (including addressing two comments/suggestions/corrections from &lt;a href="http://www.interwingly.net"&gt;Sam
Ruby&lt;/a&gt;) to get &lt;a href="http://www.intertwingly.net/wiki/pie/FrontPage"&gt;(n)echo/pie/atom &lt;/a&gt;support
working so that it can be &lt;a href="http://feeds.archive.org/validator/check?url=http://62.138.131.149/clemensv/BlogXBrowsing.asmx/GetEcho"&gt;validated&lt;/a&gt;.
&lt;/p&gt;
&lt;img width="0" height="0" src="http://vasters.com/clemensv/aggbug.ashx?id=a1e55c02-bb9e-4b27-bab9-c8ad51d1b250" /&gt;</description>
      <comments>http://vasters.com/clemensv/CommentView,guid,a1e55c02-bb9e-4b27-bab9-c8ad51d1b250.aspx</comments>
      <category>Technology</category>
      <category>Technology/ASP.NET</category>
    </item>
    <item>
      <trackback:ping>http://vasters.com/clemensv/Trackback.aspx?guid=3b320ae2-4ce4-42ac-8ce2-16f6058da0c3</trackback:ping>
      <pingback:server>http://vasters.com/clemensv/pingback.aspx</pingback:server>
      <pingback:target>http://vasters.com/clemensv/PermaLink,guid,3b320ae2-4ce4-42ac-8ce2-16f6058da0c3.aspx</pingback:target>
      <dc:creator />
      <wfw:comment>http://vasters.com/clemensv/CommentView,guid,3b320ae2-4ce4-42ac-8ce2-16f6058da0c3.aspx</wfw:comment>
      <wfw:commentRss>http://vasters.com/clemensv/SyndicationService.asmx/GetEntryCommentsRss?guid=3b320ae2-4ce4-42ac-8ce2-16f6058da0c3</wfw:commentRss>
      <slash:comments>1</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <strong>Redirecting from Radio and picking
up the links using ASP.NET</strong>
        <br />
        <p>
One of the biggest hurdles in moving away from Radio and moving blogs in general is,
of course, to take all the inbound links with you. To make that work (as you should
be able to see if you are hitting any of the permalinks of my old blog), I've
written a little HttpModule that will evaluate a set of regular expressions and apply
them to the incoming URLs.  
</p>
        <p>
So, first I need to get the links to redirect away from the radio site. In Radio,
I've updated the home page template and added the following two things:
</p>
        <p>
1. In the &lt;head&gt; section, I added:<br /><font face="Courier New, Courier, Monospace" size="2">&lt;META http-equiv="REFRESH"
content="2; URL=http://staff.newtelligence.net/clemensv/fromradio.ashx?&lt;%radio.weblog.getUrl()+path%&gt;"&gt;</font></p>
        <p>
This will, if the requested page is */2003/07/18.html indeed redirect to */2003/07/18.<strong>txt</strong>,
but that's acceptable for what's happening next. The redirect will happen after two
seconds, because I really want the following JavaScript to fire first.
</p>
        <p>
2. Right after &lt;body&gt;, I added:<br /><font face="Courier New, Courier, Monospace" size="2">&lt;SCRIPT language="JavaScript"&gt;<br />
   function redirectToNewSite()<br />
   {<br />
     location.href="http://staff.newtelligence.net/clemensv"+<br />
                     
"/fromradio.ashx?"+location.href;<br />
   } <br />
   redirectToNewSite();<br />
&lt;/SCRIPT&gt;</font></p>
        <p>
That script will simply redirect using the location.href property. The big difference
here is that it will take the bookmark portion with it, which the META tag
can't do. So if you are hitting */2003/07/17.html#a219, the target site will be able
to pick up the bookmark.
</p>
        <p>
After I did that update, I re-published all weblog entries via Radio and now all of
the pages are redirecting automatically to http://staff.newtelligence.net/clemensv/fromradio.ashx?...
</p>
        <p>
On the server, my configuration looks like this:
</p>
        <pre>&lt;configuration&gt;<br />
... &lt;newtelligence.Weblog.UrlMapper&gt;<br />
&lt;!-- the matchExpression values are line-wrapped to fit here!! --&gt; &lt;add matchExpression="(?&amp;lt;basedir&amp;gt;/[\w\.]+)/fromradio\.ashx\?<br />
http\://radio\.weblogs\.com/0108971/(?&amp;lt;year&amp;gt;\d+)/<br />
(?&amp;lt;month&amp;gt;\d+)/(?&amp;lt;day&amp;gt;\d+).*" 
<br />
mapTo="{basedir}/default.aspx?date={year}-{month}-{day}" /&gt; &lt;add matchExpression="(?&amp;lt;basedir&amp;gt;/[\w\.]+)/fromradio\.ashx\?<br />
http\://radio\.weblogs\.com/0108971/(?&amp;lt;year&amp;gt;\d+)/<br />
(?&amp;lt;month&amp;gt;\d+).*" 
<br />
mapTo="{basedir}/default.aspx?date={year}-{month}-28" /&gt; &lt;add matchExpression="(?&amp;lt;basedir&amp;gt;/[\w\.]+)/fromradio\.ashx\?<br />
http\://radio\.weblogs\.com/0108971/(?&amp;lt;year&amp;gt;\d+).*" 
<br />
mapTo="{basedir}/default.aspx?date={year}-12-31" /&gt; &lt;add matchExpression="(?&amp;lt;basedir&amp;gt;/[\w\.]+)/fromradio\.ashx\?<br />
http\://radio\.weblogs\.com/0108971.*" 
<br />
mapTo="{basedir}/default.aspx" /&gt; &lt;/newtelligence.Weblog.UrlMapper&gt; &lt;/configuration&gt; </pre>
        <p>
These regular expressions assume that the weblog is in a subweb (which it is) and
look for "fromradio.ashx?http://radio.weblogs.com/0108971/" in the URL that's passed
in. I don't really have a fromradio.ashx handler registered. Using the *.ashx suffix
I am just telling IIS to hand the request over to ASP.NET in order
to pass the request down the pipeline. The mapTo expression then picks up what
I have been extracting from the incoming URL and maps that to a real URL here.
</p>
        <p>
And here's the HttpModule that does the trick:
</p>
        <pre>namespace newtelligence.Weblog.Web
{
  using System;
  using System.Web;
  using System.Web.UI;
  using System.Configuration;
  using System.Text;
  using System.Collections;
  using System.Collections.Specialized;
  using System.Text.RegularExpressions;

  // reqister this section handler as "newtelligence.Weblog.UrlMapper"
    public class UrlMapperModuleSectionHandler :
    NameValueSectionHandler
  {
    public static string ConfigSectionName
    {
      get
      {
        return "newtelligence.Weblog.UrlMapper";
      }
    }
    public UrlMapperModuleSectionHandler()
    {
    
    }
    protected override string KeyAttributeName
    {
      get { return "matchExpression"; }
    }
    protected override string ValueAttributeName
    {
      get { return "mapTo"; }
    }
  }
  public class UrlMapperModule : IHttpModule
  {
    private EventHandler onBeginRequest;
    
    public UrlMapperModule()
    {
      onBeginRequest = new EventHandler(this.HandleBeginRequest);
    }
    void IHttpModule.Dispose()
    {
    }
    void IHttpModule.Init(HttpApplication context)
    {
      context.BeginRequest += onBeginRequest;
    }
  
    private void HandleBeginRequest( object sender, EventArgs evargs )
    {
      HttpApplication app = sender as HttpApplication;
    
      if ( app != null )
      {
        string requestUrl = app.Context.Request.Url.PathAndQuery;
        NameValueCollection urlMaps = (NameValueCollection)<br />
System.Configuration.ConfigurationSettings.GetConfig(<br />
UrlMapperModuleSectionHandler.ConfigSectionName);         if ( urlMaps != null )
        {           for ( int loop=0;loop&lt;urlMaps.Count;loop++)
          {             string matchExpression = urlMaps.GetKey(loop);
            Regex regExpression = new Regex(matchExpression);
            Match matchUrl = regExpression.Match(requestUrl);
            if ( matchUrl != null &amp;&amp; matchUrl.Success )
            {               string mapTo = urlMaps[matchExpression];
              Regex regMap = new Regex("\\{(?&lt;expr&gt;\\w+)\\}");
              foreach( Match matchExpr in regMap.Matches(mapTo) )
              {
                Group urlExpr;
                string expr = matchExpr.Groups["expr"].Value;
                urlExpr = matchUrl.Groups[expr];
                if ( urlExpr != null )
                {
                  mapTo = mapTo.Replace("{"+expr+"}",urlExpr.Value);
                }
              }
              app.Context.RewritePath(mapTo);
              break;
            }           }
        }       }
    }   } } </pre>
        <pre>
        </pre>
        <p>
Finally, here's the registration for the config section handler, that should not be
forgotten:
</p>
        <pre>&lt;configuration&gt;
  &lt;configSections&gt;
   &lt;section name="newtelligence.Weblog.UrlMapper" 
<br />
type="newtelligence.Weblog.Web.UrlMapperModuleSectionHandler, WeblogX" /&gt; &lt;/configSections&gt;
... &lt;/configuration&gt;</pre>
        <pre>
        </pre>
        <p>
Voila! Works like a charm as you can see.here.
</p>
        <img width="0" height="0" src="http://vasters.com/clemensv/aggbug.ashx?id=3b320ae2-4ce4-42ac-8ce2-16f6058da0c3" />
      </body>
      <title>Redirecting from Radio and picking up the links using ASP.NET</title>
      <guid isPermaLink="false">http://vasters.com/clemensv/PermaLink,guid,3b320ae2-4ce4-42ac-8ce2-16f6058da0c3.aspx</guid>
      <link>http://vasters.com/clemensv/2003/07/18/Redirecting+From+Radio+And+Picking+Up+The+Links+Using+ASPNET.aspx</link>
      <pubDate>Fri, 18 Jul 2003 18:00:07 GMT</pubDate>
      <description>&lt;strong&gt;Redirecting from Radio and picking up the links using ASP.NET&lt;/strong&gt;
&lt;br&gt;
&lt;p&gt;
One of the biggest hurdles in moving away from Radio and moving blogs in general is,
of course, to take all the inbound links with you. To make that work (as you&amp;nbsp;should
be able to&amp;nbsp;see if you are hitting any of the permalinks of my old blog), I've
written a little HttpModule that will evaluate a set of regular expressions and apply
them to&amp;nbsp;the incoming URLs.&amp;nbsp;&amp;nbsp;
&lt;/p&gt;
&lt;p&gt;
So, first I need to get the links to redirect away from the radio site. In Radio,
I've updated the home page template and added&amp;nbsp;the following two things:
&lt;/p&gt;
&lt;p&gt;
1. In the &amp;lt;head&amp;gt; section, I added:&lt;br&gt;
&lt;font face="Courier New, Courier, Monospace" size=2&gt;&amp;lt;META http-equiv="REFRESH"
content="2; URL=http://staff.newtelligence.net/clemensv/fromradio.ashx?&amp;lt;%radio.weblog.getUrl()+path%&amp;gt;"&amp;gt;&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
This&amp;nbsp;will, if the requested page is */2003/07/18.html indeed redirect to */2003/07/18.&lt;strong&gt;txt&lt;/strong&gt;,
but that's acceptable for what's happening next. The redirect will happen after two
seconds, because I really want the following JavaScript to fire first.
&lt;/p&gt;
&lt;p&gt;
2. Right after &amp;lt;body&amp;gt;, I added:&lt;br&gt;
&lt;font face="Courier New, Courier, Monospace" size=2&gt;&amp;lt;SCRIPT language="JavaScript"&amp;gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp; function redirectToNewSite()&lt;br&gt;
&amp;nbsp;&amp;nbsp; {&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; location.href="http://staff.newtelligence.net/clemensv"+&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
"/fromradio.ashx?"+location.href;&lt;br&gt;
&amp;nbsp;&amp;nbsp; }&amp;nbsp;&lt;br&gt;
&amp;nbsp;&amp;nbsp; redirectToNewSite();&lt;br&gt;
&amp;lt;/SCRIPT&amp;gt;&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
That script will simply redirect using the location.href property. The big difference
here is that it will take the&amp;nbsp;bookmark portion&amp;nbsp;with it, which the META tag
can't do. So if you are hitting */2003/07/17.html#a219, the target site will be able
to pick up the bookmark.
&lt;/p&gt;
&lt;p&gt;
After I did that update, I re-published all weblog entries via Radio and now all of
the pages are redirecting automatically to http://staff.newtelligence.net/clemensv/fromradio.ashx?...
&lt;/p&gt;
&lt;p&gt;
On the server, my configuration looks like this:
&lt;/p&gt;
&lt;pre&gt;&amp;lt;configuration&amp;gt;&lt;br&gt;
... &amp;lt;newtelligence.Weblog.UrlMapper&amp;gt;&lt;br&gt;
&amp;lt;!-- the matchExpression values are line-wrapped to fit here!! --&amp;gt; &amp;lt;add matchExpression="(?&amp;amp;lt;basedir&amp;amp;gt;/[\w\.]+)/fromradio\.ashx\?&lt;br&gt;
http\://radio\.weblogs\.com/0108971/(?&amp;amp;lt;year&amp;amp;gt;\d+)/&lt;br&gt;
(?&amp;amp;lt;month&amp;amp;gt;\d+)/(?&amp;amp;lt;day&amp;amp;gt;\d+).*" 
&lt;br&gt;
mapTo="{basedir}/default.aspx?date={year}-{month}-{day}" /&amp;gt; &amp;lt;add matchExpression="(?&amp;amp;lt;basedir&amp;amp;gt;/[\w\.]+)/fromradio\.ashx\?&lt;br&gt;
http\://radio\.weblogs\.com/0108971/(?&amp;amp;lt;year&amp;amp;gt;\d+)/&lt;br&gt;
(?&amp;amp;lt;month&amp;amp;gt;\d+).*" 
&lt;br&gt;
mapTo="{basedir}/default.aspx?date={year}-{month}-28" /&amp;gt; &amp;lt;add matchExpression="(?&amp;amp;lt;basedir&amp;amp;gt;/[\w\.]+)/fromradio\.ashx\?&lt;br&gt;
http\://radio\.weblogs\.com/0108971/(?&amp;amp;lt;year&amp;amp;gt;\d+).*" 
&lt;br&gt;
mapTo="{basedir}/default.aspx?date={year}-12-31" /&amp;gt; &amp;lt;add matchExpression="(?&amp;amp;lt;basedir&amp;amp;gt;/[\w\.]+)/fromradio\.ashx\?&lt;br&gt;
http\://radio\.weblogs\.com/0108971.*" 
&lt;br&gt;
mapTo="{basedir}/default.aspx" /&amp;gt; &amp;lt;/newtelligence.Weblog.UrlMapper&amp;gt; &amp;lt;/configuration&amp;gt; &lt;/pre&gt;
&lt;p&gt;
These regular expressions assume that the weblog is in a subweb (which it is) and
look for "fromradio.ashx?http://radio.weblogs.com/0108971/" in the URL that's passed
in. I don't really have a fromradio.ashx handler registered. Using the *.ashx suffix
I am just telling IIS to hand&amp;nbsp;the request&amp;nbsp;over to ASP.NET&amp;nbsp;in order
to&amp;nbsp;pass the request down the pipeline. The mapTo expression then picks up what
I have been extracting from the incoming URL and maps that to a real URL here.
&lt;/p&gt;
&lt;p&gt;
And here's the HttpModule that does the trick:
&lt;/p&gt;
&lt;pre&gt;namespace&amp;nbsp;newtelligence.Weblog.Web
{
&amp;nbsp;&amp;nbsp;using&amp;nbsp;System;
&amp;nbsp;&amp;nbsp;using&amp;nbsp;System.Web;
&amp;nbsp;&amp;nbsp;using&amp;nbsp;System.Web.UI;
&amp;nbsp;&amp;nbsp;using&amp;nbsp;System.Configuration;
&amp;nbsp;&amp;nbsp;using&amp;nbsp;System.Text;
&amp;nbsp;&amp;nbsp;using&amp;nbsp;System.Collections;
&amp;nbsp;&amp;nbsp;using&amp;nbsp;System.Collections.Specialized;
&amp;nbsp;&amp;nbsp;using&amp;nbsp;System.Text.RegularExpressions;

&amp;nbsp;&amp;nbsp;//&amp;nbsp;reqister&amp;nbsp;this&amp;nbsp;section handler as&amp;nbsp;"newtelligence.Weblog.UrlMapper"
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public&amp;nbsp;class&amp;nbsp;UrlMapperModuleSectionHandler&amp;nbsp;:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;NameValueSectionHandler
&amp;nbsp;&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public&amp;nbsp;static&amp;nbsp;string&amp;nbsp;ConfigSectionName
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;get
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;"newtelligence.Weblog.UrlMapper";
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public&amp;nbsp;UrlMapperModuleSectionHandler()
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;protected&amp;nbsp;override&amp;nbsp;string&amp;nbsp;KeyAttributeName
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;get&amp;nbsp;{&amp;nbsp;return&amp;nbsp;"matchExpression";&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;protected&amp;nbsp;override&amp;nbsp;string&amp;nbsp;ValueAttributeName
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;get&amp;nbsp;{&amp;nbsp;return&amp;nbsp;"mapTo";&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;public&amp;nbsp;class&amp;nbsp;UrlMapperModule&amp;nbsp;:&amp;nbsp;IHttpModule
&amp;nbsp;&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;private&amp;nbsp;EventHandler&amp;nbsp;onBeginRequest;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public&amp;nbsp;UrlMapperModule()
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;onBeginRequest&amp;nbsp;=&amp;nbsp;new&amp;nbsp;EventHandler(this.HandleBeginRequest);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;void&amp;nbsp;IHttpModule.Dispose()
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;void&amp;nbsp;IHttpModule.Init(HttpApplication&amp;nbsp;context)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;context.BeginRequest&amp;nbsp;+=&amp;nbsp;onBeginRequest;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;private&amp;nbsp;void&amp;nbsp;HandleBeginRequest(&amp;nbsp;object&amp;nbsp;sender,&amp;nbsp;EventArgs&amp;nbsp;evargs&amp;nbsp;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;HttpApplication&amp;nbsp;app&amp;nbsp;=&amp;nbsp;sender&amp;nbsp;as&amp;nbsp;HttpApplication;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;(&amp;nbsp;app&amp;nbsp;!=&amp;nbsp;null&amp;nbsp;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;string&amp;nbsp;requestUrl&amp;nbsp;=&amp;nbsp;app.Context.Request.Url.PathAndQuery;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;NameValueCollection&amp;nbsp;urlMaps&amp;nbsp;=&amp;nbsp;(NameValueCollection)&lt;br&gt;
System.Configuration.ConfigurationSettings.GetConfig(&lt;br&gt;
UrlMapperModuleSectionHandler.ConfigSectionName); &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;(&amp;nbsp;urlMaps&amp;nbsp;!=&amp;nbsp;null&amp;nbsp;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{ &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;for&amp;nbsp;(&amp;nbsp;int&amp;nbsp;loop=0;loop&amp;lt;urlMaps.Count;loop++)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{ &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;string&amp;nbsp;matchExpression&amp;nbsp;=&amp;nbsp;urlMaps.GetKey(loop);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Regex&amp;nbsp;regExpression&amp;nbsp;=&amp;nbsp;new&amp;nbsp;Regex(matchExpression);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Match&amp;nbsp;matchUrl&amp;nbsp;=&amp;nbsp;regExpression.Match(requestUrl);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;(&amp;nbsp;matchUrl&amp;nbsp;!=&amp;nbsp;null&amp;nbsp;&amp;amp;&amp;amp;&amp;nbsp;matchUrl.Success&amp;nbsp;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{ &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;string&amp;nbsp;mapTo&amp;nbsp;=&amp;nbsp;urlMaps[matchExpression];
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Regex&amp;nbsp;regMap&amp;nbsp;=&amp;nbsp;new&amp;nbsp;Regex("\\{(?&amp;lt;expr&amp;gt;\\w+)\\}");
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;foreach(&amp;nbsp;Match&amp;nbsp;matchExpr&amp;nbsp;in&amp;nbsp;regMap.Matches(mapTo)&amp;nbsp;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Group&amp;nbsp;urlExpr;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;string&amp;nbsp;expr&amp;nbsp;=&amp;nbsp;matchExpr.Groups["expr"].Value;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;urlExpr&amp;nbsp;=&amp;nbsp;matchUrl.Groups[expr];
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;(&amp;nbsp;urlExpr&amp;nbsp;!=&amp;nbsp;null&amp;nbsp;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;mapTo&amp;nbsp;=&amp;nbsp;mapTo.Replace("{"+expr+"}",urlExpr.Value);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;app.Context.RewritePath(mapTo);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;break;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;} &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;} &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;} &amp;nbsp;&amp;nbsp;} } &lt;/pre&gt;
&lt;pre&gt;&lt;/pre&gt;
&lt;p&gt;
Finally, here's the registration for the config section handler, that should not be
forgotten:
&lt;/p&gt;
&lt;pre&gt;&amp;lt;configuration&amp;gt;
  &amp;lt;configSections&amp;gt;
   &amp;lt;section name="newtelligence.Weblog.UrlMapper" 
&lt;br&gt;
type="newtelligence.Weblog.Web.UrlMapperModuleSectionHandler, WeblogX" /&amp;gt; &amp;lt;/configSections&amp;gt;
... &amp;lt;/configuration&amp;gt;&lt;/pre&gt;
&lt;pre&gt;&lt;/pre&gt;
&lt;p&gt;
Voila! Works like a charm as you can see.here.
&lt;/p&gt;
&lt;img width="0" height="0" src="http://vasters.com/clemensv/aggbug.ashx?id=3b320ae2-4ce4-42ac-8ce2-16f6058da0c3" /&gt;</description>
      <comments>http://vasters.com/clemensv/CommentView,guid,3b320ae2-4ce4-42ac-8ce2-16f6058da0c3.aspx</comments>
      <category>Technology</category>
      <category>Technology/ASP.NET</category>
      <category>Blog</category>
    </item>
  </channel>
</rss>