<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rssdatehelper="urn:rssdatehelper"><channel><title>Going Deeper</title><link>http://deeper.webangelo.net</link><pubDate></pubDate><generator>umbraco</generator><description>Going below the surface to highlight technical items in Umbraco and .Net.</description><language>en</language><item><title>New Training Classes for Fall 2010</title><link>http://deeper.webangelo.net/2010/8/4/new-training-classes-for-fall-2010.aspx</link><pubDate>Wed, 04 Aug 2010 00:00:00 GMT</pubDate><guid>http://deeper.webangelo.net/2010/8/4/new-training-classes-for-fall-2010.aspx</guid><description><![CDATA[ 
<p>Two new North America Umbraco Certification training classes are
being offered for the fall of 2010.</p>

<h2>Long Island, NY</h2>

<p>For the first time ever, Umbraco Certification classes are being
offered in the greater New York area.&nbsp; Join us at the Hilton
Long Island/Huntington, where we will be offering Level 1 class on
September 13 &amp; 14 and Level 2 class on September 15 &amp;
16.</p>

<p>Interest has been high in New York for Umbraco Certification and
we expect these classes to sell out soon.&nbsp; September is coming
quickly.&nbsp; Don't delay, get your seats today.</p>

<p>You can find more information and sign up for the classes
here:</p>

<p><a href="http://umbraco-longisland.eventbrite.com"
title="Long Island Training Event Page">http://umbraco-longisland.eventbrite.com</a></p>

<h2>Tallahassee, FL</h2>

<p>Florida is also seeing its first Umbraco Certification class in
November.&nbsp; Join us in Florida's beautiful State Capital with
Level 1 classes taking place November 2 &amp; 3 and Level 2 classes
taking place November 4 &amp; 5.</p>

<p>November is a great time to be in Florida and we are already
seeing lots of interest in this class.&nbsp; Don't put off signing
up or you may end up missing out on this opportunity for Training
in the Sunshine State.</p>

<p>You can find more information and sign up for the classes
here:</p>

<p><a href="http://umbraco-tallahassee.eventbrite.com"
title="Tallahassee Certification Class Event Page">http://umbraco-tallahassee.eventbrite.com</a></p>

<h2>Contact Us</h2>

<p>If you have any questions about these classes or if you are
interested in hosting a class in your area please don't hesitate to
<a href="http://webangelo.net/contact-us.aspx" title="Contact Us">contact us</a>.</p>
]]></description></item><item><title>Webangelo is now offering Umbraco Training in North America</title><link>http://deeper.webangelo.net/2010/7/6/webangelo-is-now-offering-umbraco-training-in-north-america.aspx</link><pubDate>Tue, 06 Jul 2010 00:00:00 GMT</pubDate><guid>http://deeper.webangelo.net/2010/7/6/webangelo-is-now-offering-umbraco-training-in-north-america.aspx</guid><description><![CDATA[ 
<p>Christopher Rushing has been approved to offer Umbraco certified
training for North America!&nbsp; This combines his love of Umbraco
with his enjoyment of sharing knowledge with others.</p>

<h2>North American Umbraco Training Team</h2>

<p>The North American Umbraco Training Team currently consists of
Paul Sterling an Umbraco HQ member and core team member and our
very own Christopher Rushing.&nbsp; Not only will public training
courses be offered in various places in the US and Canada, but the
team will also work to let more people know about Umbraco here in
North America.</p>

<h2>More Umbraco Courses coming soon</h2>

<p>In coordination with Paul Sterling, new courses are being set up
in key areas for the fall.&nbsp; Keep an eye on this blog and the
<a href="http://umbraco.org/training/training-in-north-america"
target="_blank" title="Umbraco Training in North America">Official
Umbraco North America Training</a> page for more details.</p>

<h2>Unscheduled Training also Available</h2>

<p>Public Training is by far the best experience for learning
Umbraco as it brings together a mix of backgrounds in one room
learning and sharing with each other.&nbsp; Unfortunately sometimes
folks are unable to attend a scheduled public training due to
timing or a variety of factors.&nbsp; Never fear!&nbsp; We may be
able to bring the training to you!&nbsp; If you have a room
available and are willing to host a public training in your area we
are interested in hearing from you.&nbsp; If you can't do that,
just contact us.&nbsp; We'll work hard to find the right scenario
for you.</p>
]]></description></item><item><title>Implemented Umbraco 4.1 Beta II in MySQL</title><link>http://deeper.webangelo.net/2010/5/28/implemented-umbraco-41-beta-ii-in-mysql.aspx</link><pubDate>Fri, 28 May 2010 00:00:00 GMT</pubDate><guid>http://deeper.webangelo.net/2010/5/28/implemented-umbraco-41-beta-ii-in-mysql.aspx</guid><description><![CDATA[ 
<p>So I finally had some time to implement 4.1 Beta II in a test
site.&nbsp; For various reasons I decided to use MySQL.&nbsp; I'm
still running it through the paces, but here are some quick notes
on my implementation experience.</p>

<h2>Install</h2>

<p>After copying the files to my test site location (shared
hosting) and setting the permissions I tried to browse to the site
to initialize the install scripts.&nbsp; Unfortunately I
immediately received a number of errors which some of the postings
on our.umbraco.org indicated were related to the medium trust
install even though no trust settings were set and the Umbraco
Setting [umbracoUseMediumTrust] was set to false. As my host allows
full trust I added a &lt;trust level="Full" /&gt; tag and was
fine.</p>

<p>The rest of the configuration went as it usually does and I was
able to successfully install the Umbraco Instance.</p>

<h2>Site Setup</h2>

<p>After install I immediately started adding Document Types and
Templates and installing my favorite Packages.&nbsp; Everything
went smoothly until I tried to add my home page to the
content.&nbsp; The UI generated an error bubble regarding a missing
table.</p>

<p>It turns out that the install scripts for the 4.1 Beta II for
MySQL are missing the Create Table calls for the CMSPREVIEWXML
table.&nbsp; So I took the MSSQL scripts and ported the related
calls to MySQL so I could run them there.&nbsp; Below is my
script.&nbsp; Be aware that it is probably not the official Umbraco
version that they will have in the final install, but it seems to
have worked for me.</p>

<pre>
CREATE TABLE CMSPREVIEWXML(
 nodeId int NOT NULL,
 versionId CHAR(36) NOT NULL,
 timestamp DATETIME NOT NULL,
 xml LONGTEXT NOT NULL
);


ALTER TABLE CMSPREVIEWXML ADD CONSTRAINT PK_cmsContentPreviewXml PRIMARY KEY CLUSTERED (nodeId, versionId);
</pre>

<h3>Installing Packages</h3>

<p>One final note is that not every package will work with version
4.1 Beta II.&nbsp; Make sure you test any package you add while you
are playing with Beta II.</p>
]]></description></item><item><title>Ajax - Don't You Love Me?</title><link>http://deeper.webangelo.net/2010/4/28/ajax---don't-you-love-me.aspx</link><pubDate>Wed, 28 Apr 2010 00:00:00 GMT</pubDate><guid>http://deeper.webangelo.net/2010/4/28/ajax---don't-you-love-me.aspx</guid><description><![CDATA[ 
<p>As the .Net 3.5 Framework becomes more prevalent in the wild
(and now .Net 4.0) we're starting to see some versioning issues
with the ASP.NET AJAX modules. These issues can raise their heads
in numerous ways, but the basic issue is the same, version
conflicts. Umbraco also sees some of these issue occasionally,
resulting in some head-scratchers in the forum.</p>

<h2>Background</h2>

<p>Prior to .Net 3.5, AJAX was a separate install which had to be
downloaded and integrated separately. Many tools and sites built
prior to .Net 3.5 or targeting .Net 2.0 or .Net 3.0 which wanted
AJAX functionality often used this previous version, the most
common still in the wild being 1.0.61025.0. This is often seen in
the following references in the web.config...</p>

<pre>
  &lt;configSections&gt;
    &lt;sectionGroup name="system.web.extensions" type="System.Web.Configuration.SystemWebExtensionsSectionGroup, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"&gt;
      &lt;sectionGroup name="scripting" type="System.Web.Configuration.ScriptingSectionGroup, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"&gt;
        &lt;section name="scriptResourceHandler" type="System.Web.Configuration.ScriptingScriptResourceHandlerSection, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" requirePermission="false" allowDefinition="MachineToApplication" /&gt;
        &lt;sectionGroup name="webServices" type="System.Web.Configuration.ScriptingWebServicesSectionGroup, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"&gt;
          &lt;section name="jsonSerialization" type="System.Web.Configuration.ScriptingJsonSerializationSection, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" requirePermission="false" allowDefinition="Everywhere" /&gt;
          &lt;section name="profileService" type="System.Web.Configuration.ScriptingProfileServiceSection, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" requirePermission="false" allowDefinition="MachineToApplication" /&gt;
          &lt;section name="authenticationService" type="System.Web.Configuration.ScriptingAuthenticationServiceSection, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" requirePermission="false" allowDefinition="MachineToApplication" /&gt;
        &lt;/sectionGroup&gt;
      &lt;/sectionGroup&gt;
    &lt;/sectionGroup&gt;
  &lt;/configSections&gt;
  &lt;system.web&gt;
    &lt;httpModules&gt;
      &lt;add name="ScriptModule" type="System.Web.Handlers.ScriptModule, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" /&gt;
    &lt;/httpModules&gt;
    &lt;httpHandlers&gt;
      &lt;remove path="*.asmx" verb="*" /&gt;
      &lt;add path="*.asmx" verb="*" type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" /&gt;
      &lt;add path="*_AppService.axd" verb="*" type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" /&gt;
      &lt;add path="ScriptResource.axd" verb="GET,HEAD" type="System.Web.Handlers.ScriptResourceHandler, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" /&gt;
    &lt;/httpHandlers&gt;
    &lt;compilation defaultLanguage="c#" debug="false" batch="false"&gt;
      &lt;assemblies&gt;
        &lt;add assembly="System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" /&gt;
        &lt;add assembly="System.Design, Version=2.0.0.0, Culture=neutral, PublicKeyToken=B03F5F7F11D50A3A" /&gt;
        &lt;add assembly="System.Web.Extensions.Design, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" /&gt;
      &lt;/assemblies&gt;
    &lt;/compilation&gt;
  &lt;/system.web&gt;
</pre>

<p>Also if you running on IIS 7.0 and using the new Integrated Mode
you might also see the following:</p>

<pre>
  &lt;!-- IIS 7 Integrated Mode Configuration --&gt;
  &lt;system.webServer&gt;
    &lt;modules&gt;  
      &lt;remove name="ScriptModule"/&gt;
      &lt;add name="ScriptModule" preCondition="managedHandler" type="System.Web.Handlers.ScriptModule, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/&gt;
    &lt;/modules&gt;
    &lt;handlers accessPolicy="Read, Write, Script, Execute"&gt;
      &lt;remove name="WebServiceHandlerFactory-Integrated"/&gt;
      &lt;remove name="ScriptHandlerFactory"/&gt;
      &lt;remove name="ScriptHandlerFactoryAppServices"/&gt;
      &lt;remove name="ScriptResource"/&gt;
      &lt;add name="ScriptHandlerFactory" verb="*" path="*.asmx" preCondition="integratedMode" type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/&gt;
      &lt;add name="ScriptHandlerFactoryAppServices" verb="*" path="*_AppService.axd" preCondition="integratedMode" type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/&gt;
      &lt;add name="ScriptResource" preCondition="integratedMode" verb="GET,HEAD" path="ScriptResource.axd" type="System.Web.Handlers.ScriptResourceHandler, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/&gt;
    &lt;/handlers&gt;
  &lt;/system.webServer&gt;
</pre>

<p>Unfortunately, with .Net 3.5 and now 4.0 web applications having
AJAX support included, issues are cropping up with one version of
the .Net AJAX assemblies being used in the main web application and
others being used in modules or packages.</p>

<h2>Symptoms</h2>

<p>The two main errors that I've seen are the following:</p>

<p>When installing Umbraco on a Windows 7 box or Windows Server
2008 you might see the following even though you have a newer
version of Systen.Web.Extensions on the box.</p>

<pre>
Could not load file or assembly 'System.Web.Extensions,  Version=1.0.61025.0,  Culture=neutral, PublicKeyToken=31bf3856ad364e35' or one of its  dependencies.
</pre>

<p>A stranger issue is when you see something similar the
following:</p>

<pre>
<span>[</span><span>InvalidCastException</span><span>:</span> <span>&nbsp;</span>    <span>Unable</span> <span>to cast</span> <span>object</span> <span>of type</span> <span>'System.Web.Configuration.ScriptingScriptResourceHandlerSection'</span> <span>to type</span> <span>'System.Web.Configuration.ScriptingScriptResourceHandlerSection'</span><span>.</span><span>&nbsp;</span>       
</pre>

<p>or</p>

<pre>
<span>... type (System.Web.UI.UpdatePanel) is not  compatible with the type of control (System.Web.UI.UpdatePanel)</span>
</pre>

<h2>What's Going On?</h2>

<p>In the first case we simply have a case where the older <a
href="http://www.microsoft.com/downloads/details.aspx?FamilyID=ca9d90fa-e8c9-42e3-aa19-08e2c027f5d6&amp;displaylang=en"
 target="_blank">ASP.Net AJAX 1.0 framework</a> isn't installed on
the machine in question but is being referenced somewhere.&nbsp;
You could install it, of course, and you may need to, however once
you do, if you have the .Net 3.5 Framework installed&nbsp; as well,
you may one day find yourself dealing with the other symptoms
described, so read on to avoid that future headache.</p>

<p>The other two errors (and other similar ones) are version
conflicts.&nbsp; A quick gloss&nbsp; on this.&nbsp; A long time ago
(in OS years) there was a situation called DLL Hell in which the
installation scripts for one program would overwrite dlls needed by
another program with newer versions or even versions made for
another OS causing unexpected failures.&nbsp; To help avoid this
issue, Microsoft started allowing multiple versions of the same dll
to be installed at the same time.&nbsp; Compiled assemblies
reference a specific version of a dll to avoid this versioning
issue.</p>

<p>For our specific discussion, this means that you can have two
versions of the System.Web.Extensions.dll at the same time.&nbsp;
Therefore in your ASP.Net web application (i.e. Umbraco) you may
have components referencing a newer version of a dll than is
referenced in the web.config.&nbsp; This can cause the strange
scenario where your external page or control (.aspx / .ascx)
references a type and gets the 1.X version but the code behind
references the same object but knows about a 3.5 version of the
type.&nbsp; So, as far as the computer knows, the two items are not
the same, thus those Type and Cast exceptions.</p>

<h2>Solution</h2>

<h3>Missing DLLs</h3>

<p>For the missing dlls issue, you have a couple of things you can
try.&nbsp; The solution for Versioning (below) may be sufficient,
especially if you update the machine.config.&nbsp; Another option,
if you have access to the source you can update the references and
recompile.&nbsp; If those aren't viable or don't work, you may have
to install the previous version of the ASP.Net AJAX framework, but
if you do this, make sure you set up a binding redirect as
discussed next.</p>

<h3>Versioning</h3>

<p>Once you have the proper files you should consider adding
entries to either the web.config (to fix this web app) or the
machine.config (to bind for all web apps) to bind calls to the
System.Web.Extensions and the System.Web.Extensions.Design to the
latest assemblies.&nbsp; To do this add the following to the
.config file to make sure that you are using the ASP.Net AJAX 3.5
versions of the files no matter where they are referenced in your
web application.</p>

<pre>
  &lt;runtime&gt;
    &lt;assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"&gt;
      &lt;dependentAssembly&gt;
        &lt;assemblyIdentity name="System.Web.Extensions" publicKeyToken="31bf3856ad364e35" /&gt;
        &lt;bindingRedirect oldVersion="1.0.0.0-1.1.0.0" newVersion="3.5.0.0" /&gt;
      &lt;/dependentAssembly&gt;
      &lt;dependentAssembly&gt;
        &lt;assemblyIdentity name="System.Web.Extensions.Design" publicKeyToken="31bf3856ad364e35" /&gt;
        &lt;bindingRedirect oldVersion="1.0.0.0-1.1.0.0" newVersion="3.5.0.0" /&gt;
      &lt;/dependentAssembly&gt;
    &lt;/assemblyBinding&gt;
  &lt;/runtime&gt;
</pre>

<p>As later versions of the .Net Framework gain popularity, you may
need to update these references on older applications to keep your
front-end and back-end in sync.</p>

<p>For more information on assembly binding see these Microsoft
Articles.</p>

<p><a
href="http://msdn.microsoft.com/en-us/library/433ysdt1%28v=VS.71%29.aspx"
 target="_blank">http://msdn.microsoft.com/en-us/library/433ysdt1%28v=VS.71%29.aspx</a></p>

<p><a
href="http://msdn.microsoft.com/en-us/library/aa720323%28v=VS.71%29.aspx"
 target="_blank">http://msdn.microsoft.com/en-us/library/aa720323%28v=VS.71%29.aspx</a></p>
]]></description></item><item><title>Blog4Umbraco Post Date</title><link>http://deeper.webangelo.net/2010/4/9/blog4umbraco-post-date.aspx</link><pubDate>Fri, 09 Apr 2010 00:00:00 GMT</pubDate><guid>http://deeper.webangelo.net/2010/4/9/blog4umbraco-post-date.aspx</guid><description><![CDATA[ 
<p>As the first two posts for this blog were more business focused
than technology focused, I wanted to do a little digging for this
post and get into some code.</p>

<p>"Fortunately" I came across a need for my blog which, if the
Umbraco Forum is any indication, has vexed couple of other people.
That is the need to have an alternate Post Date other than the
Created Date. This is more than just changing the date, but it is
also a matter of changing the structure of the date folders within
which it resides.</p>

<h2>Background</h2>

<p>This blog uses the <a
href="http://our.umbraco.org/projects/collaboration/blog-4-umbraco"
target="_blank">Blog4Umbraco</a> package put together by the
estimable Tim Geyssens. It is <a
href="http://www.opensource.org/licenses/mit-license.php"
target="_blank">MIT</a> licensed Open Source and you can download
the source from a link on the Blog4Umbraco project in Codeplex.</p>

<p>One useful part of the package is the feature which
automatically creates date folders for a blog post giving one the
handy /year/month/day/postname path. It does this by using the <a
href="http://our.umbraco.org/wiki/reference/api-cheatsheet/using-applicationbase-to-register-events/overview-of-all-events"
 target="_blank">Umbraco event model</a> to capture the New Event
which is fired when a new document is created. Within the event
handler, it checks to see if the post is currently in a Date
Folder, and if not, it creates a folder structure for the
/year/month/day as necessary (based on the CreateDate at the time
the New Document was created) and moves the post there. In
addition, many of the XSLT macros for ordering and rolling up posts
rely on the CreateDate to determine the order.</p>

<p>These facts have the following ramifications:</p>

<ol>
<li>Document path is set at the time of creation and is based on
the CreateDate, so your path will be based on that, regardless of
when you publish it.</li>

<li>Changing the CreateDate by itself will not affect the path,
since the path is set when the document is first created and the
document must be created before you can reference the createdate in
code in order to change it. 

<ol>
<li>This is why importing blogs will often run into this
issue,</li>
</ol>
</li>

<li>Changing the path but not changing the CreateDate will cause
your documents to sometimes be ordered in a different order than
your published dates if the default XSLT files are used.</li>
</ol>

<h2>Requirements</h2>

<p>So to address the shortfalls of using the CreateDate I want to
create an alternate Post Date which will be used for Blog dating
and ordering and which will determine the folder path to the
Blog.</p>

<p>To create an alternate post date I have to handle not only the
date structure, but also the XSLT which displays that date as the
Date Posted instead of the the CreateDate and also orders the posts
based on that date. In addition, it should pre-populate the new
field with the create date originally so that the XSLT has a value
to work with. Finally, to have an optimal solution, it should only
attempt to move the blog when necessary.</p>

<h2>Solution</h2>

<p>The first part of this solution and the key to the rest of it is
to create a new property on the Blog Post Document Type called
whatever you want (I called it <strong>Post Date</strong>) but with
an alias of PostDate.&nbsp; Use the DatePicker DataType for
convenience.</p>

<p><img src="/media/1587/addpostdate_450x279.jpg"  width="450"  height="279" alt="PostDateEx"/></p>

<p>Once we have this in place, we'll need to do a few things to
make it useful.&nbsp; First we'll want to populate it automatically
with the Create Date upon generating a new post.&nbsp; Since we
will later be updating our XSLT to sort our entries using this
field, we want to make sure it has a value.&nbsp; Second, we'll
want to move the post to the appropriate folder structure based
upon this new Post Date, but only as when it changes.</p>

<p>For both of these requirements, the handy Document Events are
the way to go.&nbsp; Umbraco Events allow you to listen for actions
Umbraco is taking like creating new pages.&nbsp; Then you can run
your custom code to interact with Umbraco while this is
happening.&nbsp; (For those of you experienced in .Net Event
Handlers, that is what they are).&nbsp; The Umbraco Wiki has some
pages on <a
href="http://our.umbraco.org/wiki/reference/api-cheatsheet/using-applicationbase-to-register-events"
 target="_blank">how to make use of these events</a>, so I won't go
into great detail, but it is really easy if you have any .Net
experience.&nbsp; [If you just want to use the dll that I've coded,
I've included it with the class file at the bottom of this
post.&nbsp; Just drop it in your bin directory and Umbraco will
know it is there.&nbsp; <em>Usual caveats of "No Guarantees...''
and "Do so at your own risk".</em>]</p>

<h3>Auto-populate the Post Date</h3>

<p>The first event we want to use if the Document.New event.&nbsp;
This will allow us to autopopulate our new Post Date field with the
Create Date.</p>

<pre>
void Document_New(Document sender, umbraco.cms.businesslogic.NewEventArgs e)<br />
{<br />
&nbsp;&nbsp;&nbsp; if (sender.ContentType.Alias == "BlogPost")<br />
&nbsp;&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;   if (sender.getProperty("PostDate") != null)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sender.getProperty("PostDate").Value = sender.CreateDateTime.Date;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp; }<br />
}<br />
</pre>

<p>Notice the first If-statement.&nbsp; You will see this critical
If-statement in many examples of event handling in Umbraco.&nbsp;
It is important to understand that Umbraco fires an event whenever
an appropriate action occurs regardless of whether it is germane to
what you are doing.&nbsp; In this case the Document.New event will
be fired every time a new document is created, regardless of
whether it is a Blog Post or a News Article or some other new page
on your site.&nbsp; The sender.ContentType.Alias property is a good
way to make sure that you are only taking further action if it is
related to what you are trying to accomplish.&nbsp; If you are not
sure of the appropriate Document Alias, you can find it by going to
the Settings Section of your Umbraco Admin, expand the Document
Types folder and click on the document type you are trying to
handle.&nbsp; You will see the Alias (and be able to update it) on
the screen that is loaded.</p>

<p><img src="/media/1592/documentalias.gif" width="364" height="269" alt="Document Alias"/></p>

<h3>Move the Document to the right Folder path</h3>

<p>Ok, now we've populated our PostDate field.&nbsp; How do we move
our post to the correct folder path?&nbsp; Also, just as
importantly, how do we avoid trying to move it when we don't need
to?</p>

<p>Fortunately, for moving the folder, the <a
href="http://blog4umbraco.codeplex.com/sourcecontrol/network/Show?projectName=blog4umbraco&amp;changeSetId=40819#178779"
 target="_blank">Blog4Umbraco code</a> shows us how it is being
placed in the folder path in the first place.&nbsp; We just have a
few tweaks for this part.&nbsp; First, we want to use the
Document.BeforePublish event and not the new event.</p>

<pre>
void Document_BeforePublish(Document sender, umbraco.cms.businesslogic.PublishEventArgs e)<br />
{<br />
 //... Our code will go here.<br />
}<br />
</pre>

<p>Next, we only want to run the code if we need to.&nbsp; So we'll
check for the Post Date and make sure it has changed since the last
time the page was published.</p>

<pre>
//Don't forget that above this is:<br />
//if (sender.ContentType.Alias == "BlogPost")<br />
if (sender.getProperty("PostDate") != null) //If no post date, skip<br />
{<br />
    if (sender.Parent != null)  //If top of tree, something is wrong.  Skip.<br />
    {<br />
        try<br />
        {<br />
            DocumentVersionList[] postVersions = sender.GetVersions();<br />
            bool _versionCheck = true;<br />
            DateTime postDate;<br />
            postDate = System.Convert.ToDateTime(sender.getProperty("PostDate").Value);<br />
            if (postVersions.Length &gt; 1)  //If it has been published, check post date info<br />
            {<br />
                //Length -1 is current version Length -2 is past version (if it exists)<br />
                Guid previousVersion = postVersions[postVersions.Length - 2].Version;<br />
                Document doc = new Document(sender.Id, previousVersion);<br />
                DateTime previousPostDate = System.Convert.ToDateTime(doc.getProperty("PostDate").Value);<br />
                _versionCheck = (postDate != previousPostDate);<br />
            }<br />
            if (_versionCheck)  //Only do the date folder movement if the PostDate is changed or is new Post.<br />
            {<br />
              //... More Code<br />
            }<br />
        }<br />
    }<br />
}<br />
</pre>

<p>Next, we want to use the post date and not the created date.</p>

<pre>
string[] strArray = { postDate.Year.ToString(), postDate.Month.ToString(), postDate.Day.ToString() };<br />
</pre>

<p>Next, we are likely in a Date Folder, so well need to find the
top of the blog so that we can create the correct Date Folders in
the correct places.</p>

<pre>
if (strArray.Length == 3)<br />
{<br />
    Node topBlogLevel = new Node(sender.Parent.Id);<br />
    //Traverse up the tree to Find the Blog Node since we are likely in a Date Folder path<br />
    while (topBlogLevel != null &amp;&amp; topBlogLevel.NodeTypeAlias != "Blog")<br />
    {<br />
        if (topBlogLevel.Parent != null)<br />
        {<br />
             topBlogLevel = new Node(topBlogLevel.Parent.Id);<br />
        }<br />
        else<br />
        {<br />
            topBlogLevel = null;<br />
        }<br />
    }<br />
    if (topBlogLevel != null)<br />
    {<br />
       //Create Appropriate Date Folders<br />
    }<br />
}<br />
</pre>

<p>Finally, check for and create the post folders similar to the
way the Blog4Umbraco does it when first creating a post.&nbsp;
Given that my code is very similar to what Tim did [read: brazen
code reuse] I won't post it here, but as I mentioned, I've included
that class file, modified XSLT, modified BlogPost.master and dll at
the bottom of this post.</p>

<h2>Final Comments</h2>

<p>This is one solution to moving Blog Posts to new Date Folder
paths.&nbsp; Some things to understand before you implement this
solution.</p>

<ol>
<li>Although this should work for importation, it hasn't been
tested.&nbsp; The biggest issue, in my opinion, will be
threading.&nbsp; If this is being called asynchronously, it is
theoretically possible for duplicate folders to be created since a
second thread may find a date folder isn't there and try to create
it while a first thread is in the process of doing the same.&nbsp;
Although it would slow things down a little, some Mutex calls
around the Folder Discovery part may be necessary.</li>

<li>Use at your own risk.&nbsp; This was only tested against my
personal install(s) of blog4Umbraco 2.0.26.&nbsp; Additionally, it
modifies the xslt and BlogPost.master so future updates to the blog
engine may overwrite these changes.&nbsp; I'm going to submit this
as a patch to the codeplex project, so it may make it in.&nbsp; If
it does, you may have to remove the homemade version so it doesn't
try to do this twice.</li>
</ol>

<p>BTW, I started this blog post March 30th.</p>

<p>You can download the code and binary <a
href="http://code.webangelo.net/BlogPostDateFix.zip"
target="_blank">here</a>.</p>
]]></description></item><item><title>The Feature Comparison Fallacy</title><link>http://deeper.webangelo.net/2010/3/26/the-feature-comparison-fallacy.aspx</link><pubDate>Fri, 26 Mar 2010 00:00:00 GMT</pubDate><guid>http://deeper.webangelo.net/2010/3/26/the-feature-comparison-fallacy.aspx</guid><description><![CDATA[ 
<p>There are a number of blog posts and web pages available that
take various CMS products and compare their features.&nbsp; Some
are focused on the writers specific needs while others try to give
a more general overview.&nbsp; These types of comparisons can be a
very helpful first step in understanding what is out there in the
marketplace for these products.</p>

<p>Unfortunately, it can be too easy to just take these lists,
match them up with your&nbsp; external needs and pick the one that
has the greatest number of green checkmarks.&nbsp; If you do this,
then I would contend that you are making two potentially very
costly mistakes.&nbsp; First, you are treating all needs as equal,
which is a suspect assumption at best.&nbsp; Second, you are not
giving enough consideration to the long-term costs.</p>

<h2>Not all features are created equal</h2>

<p>It may be tempting to look at your needs and say,</p>

<blockquote>
<p>"Ahh, CMS X has a forum and a blog and a control that puts
dancing ballerinas on my pages, all built in.&nbsp; That's exactly
what I need, we'll use them."</p>
</blockquote>

<p>This approach may actually decrease your time-to-market since
you won't have to create any of those features yourself or look
into add-ons, so it may look wise at first blush.&nbsp; But before
you commit to a CMS based on external needs, ask yourself these
questions:</p>

<ol>
<li>Does the end-user experience on my website matter to me?</li>

<li>Do I expect to continually need to add content overtime?</li>

<li>Do I expect to ever need more functionality?</li>
</ol>

<p>If you answered "Yes" to any of these then you need to look
deeper at what a CMS is really providing you.&nbsp; (And if you
answered "No" to any of these, you should look deeper at whether
your expectations from your site are reasonable.&nbsp; In my
experience #1 should be an automatic "Yes" and #2 and #3 happen
much more often than expected and cause the largest amount of
unplanned costs in a website.)</p>

<h3>End-user Experience</h3>

<p>It may seem that end-user experience is dependent upon the
design and functionality of your site, and to a degree this is
true.&nbsp; But given that a CMS is the backbone of your site, you
have to take its performance into account.&nbsp; You may have the
best site in the world, in regards to usability and functionality,
but if the backbone is sluggish, your end-users will become
frustrated.&nbsp; This will result in less goal conversions (i.e.
sales or donations, etc...) and thus will affect your business in a
big way.&nbsp; Do you know the typical performance of the CMS you
are considering?&nbsp; Is a quicker time-to-market worth the user
frustration in the end?</p>

<h3>Ease of Administration</h3>

<p>Let's face it, features are all well and good, but the purpose
of a Content Management System (CMS) is... (prepare to be
shocked)... content management.&nbsp; And when we are dealing with
content management we are usually dealing with&nbsp; an
organization's employees at varying technical skill levels.&nbsp;
In fact, since much content is business driven and not IT driven,
those who would be best at creating the content are often business
users and not technical staff.</p>

<p>Unfortunately, that is often not what happens in the real
world.&nbsp; Often, due to the challenges of working with a CMS,
content management falls to a technical user and not the actual
source of the content, the business specialist.&nbsp; This
increases costs, since technical staff are often a more expensive
resource and maintaining content isn't really the best use of their
time.</p>

<p>Many business have accepted that this is how it works, but it
doesn't have to be.&nbsp; Ease of creating content should be a
large part of your decision for choosing a CMS.</p>

<h3>Ease of Functional Change</h3>

<p>As much as we try to forecast business needs, no one is
completely prescient.&nbsp; Therefore, one thing we must always
take into consideration in every business decision is the potential
for change.&nbsp; This is especially true in the technology sector
and doubly so for customer facing technologies like a CMS.</p>

<p>Sure you may have needed the dancing ballerinas when you
started, but what if ballerinas go out of style?&nbsp; What if you
need to add Lords-a-leaping or Drummers-drumming?&nbsp; What if, in
fact, you need to do a complete overhaul?</p>

<p>The fact is that changes will come and your ability to adapt
will affect your ability to meet your clients needs in the long
run.&nbsp; Again, since the CMS is the backbone of your externally
facing, client-visible presence, the ability to modify the
functionality is critical.&nbsp; It is imperative to evaluate how
difficult it would be to change something if it became
necessary.</p>

<h2>The Cost of Short-Term thinking</h2>

<p>The second issue I mentioned way back at the beginning of this
post, was long -term costs. From my experience long-term costs
often overshadow the initial cost of deployment of an IT
product.&nbsp; The less you plan with these long-term needs in
mind, the more this cost disparity will be.</p>

<p>As I hope you can see from my previous points, there are some
features in a CMS that affect long-term costs more than
others.&nbsp; The more difficult a CMS is to work with and modify
and the less user-friendly it is, the larger your long-term costs
will tend to be.&nbsp; The worse the end-user experience the
smaller gain your organization will receive from it.&nbsp; A small
investment in mitigating these concerns will pay huge dividends in
the long run.</p>

<h2>So where does that leave us?</h2>

<p>As anyone who takes a look at our services and this blog will
soon see, the <a href="http://umbraco.org" target="_blank">Umbraco
CMS</a> was the choice for us for all of the reasons stated above
as well as some subjective considerations mentioned in <a
href="/2010/3/22/why-umbraco.aspx" title="Why Umbraco">my first
post</a>.&nbsp; We believe it would be a good choice for your
organization as well, which is why we've staked our business on
it.</p>

<p>That said, we understand that some other requirements may take
your organization in a different direction.&nbsp; Regardless
whether Umbraco is your choice for a CMS or not, I ask that you
please take these considerations into account.&nbsp; One of the
reasons Webangelo and this blog exist is to promote thoughtful
decisions in the web and development world.&nbsp; We may one day be
a potential client/constituent of yours and we hope you will make
our experience a pleasant one.</p>
]]></description></item><item><title>Why Umbraco</title><link>http://deeper.webangelo.net/2010/3/22/why-umbraco.aspx</link><pubDate>Mon, 22 Mar 2010 00:00:00 GMT</pubDate><guid>http://deeper.webangelo.net/2010/3/22/why-umbraco.aspx</guid><description><![CDATA[ 
<p style="text-align: left;">Welcome to the inaugural post of the
Going Deeper Blog.&nbsp; I'm Christopher Rushing CEO and founder of
Webangelo, LLC.</p>

<p style="text-align: left;">Since one of the focuses of this blog
is Umbraco, I decided to start the blog off with an explain of why
Webangelo has focused on the Umbraco CMS.</p>

<h2>The Problem</h2>

<p style="text-align: left;">For every solution, there must be a
problem that it solves, right?&nbsp; So to understand why Webangelo
only uses Umbraco for Website Development you must understand what
challenge(s) Umbraco solves for us.</p>

<p style="text-align: left;">Webangelo, LLC is an extension of my
personal commitment to quality and value.&nbsp; As such, I wanted
to create an environment in which I could use my skill sets to
greatest advantage for my clients and also give them a good return
on their investment with Webangelo.</p>

<p style="text-align: left;">Thus I had the following challenges I
needed to tackle.</p>

<ol>
<li>I want to provide a good return on investment (ROI) for my
clients.&nbsp; What is the best way for me to do that when
developing web sites / tools?</li>

<li>I have a large personal investment in the .Net framework.&nbsp;
How do I leverage that skill set for my clients?</li>

<li>I've run into situations before where I had to pass off
troubleshooting to another company since I didn't have access to
the full code.&nbsp; How do I avoid that in the future?</li>

<li>No one knows everything.&nbsp; How do I get plugged into a
helpful community that can support me?</li>
</ol>

<h2>The Solution: Umbraco</h2>

<p style="text-align: left;">Sure the title gives away the answer,
but here is what led up to it.</p>

<h3>ROI - Providing value for my clients</h3>

<p>Anyone who has been in web development for a while (or any sort
of development for that matter) will see two aspects of the process
which in fact fuel much of the progress in the IT sector.&nbsp;
First, one will find oneself doing the same basic things over and
over&nbsp; (and over and over...) again, thus making automation of
those tasks a beneficial undertaking.&nbsp; Secondly, although the
basics are the same, there is enough variation that attempts to
automate the basics or hide the technical aspects of something
often run into limitations that require some additional technical
expertise to work around.&nbsp; So even as we improve things&nbsp;
and make them easier for the non-technical user, we never quite
make the technical aspect obsolete.</p>

<p>So one key to ROI is identifying what requires a technical
resource and what can now be done by a Power User or even a
non-technical user.&nbsp; Although having clients come to me every
time they need basic content changed on their site would provide an
ongoing source of income, it isn't the most efficient or effective
way to provide web content.&nbsp; The solution to this problem in
the web world is usually some sort of Content Management System
(CMS) which separates (to some extent) the content and site
structure from the technical implementation.</p>

<p>For a web site there are two classic ways to do this.&nbsp;
First is a desktop tool that the client can purchase for their
machines which will handle the HTML, CSS and to some extent, site
structure.&nbsp; These tools vary in their complexity and focus,
but all suffer from the same basic drawback.&nbsp; You need to have
that tool on your system to update the content (unless you have the
technical knowledge to alter the files directly, usually with a
text editor, but that usually carries risks of its own).</p>

<p>Second is a web-based CMS.&nbsp; These also vary in their
complexity, but all of them seek to provide a way to manage the
content of a site from any browser.&nbsp; Although many of the
desktop tools are quite useful, I didn't want to be tied to a
proprietary desktop based solution.&nbsp; Therefore, for Webangelo,
I wanted to focus on a web-based CMS.</p>

<p>There were other ROI considerations, but these will be best
answered by moving on to the other challenges I wanted to
solve.</p>

<h3>Leveraging .Net</h3>

<p>As Webangelo was starting out as an extension of myself
(although I of course expect it to grow), I wanted to make good use
of my existing .Net skillset which would also provide some more of
that ROI for my customers.&nbsp; This naturally limited the number
of applicable CMS entries to ones in which my .Net skillset could
play a key role.</p>

<h3>Avoiding Proprietary Software (as much as possible)</h3>

<p>One of my stronger skills is in Root Cause Analysis which is the
process of finding out what really caused a problem so that one can
1) fix it and 2) make sure it doesn't happen again.&nbsp; There
have been a number of cases in which I have been tracking down a
problem when I ran smack-dab into some proprietary code which
stopped me cold.&nbsp; Life is then further complicated by the way
in which some companies seem to be more interested in stating that
nothing is wrong with their code rather than trying to find out if
something is.&nbsp; After many such frustrating sessions, I wanted
to avoid this issue if at all possible as this just puts you as a
middleman between your client and the maker of the proprietary
software.</p>

<p>Although there is a limit to this in the .Net world (since the
.Net Framework is itself proprietary), I wanted to have access to
troubleshoot problems if something didn't work as expected.&nbsp;
Given how fundamental a CMS is to a website, I wanted access at the
deepest level possible.&nbsp; This lead to Open Source.</p>

<p>Unfortunately, many (i.e. most) Open Source CMS tools are in a
language other than .Net.&nbsp; Imagine my pleasure, then when I
came across Umbraco, which not only fit the bill as .Net and Open
Source (and C#, but we won't go into that), it was also well
thought out and actually a pleasant environment in which to
work.&nbsp; (Yes there are other .Net Open Source CMS tools, but
the choice between them is a post for another day).</p>

<h3>And Then There's the Community</h3>

<p>The final reason for my choice of Umbraco was the helpful
community.&nbsp; Between twitter and the <a
href="http://our.umbraco.org" target="_blank">our.umbraco.org</a>
forums, assistance abounds.&nbsp; The combination of the two is a
one-two punch that usually knocks out problems quickly.</p>

<h2>Final Thoughts</h2>

<p>So, this is the overview of why I picked Umbraco.&nbsp; The
final thing to note is that I wanted something in which we could
gain an expertise.&nbsp; By focusing on Umbraco and getting
certification, I can be confident that Webangelo is providing the
best service we can for our clients, which was the most important
requirement of all.</p>

<p>I'm sure I'll have more comments on these topics over time.</p>
]]></description></item></channel></rss>

