<?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:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>BeaverBlog &#187; Articles</title>
	<atom:link href="http://blog.crazybeavers.se/index.php/archive/category/articles/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.crazybeavers.se</link>
	<description>A beaver bloging about webdevelopment, XML and .Net</description>
	<lastBuildDate>Tue, 26 Jul 2011 10:59:50 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.1.1</generator>
		<item>
		<title>ActionFilters in MVC</title>
		<link>http://blog.crazybeavers.se/index.php/archive/actionfilters-in-mvc/</link>
		<comments>http://blog.crazybeavers.se/index.php/archive/actionfilters-in-mvc/#comments</comments>
		<pubDate>Tue, 20 Oct 2009 10:17:13 +0000</pubDate>
		<dc:creator>Karl</dc:creator>
				<category><![CDATA[.Net]]></category>
		<category><![CDATA[Articles]]></category>
		<category><![CDATA[c#]]></category>
		<category><![CDATA[Code samples]]></category>
		<category><![CDATA[asp.net]]></category>
		<category><![CDATA[imagergallery]]></category>
		<category><![CDATA[mvc]]></category>
		<category><![CDATA[sample]]></category>

		<guid isPermaLink="false">http://blog.crazybeavers.se/?p=124</guid>
		<description><![CDATA[I&#8217;ve been working on two fairly large MVC-projects lately. ImagerGallery.Net and a webshop-application suitably named BeaverShop. While working on those projects I&#8217;ve realized that I just love being able to use ActionFilters in MVC. Basically, they are attributes that you append to action-methods. They can be used to validate input, parse data into more suitable [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve been working on two fairly large MVC-projects lately. ImagerGallery.Net and a webshop-application suitably named BeaverShop. While working on those projects I&#8217;ve realized that I just love being able to use ActionFilters in MVC. Basically, they are attributes that you append to action-methods. They can be used to validate input, parse data into more suitable structures, check security and lots more.</p>
<p>One of my most used filters in both ImagerGallery and BeaverShop is one I named PagingAttribute which I thought I should show to you today.</p>
<p>Any ActionFilter need to inherit the ActionFilterAttribute and implement at least one of the following methods: OnActionExecuting, OnActionExecuted, OnResultExecuting or OnResultExecuted. They are all called during different stages of the execution of an action-method and can be used for various things. The one I&#8217;ll be using is OnActionExecuting since it is executed before the action so that I can pass extra arguments to the action.</p>
<p>The code is quite easy to understand. There is only one property to be set (except for the default property Order which is defined in ActionFilterAttribute) which is which field to be parsed. I check if the field is null or empty, if not ten I use a regular expression to see check if the selected field ends with &#8220;page&#8221; and a numerical value. The numerical value is then returned as a argument for the action called &#8220;pageNo&#8221;. This value is defaulted to 1 to make sure that we always get a number for our page (and not specifying anything should mean the first page). In my case I also want the field to be modified so it doesn&#8217;t contain the &#8220;page&#8221; part but that might not be suitable for everyone. If not, then you can easily remove that part by commenting the line looking like this: <i>filterContext.ActionParameters[Field] = id;</i></p>
<pre class="brush: csharp; title: ;">
using System;
using System.Text.RegularExpressions;
using System.Web;
using System.Web.Mvc;

namespace BeaverShopMvc.Attributes
{
    /// &lt;summary&gt;
    /// An ActionFilter to parse a page number from a field value
    /// &lt;/summary&gt;
    public class PagingAttribute : ActionFilterAttribute
    {
        /// &lt;summary&gt;
        /// The name of the field to parse
        /// &lt;/summary&gt;
        public string Field { get; set; }

        // A compiled regular expression to speed things up
        private static Regex _pageRegex = new Regex(&quot;page(?&lt;PageNo&gt;\\d+)$&quot;, RegexOptions.CultureInvariant | RegexOptions.Compiled);

        public override void OnActionExecuting(ActionExecutingContext filterContext)
        {
            string id = filterContext.ActionParameters[Field] as string;
            Int32 pageNo = 1;

            // We never need an ending / so remove it
            id = id.TrimEnd('/');

            // Check so that the field isn't empty and while at it also that it
            // contains &quot;page&quot;
            if (!string.IsNullOrEmpty(id) &amp;&amp; id.ToLowerInvariant().Contains(&quot;page&quot;))
            {
                Match match = _pageRegex.Match(id);
                if (match.Success)
                {
                    pageNo = Convert.ToInt32(match.Groups[&quot;PageNo&quot;].Value);
                    if (id.Contains(&quot;/&quot;))
                        id = id.Substring(0, id.LastIndexOf('/'));
                    else
                        id = string.Empty;
                }
            }

            filterContext.ActionParameters[&quot;pageNo&quot;] = pageNo;
            // The line below replaces the old field value with a
            // new one without the &quot;page&quot; part
            filterContext.ActionParameters[Field] = id;

            base.OnActionExecuting(filterContext);
        }
    }
}
</pre>
<p>Using the attribute is really simple and the great thing about this is that it is easily reusable on any actions you need it to. Below is a little sample of it in action.</p>
<pre class="brush: csharp; title: ;">
        [Paging(Field = &quot;id&quot;)]
        public ActionResult ListProducts(string id, Int32 pageNo)
        {
            return View();
        }
</pre>
<p>I have a few more filters that I really like as well (AkismetValidatorAttribute for example) that I might share some other day. I&#8217;m still learning a lot about working with MVC and will keep you posted with what other interesting things I can find.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.crazybeavers.se/index.php/archive/actionfilters-in-mvc/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Disabling &#8220;Missing XML comment for publicly visible type or member XX&#8221;</title>
		<link>http://blog.crazybeavers.se/index.php/archive/disabling-missing-xml-comment-for-publicly-visible-type-or-member-xx/</link>
		<comments>http://blog.crazybeavers.se/index.php/archive/disabling-missing-xml-comment-for-publicly-visible-type-or-member-xx/#comments</comments>
		<pubDate>Sun, 24 May 2009 09:52:04 +0000</pubDate>
		<dc:creator>Karl</dc:creator>
				<category><![CDATA[.Net]]></category>
		<category><![CDATA[Articles]]></category>
		<category><![CDATA[c#]]></category>
		<category><![CDATA[Code samples]]></category>
		<category><![CDATA[pragma]]></category>
		<category><![CDATA[xml comments]]></category>

		<guid isPermaLink="false">http://blog.crazybeavers.se/?p=55</guid>
		<description><![CDATA[Adding descriptive comments to your code is something that everyone will always tell you to do though in reality many people simply don&#8217;t do it. Some are just lazy, some doesn&#8217;t see the need of it, some are to stressed out to do it and some things that the c# compiler will warn you about [...]]]></description>
			<content:encoded><![CDATA[<p>
  Adding descriptive comments to your code is something that everyone will always tell you to do though in reality many people simply don&#8217;t do it. Some are just lazy, some doesn&#8217;t see the need of it, some are to stressed out to do it and some things that the c# compiler will warn you about just doesn&#8217;t need commenting. Looking at the last category, things that just doesn&#8217;t need commenting, we many times find enums. Look at this as a sample.
</p>
<pre class="brush: csharp; title: ;">
/// &lt;summary&gt;
///  Datatypes used by the EXIF specification
/// &lt;/summary&gt;
public enum ExifDataTypes
{
	UnsignedByte = 1,
	AsciiString = 2,
	UnsignedShort = 3,
	UnsignedLong = 4,
	UnsignedRational = 5,
	SignedByte = 6,
	Undefined = 7,
	SignedShort = 8,
	SignedLong = 9,
	SignedRational = 10,
	SingleFloat = 11,
	DoubleFloat = 12
}
</pre>
<p>What useful comments could added to this? When compiling I&#8217;m getting twelve warnings about this code not being documented though I do have a hard time finding out what I should write about each option since I feel that the names are quite self explanatory. Just adding a dummy comment to each line would get rid of the warnings but also clutter up my code which isn&#8217;t really helping me. I could also tell the compiler to ignore all warnings of this type (&#8220;/nowarn 1591&#8243; when compiling) though there might be other places in my code where I want to know that I missed a comment.</p>
<p>So no luck just yet. There is however a third method to use. Going back to C there has been a way to communicate with the compiler from your code using directives called &#8220;pragmas&#8221;. C# have it as well though the standard compiler (csc.exe) only understands two commands, <a href="http://msdn.microsoft.com/en-us/library/441722ys(VS.80).aspx" target="_blank" title="Check it out on MSDN">warning</a> and <a href="http://msdn.microsoft.com/en-us/library/ms173226(VS.80).aspx" target="_blank"  title="Check it out on MSDN">checksum</a>. For my problem, warning was the one I could use.</p>
<p>The code below has a pragma added that tells the compiler not to raise warnings with id 1591 (missing comments) from line 6 to line 19.</p>
<pre class="brush: csharp; title: ;">
/// &lt;summary&gt;
///  Datatypes used by the EXIF specification
/// &lt;/summary&gt;
public enum ExifDataTypes
{
#pragma warning disable 1591
	UnsignedByte = 1,
	AsciiString = 2,
	UnsignedShort = 3,
	UnsignedLong = 4,
	UnsignedRational = 5,
	SignedByte = 6,
	Undefined = 7,
	SignedShort = 8,
	SignedLong = 9,
	SignedRational = 10,
	SingleFloat = 11,
	DoubleFloat = 12
#pragma warning restore 1591
}
</pre>
<p>It still gives me lots of warnings (still have some huge enums for the EXIF class that needs this) but now I have a chance of finding the real warnings and still document the parts of my code that really needs documenting.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.crazybeavers.se/index.php/archive/disabling-missing-xml-comment-for-publicly-visible-type-or-member-xx/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>ASP.Net and metadata</title>
		<link>http://blog.crazybeavers.se/index.php/archive/aspnet-and-metadata/</link>
		<comments>http://blog.crazybeavers.se/index.php/archive/aspnet-and-metadata/#comments</comments>
		<pubDate>Fri, 19 Dec 2008 09:36:47 +0000</pubDate>
		<dc:creator>Karl</dc:creator>
				<category><![CDATA[.Net]]></category>
		<category><![CDATA[Articles]]></category>
		<category><![CDATA[c#]]></category>
		<category><![CDATA[adapter]]></category>
		<category><![CDATA[app_browsers]]></category>
		<category><![CDATA[asp.net]]></category>
		<category><![CDATA[meta]]></category>
		<category><![CDATA[page_load]]></category>

		<guid isPermaLink="false">http://www.beaverblogg.com/?p=33</guid>
		<description><![CDATA[Building great websites have several parts to it. First of all you need a great idea of what to fill the site with, then you&#8217;ll need some great technology in the background (sloppy code can achieve lots of great things aswell, but you won&#8217;t want to go in there and add things afterwards) and then [...]]]></description>
			<content:encoded><![CDATA[<p>
  Building great websites have several parts to it. First of all you need a great idea of what to fill the site with, then you&#8217;ll need some great technology in the background (sloppy code can achieve lots of great things aswell, but you won&#8217;t want to go in there and add things afterwards) and then a great presentation to the users of your site. In this article I will touch two parts of this, the technology (ASP.Net) and the presentation (metadata).
</p>
<p>
  First of all I just want to state that I&#8217;m not a believer in all the SEO crap thats out there. I simply believe that if you have a great site that people visit and link to it will rank higher in search engines. A great site though will incorporate lots of things that &#8220;SEO experts&#8221; are chattering about like validating markup, good titles and things like that but that doesn&#8217;t mean it is those parts that put it high in the searchresults.
</p>
<p>
  When working on a new version the CMS I use for <a href="http://www.crazybeavers.se/" title="Visit CrazyBeaver Software">CrazyBeaver Softwares website</a> I ran into a really disturbing problem with how ASP.Net handles metadata. Look at the sample below.
</p>
<pre class="brush: xml; title: ;">
&lt;head runat=&quot;server&quot;&gt;
    &lt;title&gt;My website&lt;/title&gt;
    &lt;meta name=&quot;keywords&quot; content=&quot;&quot; /&gt;
&lt;/head&gt;
</pre>
<p>
  It looks alright doesn&#8217;t it? Well if you browse to that page you&#8217;ll see that the generated source is different.
</p>
<pre class="brush: xml; title: ;">
&lt;head&gt;
    &lt;title&gt;My website&lt;/title&gt;
    &lt;meta name=&quot;keywords&quot; /&gt;
&lt;/head&gt;
</pre>
<p>
  Where did my content go? Just because it is empty doesn&#8217;t mean it can be removed just like that. If you pay a quick visit to <a href="http://www.w3.org/" title="Visit World Wide Web Consortium">www.w3.org</a> and look at the xhtml specification you&#8217;ll see that the content attribute is a REQUIRED attribute of the meta element and therefore shouldn&#8217;t be removed. Now I hear you say that it shouldn&#8217;t matter since it didn&#8217;t convey any information anyway and while that is true the removal of that attribute also made sure that the page won&#8217;t generate valid html. Sure, it&#8217;s a very small error and won&#8217;t stop anything that doesn&#8217;t require a strict DTD validation to display the page (and no browsers do that since they wouldn&#8217;t be able to browse large parts of the web) but start out small and soon you won&#8217;t even bother to close tags properly since the page doesn&#8217;t validate anyway.
</p>
<p>
  So, this is a behavior of ASP.Net that we need to work around somehow. There are a few choices here. You could simply loop through the HtmlMeta controls during Page_Load and check if they have empty content. It would look something like this.
</p>
<pre class="brush: csharp; title: ;">
protected void Page_Load(object sender, EventArgs e)
{
    if (!Page.IsPostBack)
    {
        Control[] headerControls = new Control[Page.Header.Controls.Count];
        Page.Header.Controls.CopyTo(headerControls, 0);

        foreach (Control control in headerControls)
        {
            HtmlMeta meta = control as HtmlMeta;

            if (meta == null)
                continue;

            if (string.IsNullOrEmpty(meta.Content))
            {
                Page.Header.Controls.Remove(control);
                break;
            }
        }
    }
}
</pre>
<p>
  Does this look as a good enough solution for you? It will do the work needed for most parts (it won&#8217;t remove a completely empty meta for some reason though so a &lt;meta name=&#8221;" content=&#8221;" /&gt;will still fail your validation..) but it isn&#8217;t the nicest solution since you&#8217;ll need to loop through all controls in your header for every pageview that isn&#8217;t a postback. Also, maybe you want to specify an empty content for some reason since you have some other piece of code or application that relies on them being there. So what would be a nicer solution? Well writing an adapter of course! In ASP.Net 2.0 they introduced a cool thing called control adapters which basicly let you override the rendering of an existing webcontrol. In this case we will use it to force the HtmlMeta control to always render a content attribute.
</p>
<pre class="brush: csharp; title: ;">
using System.Web.UI;
using System.Web.UI.Adapters;
using System.Web.UI.HtmlControls;

namespace CrazyBeavers.Web.UI.Adapters
{
    public class HtmlMetaAdapter : ControlAdapter
    {
        private static string[] _i8nAttributes = new string[] { &quot;lang&quot;, &quot;xml:lang&quot;, &quot;dir&quot; };

        protected override void Render(HtmlTextWriter writer)
        {
            HtmlMeta meta = this.Control as HtmlMeta;

            writer.WriteBeginTag(&quot;meta&quot;);

            if (!string.IsNullOrEmpty(meta.HttpEquiv))
                writer.WriteAttribute(&quot;http-equiv&quot;, meta.HttpEquiv);

            if (!string.IsNullOrEmpty(meta.Scheme))
                writer.WriteAttribute(&quot;scheme&quot;, meta.Scheme);

            if (!string.IsNullOrEmpty(meta.Name))
                writer.WriteAttribute(&quot;name&quot;, meta.Name);

            foreach (string attr in meta.Attributes.Keys)
                foreach (string i18n in _i8nAttributes)
                    if (attr.Equals(i18n, System.StringComparison.InvariantCultureIgnoreCase))
                        writer.WriteAttribute(i18n, meta.Attributes[i18n]);

            writer.WriteAttribute(&quot;content&quot;, meta.Content);

            writer.Write(HtmlTextWriter.SelfClosingTagEnd);
        }
    }
}
</pre>
<p>
  Just drop that piece of code in your App_Code or compile it as an assembly and put it in the Bin-folder on your site. There is still one step that needs to be completed for this to work though. All control adapters needs to be referenced via an browser-file in App_Browsers aswell (which is a really cool thing since you can set conditions and use adapters on certain controls for certain browsers, but more on that some other time). Below is a short sample of my Default.browser-file, it doesn&#8217;t use any extra features of the browser-file and just say that I want to use my adapter everywhere.
</p>
<pre class="brush: xml; title: ;">
&lt;browsers&gt;
  &lt;browser refID=&quot;Default&quot;&gt;
    &lt;controladapters&gt;
      &lt;adapter controlType=&quot;System.Web.UI.HtmlControls.HtmlMeta&quot;
               adapterType=&quot;CrazyBeavers.Web.UI.Adapters.HtmlMetaAdapter&quot; /&gt;
    &lt;/controladapters&gt;
  &lt;/browser&gt;
&lt;/browsers&gt;
</pre>
<p>
  There you go, now all your MetaCotrol should always render properly for you even though you don&#8217;t put any data at all in them. Feel free to comment on this article if you have other solutions or ideas on how to work around this problem.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.crazybeavers.se/index.php/archive/aspnet-and-metadata/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>My most downloaded resource</title>
		<link>http://blog.crazybeavers.se/index.php/archive/my-most-downloaded-resource/</link>
		<comments>http://blog.crazybeavers.se/index.php/archive/my-most-downloaded-resource/#comments</comments>
		<pubDate>Fri, 25 Apr 2008 11:28:56 +0000</pubDate>
		<dc:creator>Karl</dc:creator>
				<category><![CDATA[Articles]]></category>
		<category><![CDATA[Beaver]]></category>

		<guid isPermaLink="false">http://www.beaverblogg.com/index.php/archive/my-most-downloaded-resource/</guid>
		<description><![CDATA[Last week I started wondering how many downloads my products really had had throughout the years. Seeing that I didn&#8217;t have complete statistics over the downloads since I&#8217;ve rebuilt the sites lots of times and moved servers and such. Currently, these are the download stats from CrazyBeaver Softwares homepage: BeaverSFV 1.1 &#8211; 167 CrazyBeavers YouTube [...]]]></description>
			<content:encoded><![CDATA[<p>Last week I started wondering how many downloads my products really had had throughout the years. Seeing that I didn&#8217;t have complete statistics over the downloads since I&#8217;ve rebuilt the sites lots of times and moved servers and such. Currently, these are the download stats from <a href="http://www.crazybeavers.se/" title="Visit CrazyBeaver Software">CrazyBeaver Softwares</a> homepage:</p>
<ul>
<li>BeaverSFV 1.1 &#8211; 167</li>
<li>CrazyBeavers YouTube Downloader 1.01 &#8211; 6</li>
<li>CrazyBeavers Calendar Class 1.1 &#8211; 143</li>
<li>CrazyBeavers RSS Class 1.3 &#8211; 188</li>
<li>CrazyBeavers Upload Class 1.2 &#8211; 233</li>
<li>CrazyBeavers Chat 1.3 &#8211; 123</li>
<li>Imager Gallery 5.5 Prerelease &#8211; <strong>1276</strong></li>
<li>CrazyBeavers Upload 2.4 &#8211; 207</li>
<li>CrazyBeavers ZIP 1.0 Prerelease 3 &#8211; 69</li>
<li>Imager Resizer 2.4 &#8211; <strong>957</strong></li>
</ul>
<p>Looking at this it seems quite clear that Imager Gallery and Imager Resizer would be the best candidates for downloaded products. These stats are just for the past few months though but if they&#8217;ve had similar numbers since they were released during 2004-2005 it would give quite a lot of downloads. Lets elaborate a bit further though, most of my old ASP and ISAPI/COM applications are listed on <a href="http://www.hotscripts.com/?RID=198852">HotScripts</a> and <a href="http://www.aspin.com/">Aspin</a> aswell, lets look at their popularity there to the calculation.</p>
<ul>
<li>CrazyBeavers Calendar Class 1.1 &#8211; <strong>5 565</strong> views on HotScripts with 3 votes (4.33 average)</li>
<li>CrazyBeavers RSS Class 1.3 &#8211; 2 175 views on HotScripts with 2 votes (5.00 average)</li>
<li>Imager Gallery 5.5 Prerelease &#8211; <strong>22 271</strong> views on HotScripts with 74 votes (4.39 average)</li>
<li>CrazyBeavers Upload 2.4 &#8211; 3 415 views on HotScripts with 15 votes (4.20 average)</li>
<li>CrazyBeavers ZIP 1.0 Prerelease 3 &#8211; 651 views on HotScripts with 2 votes (5.00 average) &#8211; Listed under CGI &#038; Perl though, wasn&#8217;t allowed in the ASP category</li>
<li>Imager Resizer 2.4 &#8211; <strong>6 246</strong> views on HotScripts with 176 votes (4.78 average)</li>
</ul>
<ul>
<li>Imager Gallery 5.5 Prerelease &#8211; <strong>26 940</strong> views on Aspin with 9 votes (5 stars)</li>
<li>CrazyBeavers 2.4 &#8211; 6 147 views on Aspin with 1 votes (5 stars)</li>
<li>Imager Resizer 2.4 &#8211; <strong>17 325</strong> views on Aspin with 37 votes (5 stars)</li>
</ul>
<p>Now thats some numbers, over 22 000 views of Imager Gallery on HotScripts and almost 27 000 on Aspin. If we go a bit crazy and assume that a third the of people (probably it would be closer to a quarter of the people but that isn&#8217;t as fun to count with) also downloaded the script we would have 16 000 downloads of Imager Gallery there! If we then add the numbers we would have 17 000 assumed downloads which is quite a lot. Still, Imager Gallery is only the second most downloaded of my products. The true winner, and the only product which I know for sure how many times it has been downloaded, is <a href="http://www.winamp.com/plugins/details/143940" title="Visit CrazyBeavers Winamp Controller over at Winamp.com">CrazyBeavers Winamp Controller</a>. Counting in at <strong>25 239</strong> downloads since January 27th, 2005 its by far the most downloaded product I ever created and one of the few that I don&#8217;t use myself!</p>
<p>This article was just a little ego boost for myself but it feels so damn good that people actually seem to appreciate my work enough to download it over 20 000 times!</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.crazybeavers.se/index.php/archive/my-most-downloaded-resource/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Installing an ISAPI/CGI extension on Windows 2003</title>
		<link>http://blog.crazybeavers.se/index.php/archive/installing-an-isapicgi-extension-on-windows-2003/</link>
		<comments>http://blog.crazybeavers.se/index.php/archive/installing-an-isapicgi-extension-on-windows-2003/#comments</comments>
		<pubDate>Sun, 10 Jun 2007 21:28:54 +0000</pubDate>
		<dc:creator>Karl</dc:creator>
				<category><![CDATA[Articles]]></category>
		<category><![CDATA[IIS]]></category>
		<category><![CDATA[ISAPI/CGI]]></category>

		<guid isPermaLink="false">http://www.beaverblogg.com/index.php/archive/installing-an-isapicgi-extension-on-windows-2003/</guid>
		<description><![CDATA[This is the last article that has to be rewritten since I lost my database, it is also the one that people have asked for most so it feels good to finally get it up and running again. This article describes how to setup IIS6 on Windows 2003 to allow it to execute ISAPI and [...]]]></description>
			<content:encoded><![CDATA[<p>This is the last article that has to be rewritten since I lost my database, it is also the one that people have asked for most so it feels good to finally get it up and running again.</p>
<p>This article describes how to setup IIS6 on Windows 2003 to allow it to execute ISAPI and CGI extensions. For this example I&#8217;m using my own ISAPI application called Imager Resizer (which also was the reason that I wrote this article from the beginning).</p>
<p><img src="/wp-content/uploads/2007/06/icon.png" alt="Internet Information Services (IIS) Manager" /></p>
<p>First of all you need to locate your IIS Manager, if you don&#8217;t have it as a desktop icon as I have you will find it under Start->Settings->Control Panel->Administrative Tools->Internet Information Services and open it up.</p>
<p><img src="/wp-content/uploads/2007/06/iismanager.png" alt="IIS Manager" /></p>
<p>When the IIS Manager opens up you first click on &#8220;Web service Extensions&#8221; node in the tree view on your left. This brings up a list with the currently known ISAPI/CGI extensions on your server. At the top of the list you&#8217;ll see &#8220;All Unknown CGI Extensions&#8221; and &#8220;All Unknown ISAPI Extensions&#8221;, by default both these are prohibited and I would recommend that they stay that way. If you are running a ton of different ISAPI or CGI extensions or is just a very lazy person that doesn&#8217;t care to much about security you can allow unknown extensions to execute but remember that if someone manage to put an ISAPI or CGI extension on your server without you knowing (a flawed upload script or whatever) they can do almost anything with it. If you decide to allow all unknown extensions you can skip to the <a href="#article_last_step" title="Skip to last part">last part of the article</a> now.</p>
<p><img src="/wp-content/uploads/2007/06/iismanager_actionmenu.png" alt="IIS Manager with expanded Action menu" /></p>
<p>To add a new extension to the list you can either go via the Action menu and selecting &#8220;Add a new Web service extension&#8221; or you can right click in the list (not on an item though!) and select the same thing.</p>
<p><img src="/wp-content/uploads/2007/06/iismanager_newextension.png" alt="IIS Manager with the New Web Service Extension dialog open" /></p>
<p>This dialog is quite self explanatory but I&#8217;ll describe it anyway. Here you assign a name to identify the extension, in my case I chose &#8220;Imager Resizer&#8221; for the name. Then I click the &#8220;Add&#8221; button to browse to the required files (only Imager.dll in my case) and then finally I check the checkbox with the label &#8220;Set extension status to Allowed&#8221; so I don&#8217;t have to enable it manually afterwards. After that, I simply click OK and the dialog vanishes. Now Imager Resizer will be visible in the extension list (since I took the screenshots from my production server Imager Resizer was already in the list though) and it&#8217;s status is set to Allowed.</p>
<p><img src="/wp-content/uploads/2007/06/object_properties.png" alt="Properties dialog for a virtual directory in IIS Manager" id="article_last_step" /></p>
<p>Now we&#8217;ve introduced Imager.dll to IIS and told it to allow it to execute, however there is one more condition that must be filled and it has been there since IIS5 and maybe even longer then that. Anyway, what you need to do is to set the &#8220;Execute permissions&#8221; for the folder that holds the extension to &#8220;Scripts and Executables&#8221;. This is done by locating the folder in the IIS Manager (under Web Sites->MySite for example), right clicking on it and then selecting properties. In the properties dialog you chose the &#8220;Virtual Directory&#8221;/&#8221;Home directory&#8221; tab and look at the bottom of it. The second combobox counting from the bottom is the &#8220;Execute permissions&#8221; (hopefully you were able to read that yourself though) and it is probably set to &#8220;Scripts only&#8221; to start with. Set it to &#8220;Scripts and Executables&#8221; and click OK.</p>
<p>Thats it, now you should be able to browse to your extension and see it in action. If using Imager Resizer you can use the /test action to verify that it works correctly by going to http://www.mysite.com/Imager.dll/test. It should then return a page looking something like this: <a href="http://www.kallesbildarkiv.se/cgi-bin/Imager.dll/test">http://www.kallesbildarkiv.se/cgi-bin/Imager.dll/test</a>. Thats it for this article, hope I didn&#8217;t miss anything essential and that it will help a few people setting up Imager Resizer or any other ISAPI or CGI extensions.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.crazybeavers.se/index.php/archive/installing-an-isapicgi-extension-on-windows-2003/feed/</wfw:commentRss>
		<slash:comments>15</slash:comments>
		</item>
		<item>
		<title>Displaying an RSS feed using XMLDom and ASP</title>
		<link>http://blog.crazybeavers.se/index.php/archive/displaying-an-rss-feed-using-xmldom-and-asp/</link>
		<comments>http://blog.crazybeavers.se/index.php/archive/displaying-an-rss-feed-using-xmldom-and-asp/#comments</comments>
		<pubDate>Tue, 24 Apr 2007 13:21:11 +0000</pubDate>
		<dc:creator>Karl</dc:creator>
				<category><![CDATA[Articles]]></category>
		<category><![CDATA[ASP]]></category>
		<category><![CDATA[XML]]></category>

		<guid isPermaLink="false">http://www.beaverblogg.com/index.php/archive/displaying-an-rss-feed-using-xmldom-and-asp/</guid>
		<description><![CDATA[It happened again. I saw some really horrible examples today on how to show an RSS feed using XMLDom so I took another trip with the WayBackMachine to try to dig this article up. After figuring which id-number this post had on the old installation it wasn&#8217;t that hard. Anyone remembered why I wrote this [...]]]></description>
			<content:encoded><![CDATA[<p>It happened again. I saw some really horrible examples today on how to show an RSS feed using XMLDom so I took another trip with the <a href="http://www.archive.org/web/web.php">WayBackMachine</a> to try to dig this article up. After figuring which id-number this post had on the old installation it wasn&#8217;t that hard.</p>
<p>Anyone remembered why I wrote this article the first time? Here is a quote from the original about why I wrote it.</p>
<blockquote><p>Imagine a script that selects all nodes (XPath query was something like “//*”), not caring where in the document, then looping them thru looking at their names and guessing what they are and then adding them to four separate strings with some weird separator. After doing this, they split the strings into four arrays and started looping out the content. Oh please, it was horrible. No real sense of XML at all I’m afraid  . I know there are better resources then that on the net, but I still felt I had to contribute with just one more.</p></blockquote>
<p>Hopefully there are still people who need to learn this out there so I didn&#8217;t waste my time recovering it. Anyway, let&#8217;s get going</p>
<p>If you never heard of RSS earlier, you are either very ignorant to what happens on the web these days and/or you are stuck running Internet Explorer which lacks any built in support for it. It all comes down quite easy though. An RSS feed is an online news syndication in the XML format. The main idea is to have a standardized way to share news over the net. I for an instance offers my articles as an RSS feed so people easily will know when I’ve written something new. For those who want to dive deeper into RSS I would recommend “<a href="http://www.xml.com/pub/a/2002/12/18/dive-into-xml.html">What Is RSS</a>” over at <a href="http://www.xml.com/">XML.com</a>.</p>
<p>I thought that it might also be a good idea to show a short RSS feed with only one news item in it so you know what source we are working with.</p>
<pre class="brush: xml; title: ;">
&lt;?xml version=&quot;1.0&quot; encoding=&quot;ISO-8859-1&quot;?&gt;
&lt;rss version=&quot;2.0&quot;&gt;
  &lt;channel&gt;
    &lt;title&gt;My company RSS Feed&lt;/title&gt;
    &lt;link&gt;http://www.mysite.com/&lt;/link&gt;
    &lt;description&gt;My company extends products using XML&lt;/description&gt;
    &lt;language&gt;en-uk&lt;/language&gt;
    &lt;pubdate&gt;Fri, 16 Apr 2006 15:15:00 +0200&lt;/pubdate&gt;
    &lt;item&gt;
      &lt;title&gt;New company started&lt;/title&gt;
      &lt;link&gt;http://www.mysite.com/news.asp?id=26&lt;/link&gt;
      &lt;comments&gt;http://www.mysite.com/comments.asp?id=26&lt;/comments&gt;
      &lt;description&gt;Here the description goes&lt;/description&gt;
      &lt;pubdate&gt;Fri, 16 Feb 2006 00:00:00 +0200&lt;/pubdate&gt;
&lt;/rss&gt;
</pre>
<p>This is a quite minimal feed document. It could have any number of “item” nodes aswell as it could have way more descriptive tags both for the channel and for the items. This is not how the feed for my site looks. I’m using a nice tool that generates everything for me and puts in 10 or 15 extra tags that are far from necessary. I feel that it would be quite an overkill to start out with that and I doubt that more then 5% of the RSS readers out there actually cares about all those tags anyway.</p>
<p>Anyway, lets get going. For those who have read my previous tutorials, there isn’t anything really new here, for those who haven’t, I would recommend reading <a href="http://www.beaverblogg.com/index.php/archive/xml-xmldom-and-asp-part-1/">XML, XMLDom and ASP Part 1</a> and <a href="http://www.beaverblogg.com/index.php/archive/xml-xmldom-and-asp-part-2/">XML, XMLDom and ASP Part 2</a>.</p>
<pre class="brush: vb; title: ;">
dim xmlDom, nodeCol, oNode, oChildNode
set xmlDom = Server.CreateObject(&quot;MSXML2.Domdocument.4.0&quot;)

call xmlDom.setProperty(&quot;ServerHTTPRequest&quot;, true)
xmlDom.async = false
call xmlDom.load(&quot;http://www.beaverblogg.com/?feed=rss2&quot;)

if not xmlDom.documentElement is nothing then
  set nodeCol = xmlDom.documentElement.selectNodes(&quot;channel/item&quot;)
  for each oNode in nodeCol
    Response.Write(&quot;&lt;p&gt;&quot; &amp; vbCrLf)
    set oChildNode = oNode.selectSingleNode(&quot;title&quot;)
    if not oChildNode is nothing then
      Response.Write(&quot;  &lt;h1&gt;&quot; &amp; oChildNode.text &amp; &quot;&lt;/h1&gt;&quot; &amp; vbCrLf)
    end if
    set oChildNode = oNode.selectSingleNode(&quot;pubDate&quot;)
    if not oChildNode is nothing then
      Response.Write(&quot;  &amp;raquo; &quot; &amp; oChildNode.text &amp; &quot;&lt;br /&gt;&quot; &amp; vbCrLf)
    end if
    set oChildNode = oNode.selectSingleNode(&quot;description&quot;)
    if not oChildNode is nothing then
      Response.Write(&quot;  &quot; &amp; oChildNode.text &amp; &quot;&lt;br /&gt;&quot; &amp; vbCrLf)
    end if
    set oChildNode = oNode.selectSingleNode(&quot;link&quot;)
    if not oChildNode is nothing then
      Response.Write(&quot;  &lt;br /&gt;&quot; &amp; vbCrLf)
      Response.Write(&quot;  &lt;a href=&quot;&quot;&quot; &amp; oChildNode.text &amp; &quot;&quot;&quot; target=&quot;&quot;_blank&quot;&quot;&gt;&quot;)
      Response.Write(&quot;    Link to full article&quot; &amp; vbCrLf)
      Response.Write(&quot;  &lt;/a&gt;&quot; &amp; vbCrLf)
    end if
    Response.Write(&quot;&lt;/p&gt;&quot; &amp; vbCrLf)
  next
else
  Response.Write(&quot;&lt;p&gt;&quot; &amp; vbCrLf)
  Response.Write(&quot;  An error occured.&quot; &amp; vbCrLf)
  Response.Write(&quot;&lt;/p&gt;&quot; &amp; vbCrLf)
end if
</pre>
<p>So lets start examining the code then.</p>
<pre class="brush: vb; title: ;">
dim xmlDom, nodeCol, oNode, oChildNode
set xmlDom = Server.CreateObject(&quot;MSXML2.Domdocument.4.0&quot;)

call xmlDom.setProperty(&quot;ServerHTTPRequest&quot;, true)
xmlDom.async = false
call xmlDom.load(&quot;http://www.beaverblogg.com/?feed=rss2&quot;)
</pre>
<p>This part is very almost a carbon copy of the first lines in my second article, I just added nodeCol, oNode, oChildNode and i to the variable declaration and set the async property to false. The async property tells if the dom should proceed in asynchronous or synchronous mode. Since we don’t want it to continue to execute without being done with the HTTP request, we set it to false (synchronous mode).</p>
<pre class="brush: vb; title: ;">
if not xmlDom.documentElement is nothing then
 ...
else
  Response.Write(&quot;&lt;p&gt;&quot; &amp; vbCrLf)
  Response.Write(&quot;  An error occured.&quot; &amp; vbCrLf)
  Response.Write(&quot;&lt;/p&gt;&quot; &amp; vbCrLf)
end if
</pre>
<p>Next, we have a simple if statement to see if the document has a documentElement (root element, remember?). If not, we show a short error message.</p>
<pre class="brush: vb; title: ;">
  set nodeCol = xmlDom.documentElement.selectNodes(&quot;channel/item&quot;)
  for each oNode in nodeCol
    ...
  next
</pre>
<p>If the script got this far, we probably got our RSS feed without any problems. Now we call the selectNodes function to select all item nodes from the feed and put the collection in nodeCol. Then, we do a simple for-each loop to go through all the nodes in the collection.</p>
<pre class="brush: vb; title: ;">
    Response.Write(&quot;&lt;p&gt;&quot; &amp; vbCrLf)
    set oChildNode = oNode.selectSingleNode(&quot;title&quot;)
    if not oChildNode is nothing then
      Response.Write(&quot;  &lt;h1&gt;&quot; &amp; oChildNode.text &amp; &quot;&lt;/h1&gt;&quot; &amp; vbCrLf)
    end if
    set oChildNode = oNode.selectSingleNode(&quot;pubDate&quot;)
    if not oChildNode is nothing then
      Response.Write(&quot;  &amp;raquo; &quot; &amp; oChildNode.text &amp; &quot;&lt;br /&gt;&quot; &amp; vbCrLf)
    end if
    set oChildNode = oNode.selectSingleNode(&quot;description&quot;)
    if not oChildNode is nothing then
      Response.Write(&quot;  &quot; &amp; oChildNode.text &amp; &quot;&lt;br /&gt;&quot; &amp; vbCrLf)
    end if
    set oChildNode = oNode.selectSingleNode(&quot;link&quot;)
    if not oChildNode is nothing then
      Response.Write(&quot;  &lt;br /&gt;&quot; &amp; vbCrLf)
      Response.Write(&quot;  &lt;a href=&quot;&quot;&quot; &amp; oChildNode.text &amp; &quot;&quot;&quot; target=&quot;&quot;_blank&quot;&quot;&gt;&quot;)
      Response.Write(&quot;    Link to full article&quot; &amp; vbCrLf)
      Response.Write(&quot;  &lt;/a&gt;&quot; &amp; vbCrLf)
    end if
    Response.Write(&quot;&lt;/p&gt;&quot; &amp; vbCrLf)
</pre>
<p>This might seem like a long chunk of code, but it’s quite repetive so I think you can handle it. First of all, we write some standard html markup. We encapsulate each item in a paragraph. Next, we try to select a childnode from the current node. Each item should have a title, a pubdate, a description and a link, but since people are lazy sometimes they leave one or several of them out so to make this as general as possible we make sure that the nodes exists to avoid a crash. Anyway, we try to selet any childnode named title and put it into the oChildNode variable. Then, if not oChildNode is nothing, we can ouput the text content of that node by using oChildNode.text. Again we are adding some markup to the code, this to make it easy to style it afterwards using CSS. We repeat the exact same thing for the other “supposed to be there” nodes and print them out accordingly. We even make a link out of the link node if it exists. And well, thats kinda it.</p>
<p>This post didn’t take long to write so I apologize if it contains any errors of some sort. If it do, then please tell me so I can correct them as fast as possible. It was quite fun though to join the stuff I’ve written about in the first to articles into this one and there will be more to come!</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.crazybeavers.se/index.php/archive/displaying-an-rss-feed-using-xmldom-and-asp/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>XML, XMLDom and ASP, Part 2</title>
		<link>http://blog.crazybeavers.se/index.php/archive/xml-xmldom-and-asp-part-2/</link>
		<comments>http://blog.crazybeavers.se/index.php/archive/xml-xmldom-and-asp-part-2/#comments</comments>
		<pubDate>Mon, 09 Apr 2007 20:34:07 +0000</pubDate>
		<dc:creator>Karl</dc:creator>
				<category><![CDATA[Articles]]></category>
		<category><![CDATA[ASP]]></category>
		<category><![CDATA[XML]]></category>

		<guid isPermaLink="false">http://www.beaverblogg.com/index.php/archive/xml-xmldom-and-asp-part-2/</guid>
		<description><![CDATA[This is the second article in my series about XML, XMLDom and ASP. For those who missed the first it&#8217;s available here In my first article I showed how to parse an XML document using XMLDom and displaying the data. In this second tutorial I&#8217;ll show two different ways to retrieve an XML document from [...]]]></description>
			<content:encoded><![CDATA[<p>This is the second article in my series about XML, XMLDom and ASP. For those who missed the first it&#8217;s available <a href="/index.php/archive/xml-xmldom-and-asp-part-1/">here</a></p>
<p>In my first article I showed how to parse an XML document using XMLDom and displaying the data. In this second tutorial I&#8217;ll show two different ways to retrieve an XML document from a remote server using ASP and ServerXMLHTTP.</p>
<p>XML is a great way to share information. However, if you want to be able to share it people will need to retrieve the data from you somehow (or you from them). For this purpose we have an object called XMLHTTP or, if used on a server, ServerXMLHTTP. Since both XMLDom and XMLHTTP are part of MSXML2 they can cooperate very nice. XMLDom can by auto use XMLHTTP to retrieve information and if you use XMLHTTP it can by auto return a XMLDom object with the retrieved XML data.</p>
<p>The easiest way to retrieve XML from an external site is to let the XMLDom handle it all. This requires the least amount of code and I would guess that it&#8217;s also a tiny bit more effective resource wise. Here is how to do it:</p>
<pre class="brush: vb; title: ;">
dim xmlDom
set xmlDom = Server.CreateObject(&quot;MSXML2.Domdocument.4.0&quot;)

call xmlDom.setProperty(&quot;ServerHTTPRequest&quot;, true)
call xmlDom.load(&quot;http://www.beaverblogg.com/?feed=rss2&quot;)
</pre>
<p>This code is really simple so I&#8217;ll describe it all in one chunk. First we declare the variable and create the xmlDom object. This is precisely as we did in the first article so far. Next we call the setProperty method to specify that it should use the &#8220;ServerHTTPRequest&#8221; feature. By specifying this we are able to pass an URL to the load method which we do on the next line. In this example it will load my RSS feed into the xmlDom.</p>
<p>This might seem like a great solution since it&#8217;s so simple, however it has some drawbacks. First of all, if the URL is unavaible, it will throw an error. Aswell as if the loaded data isn&#8217;t wellformed xml, it will throw an error. So to be sure that this code doesn&#8217;t throw an nasty error on your visitors you would have to extend it with some error handling.</p>
<pre class="brush: vb; title: ;">
dim xmlDom
set xmlDom = Server.CreateObject(&quot;MSXML2.Domdocument.4.0&quot;)

on error resume next

call xmlDom.setProperty(&quot;ServerHTTPRequest&quot;, true)
call xmlDom.load(&quot;http://www.beaverblogg.com/?feed=rss2&quot;)

if(Err &lt;&gt; 0) then
  Response.Write(&quot;An error occured when retrieving data from an external source.&quot;)
  Response.Write(Err.Description)
  Response.End
end if

on error goto 0
</pre>
<p>There we have it, some basic error handling to see if it loaded or not. I expect that people know at least some about error handling in ASP. If not, then write a comment about it and I make take it up a bit more in an later article.</p>
<p>The other way to go to retrieve external information is to manually create the ServerXMLHTTP object and making it browse to the URL and return it&#8217;s contents. This requires a bit more code, but it also has some other nice features. For example, it can post data to the remote server, it can retrieve other data then just xml like a binary file or a simple text document. I will start by creating the same example as I did previous in this article using ServerXMLHTTP.</p>
<pre class="brush: vb; title: ;">
dim xmlDom, xmlHttp
set xmlHttp = Server.CreateObject(&quot;Msxml2.ServerXMLHTTP.4.0&quot;)

call xmlHttp.Open(&quot;GET&quot;, &quot;http://www.beaverblogg.com/?feed=rss2&quot;)
call xmlHttp.Send()

set xmlDom = xmlHttp.responseXML
</pre>
<p>This made for a whole extra line to the code if compared to the original earlier in this post. This one isn&#8217;t much harder to understand then the previous one. We declare the variables, we create the ServerXMLHTTP object and then we call the Open method of the xmlHttp object. This method takes two arguments, first one is a string which describes the HTTP method to use. GET is fine unless you need to post data which you mostly won&#8217;t do. The second argument is the URL to retrieve the data from and again we use my RSS feed. After that we call the Send method which will trigger the object to browse to our URL and fetch the data. The Send method takes one optional argument which is the data to send to the URL. When using GET as method this has no real function. Last in the script we retrieve an xmlDom from the responseXML property of xmlHttp.</p>
<p>That wasn&#8217;t to bad was it? Though it isn&#8217;t ever as simple as it seems. If you are browsing to a url that doesn&#8217;t return &#8220;text/xml&#8221; as content type the responseXML property will be empty so we will need to add some error handling to that as well. Also, if you take the URL as a dynamic parameter and it doesn&#8217;t contain a valid URL or the URL is unavaible it will throw an error. So lets add the same as in the previous example here aswell and add some stuff to it.</p>
<pre class="brush: vb; title: ;">
dim xmlDom, xmlHttp
set xmlHttp = Server.CreateObject(&quot;Msxml2.ServerXMLHTTP.4.0&quot;)

on error resume next

call xmlHttp.Open(&quot;GET&quot;, &quot;http://www.beaverblogg.com/?feed=rss2&quot;)
call xmlHttp.Send()

if(Err &lt;&gt; 0) then
  Response.Write(&quot;An error occured when retrieving data from an external source.&lt;br /&gt;&quot;)

  Response.Write(Err.Description)
  Response.End
end if

on error goto 0

if(xmlHttp.status &lt;&gt; 200) then
  Response.Write(&quot;The remote server returned an invalid statuscode: #8221; &amp; _
                       xmlHttp.status &amp; &quot; &quot; &amp; xmlHttp.statusText)
  Response.End
end if

if xmlHttp.responseXML is nothing then
  Response.Write(&quot;The remote server didn't return xml content.&quot;)
  Response.End
end if

set xmlDom = xmlHttp.responseXML
</pre>
<p>I know, it&#8217;s a mess. But it covers all problems that can arise and provides specific error messages for the different ones. I have to admit, I never go this far in error handling but I still want to show what that can be done and what to look for.</p>
<pre class="brush: vb; title: ;">
if(Err &lt;&gt; 0) then
  Response.Write(&quot;An error occurred when retrieving data from an external source.&quot;)
  Response.End
end if
</pre>
<p>After calling the Send method it might be an good idea to check the error object. If something failed miserably it probably was here.</p>
<pre class="brush: vb; title: ;">
if(xmlHttp.status &lt;&gt; 200) then
  Response.Write(&quot;The remote server returned an invalid statuscode: &quot; &amp; _
                       xmlHttp.status &amp; &quot; &quot; &amp; xmlHttp.statusText)
  Response.End
end if
</pre>
<p>After that it can always be an good idea to have a look at the status property to see what HTTP response code it returned. It it wasn&#8217;t 200 (HTTP 200 OK) we don&#8217;t want the data. Other usual statuscodes are 404 (File not found) and 500 (Internal server error) so those who want it really nice can check for those aswell and output it to the user.</p>
<pre class="brush: vb; title: ;">
if xmlHttp.responseXML is nothing then
  Response.Write(&quot;The remote server didn't return xml content.&quot;)
  Response.End
end if
</pre>
<p>Last we check if there is a responseXML object avaible. If it isn&#8217;t, then the server returned an invalid response (and might be caught already but not for sure).</p>
<p>There we have it, two different approaches to retrieving XML from an external source. There is however one more thing I would like to talk about. In this article I&#8217;ve used the ServerXMLHTTP object. When asking my good friend <a href="http://www.google.com/" title="Visit my friend Google!">Google</a> about retrieving external data using ASP I found several articles telling the readers to create the &#8220;Microsoft.XMLHTTP&#8221; object or &#8220;MSXML2.XMLHTTP.4.0&#8243;. This will work on your ASP page, but it&#8217;s not a very good idea to use. They were created for use in a client environment, not to be executed by a server. They rely on winsock (or some other client side communication layer, can&#8217;t remember exactly which, sorry) instead of winhttp which is used for server applications. Being built as clientside objects they also use the current proxy settings from Internet Explorer which might not always be desirable. I will get back to these objects in a later article when I start to talk about Ajax development which works with these objects using clientside JavaScript.</p>
<p>I haven&#8217;t decided yet what to write about in Part 3 to be honest. It will be XML for sure, but I&#8217;m not sure if I will go for simple XSL stylesheets or creating new documents using xmlDom only. Tune in for my next article and we&#8217;ll see what it contains <img src='http://www.beaverblogg.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> .</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.crazybeavers.se/index.php/archive/xml-xmldom-and-asp-part-2/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>XML, XMLDom and ASP, Part 1</title>
		<link>http://blog.crazybeavers.se/index.php/archive/xml-xmldom-and-asp-part-1/</link>
		<comments>http://blog.crazybeavers.se/index.php/archive/xml-xmldom-and-asp-part-1/#comments</comments>
		<pubDate>Mon, 09 Apr 2007 20:30:00 +0000</pubDate>
		<dc:creator>Karl</dc:creator>
				<category><![CDATA[Articles]]></category>
		<category><![CDATA[ASP]]></category>
		<category><![CDATA[XML]]></category>

		<guid isPermaLink="false">http://www.beaverblogg.com/index.php/archive/xml-xmldom-and-asp-part-1/</guid>
		<description><![CDATA[Everyone who works with the web these days know what XML is, but how many know how to really use it? Over the past months I&#8217;ve seen lots of people using regexps to parse XML as text strings and people trying to use the XMLDom in ASP and failing miserably. They just look at me [...]]]></description>
			<content:encoded><![CDATA[<p align="left">Everyone who works with the web these days know what XML is, but how many know how to really use it? Over the past months I&#8217;ve seen lots of people using regexps to parse XML as text strings and people trying to use the XMLDom in ASP and failing miserably. They just look at me like I&#8217;m stupid or something when I try to mention XPath as the correct way to go and kindly explain that they use XML, not XPath. I&#8217;ve been working with XML and XMLDom for over a bit over a year now and I feel really comfortable with it. It can do just about everything I want it to.</p>
<p align="left">Here is a quite typical XML document. It contains a root element, a description tag and a collection of files.</p>
<pre class="brush: xml; title: ;">
&lt;root&gt;
  &lt;description&gt;Files attached to subject 1&lt;/description&gt;
  &lt;files&gt;
    &lt;file filename=&quot;beaver.jpg&quot; size=&quot;12432&quot; description=&quot;A picture of a beaver&quot; /&gt;
    &lt;file filename=&quot;beaver2.jpg&quot; size=&quot;53174&quot; description=&quot;Another picture of a beaver&quot; /&gt;
    &lt;file filename=&quot;beaverfarm.doc&quot; size=&quot;162475&amp;#8243; description=&quot;Secret plans of new beaver farm&quot; /&gt;
  &lt;/files&gt;
&lt;/root&gt;
</pre>
<p align="left">Thats the way I like to have my XML. As much as possible as attributes. Some people seem to prefer this type though:</p>
<pre class="brush: xml; title: ;">
&lt;root&gt;
  &lt;description&gt;Files attached to subject 1&lt;/description&gt;
  &lt;files&gt;
    &lt;file&gt;
      &lt;filename&gt;beaver.jpg&lt;/filename&gt;
      &lt;size&gt;12432&lt;/size&gt;
      &lt;description&gt;A picture of a beaver&lt;/description&gt;
    &lt;/file&gt;
    &lt;file&gt;
      &lt;filename&gt;beaver2.jpg&lt;/filename&gt;
      &lt;size&gt;53174&lt;/size&gt;
      &lt;description&gt;Another picture of a beaver&lt;/description&gt;
    &lt;/file&gt;
    &lt;file&gt;
      &lt;filename&gt;beaverfarm.doc&lt;/filename&gt;
      &lt;size&gt;162475&lt;/size&gt;
      &lt;description&gt;Secret plans of new beaver farm&lt;/description&gt;
    &lt;/file&gt;
  &lt;/files&gt;
&lt;/root&gt;
</pre>
<p align="left">This is easier to understand for a beginner maybe but it&#8217;s not as easy to work with as the first data.</p>
<p align="left">Anyway, lets try to get some data out of this. Lets imagine that the XML data is avaible in a filed called Data.xml in the same folder as the script. I&#8217;ll concentrate on the first XML example to start with.</p>
<pre class="brush: vb; title: ;">dim xmlDom, oNode, nodeCol
set xmlDom = Server.CreateObject(&quot;MSXML2.DOMDocument.4.0&quot;)
xmlDom.load(Server.Mappath(&quot;Data.xml&quot;))
if(xmlDom.parseError &lt;&gt; 0) then

  Response.Write(&quot;Invalid XML loaded. &quot; &amp; xmlDom.parseError.reason)
  Response.End
end if

if xmlDom.documentElement is nothing then
  Response.Write(&quot;Invalid XML loaded. No root tag exists&quot;)
  Response.End
end if

set oNode = xmlDom.documentElement.selectSingleNode(&quot;description&quot;)
if not oNode is nothing then
  Response.Write(&quot;Description: &quot; &amp; oNode.text &amp; &quot;&lt;br /&gt;&quot;)
end if

set nodeCol = xmlDom.documentElement.selectNodes(&quot;files/file&quot;)
for each oNode in nodeCol

  Response.Write(&quot;&lt;span title=&quot;&quot;&quot;)
  Response.Write(Server.HTMLEncode(oNode.getAttribute(&quot;description&quot;))
  Response.Write(&quot;&quot;&quot;&gt;File: &quot;)
  Response.Write(Server.HTMLEncode(oNode.getAttribute(&quot;filename&quot;)))
  Response.Write(&quot; (&quot;)

  Response.Write(Server.HTMLEncode(oNode.getAttribute(&quot;size&quot;)))
  Response.Write(&quot; bytes)&lt;/span&gt;&lt;br /&gt;&quot;)
next</pre>
<p align="left">The output of this would look something like this:</p>
<p align="left">Description: Files attached to subject 1<br />
<span title="A picture of a beaver">File: beaver.jpg (12432 bytes)</span><br />
<span title="Another picture of a beaver">File: beaver2.jpg (53174 bytes)</span></p>
<p><span title="Plan of new beaver farm">File: beaverfarm.doc (162475 bytes)</span>
</p>
<p align="left">Not to shabby if you ask me. Lets take a quick stroll through the code now.</p>
<pre class="brush: vb; title: ;">
dim xmlDom, oNode, nodeCol
set xmlDom = Server.CreateObject(&quot;MSXML2.DOMDocument.4.0&quot;)
xmlDom.load(Server.Mappath(&quot;Data.xml&quot;))
if(xmlDom.parseError &lt;&gt; 0) then
  Response.Write(&quot;Invalid XML loaded. &quot; &amp; xmlDom.parseError.reason)
  Response.End
end if
</pre>
<p align="left">This part kinda explains itself. Declare the variables we are going to use. Then create the XMLDom object. We expect the data to be in a file called Data.xml in the current folder so we use Server.Mappath to get the absolute path to it and then calls .load from the XMLDom to load the data.</p>
<p align="left">Then to be sure that there was no problems with the loading we check that the parseError property of the XMLDom is 0. If it isn&#8217;t something is wrong with our XML data and we show an error and quit.</p>
<pre class="brush: vb; title: ;">
if xmlDom.documentElement is nothing then
  Response.Write(&quot;Invalid XML loaded. No root tag exists&quot;)
  Response.End
end if

set oNode = xmlDom.documentElement.selectSingleNode(&quot;description&quot;)
if not oNode is nothing then
  Response.Write(&quot;Description: &quot; &amp; oNode.text &amp; &quot;&lt;br /&gt;&quot;)
end if
</pre>
<p align="left">The second part might be a bit harder to understand. First, we check if xmlDom.documentElement is nothing. If it is we throw an error and end the execution of the script. The documentElement of a XML document is the root element. In our case, the <root> tag. Every XML document needs one and only one root element. It can be named anything however so </root><root> isn&#8217;t a mandatory name, I just like to use it. If xmlDom.documentElement is nothing then it&#8217;s most likely that Data.xml was just an empty file. The XMLDom could parse the data without problems since there wasn&#8217;t anything to parse so this is a good thing to look for.</root></p>
<p align="left">Next we try to read out the description element by using a XPath query. The function used is called selectSingleNode() and will return one single node (just as it&#8217;s name says) from the specified XPath query. It is avaible on any node in the document and works with relative XPaths. My XPath query is very simple and states that I want the node called &#8220;description&#8221;. I call the procedure from the documentElement node so I don&#8217;t have to write &#8220;root/description&#8221; which is it&#8217;s real path. Calling xmlDom.selectSingleNode(&#8220;root/description&#8221;) would return the same result.</p>
<p align="left">After selecting the node and puttings it&#8217;s reference in the oNode variable we make an if-statement to see if it returned an object. If oNode is nothing then there wasn&#8217;t any node called &#8220;description&#8221; at the specified place in the document. If it isn&#8217;t nothing, then we expect that we got the right now and print it out using it&#8217;s .text property.</p>
<pre class="brush: vb; title: ;">
set nodeCol = xmlDom.documentElement.selectNodes(&quot;files/file&quot;)
for each oNode in nodeCol
  Response.Write(&quot;&lt;span title=&quot;&quot;&quot;)
  Response.Write(Server.HTMLEncode(oNode.getAttribute(&quot;description&quot;))
  Response.Write(&quot;&quot;&quot;&gt;File: &quot;)
  Response.Write(Server.HTMLEncode(oNode.getAttribute(&quot;filename&quot;)))
  Response.Write(&quot; (&quot;)
  Response.Write(Server.HTMLEncode(oNode.getAttribute(&quot;size&quot;)))
  Response.Write(&quot; bytes)&lt;/span&gt;&lt;br /&gt;&quot;)
next
</pre>
<p align="left">Not much left now. Here we use another procedure called selectNodes(). Like selectSingleNode() this procedure is avaible on all nodes and uses an XPath query to specify which nodes that we want. The main difference is that selectNodes() returns a collection of nodes instead of a single one.</p>
<p align="left">The XPath query this time specifies that we want all &#8220;file&#8221; nodes under &#8220;files&#8221;. Not to hard to understand this one either. We put the reference to the collection in the nodeCol variable.</p>
<p align="left">Next we initiate a for-each loop to go through all the nodes in a simple manner. We write out some markup (HTML) to make it look good. First we create a <span> tag with a title attribute in which we put the file description. Every node has a function called getAttribute() which takes one parameter with the attribute name. It returns an empty string if the attribute was not found and if it exists it returns the value. We make sure to HTMLEncode the value since we might not know what text is in the attribute and we don&#8217;t want anything that breaks our markup do we?</span></p>
<p align="left">We end the opening <span> tag and write out the filename. We also add a paranthesis with the filesize in bytes. All using the .getAttribute function. Then finallyl we close the <span> tag and add a linebreak before the next file.</span></span></p>
<p align="left">This is the way I like it to be done. If I got to shape the XML it would be as much as possible in the attributes and as few element nodes as possible. But since I don&#8217;t get to chose XML in all cases I still get suck with the second XML example some times. Here is how the code to produce the same output would look using that source data.</p>
<pre class="brush: vb; title: ;">dim xmlDom, oNode, nodeCol
set xmlDom = Server.CreateObject(&quot;MSXML2.DOMDocument.4.0&quot;)
xmlDom.load(Server.Mappath(&quot;Data.xml&quot;))
if(xmlDom.parseError &lt;&gt; 0) then
  Response.Write(&quot;Invalid XML loaded. &quot; &amp; xmlDom.parseError.reason)
  Response.End
end if

if xmlDom.documentElement is nothing then
  Response.Write(&quot;Invalid XML loaded. No root tag exists&quot;)
  Response.End
end if

set oNode = xmlDom.documentElement.selectSingleNode(&quot;description&quot;)
if not oNode is nothing then

  Response.Write(&quot;Description: &quot; &amp; oNode.text &amp; &quot;&lt;br /&gt;&quot;)
end if

set nodeCol = xmlDom.documentElement.selectNodes(&quot;files/file&quot;)
for each oNode in nodeCol
  Response.Write(&quot;&lt;span title=&quot;&quot;&quot;)
  Response.Write(Server.HTMLEncode(oNode.selectSingleNode(&quot;description&quot;).text)
  Response.Write(&quot;&quot;&quot;&gt;File: &quot;)
  Response.Write(Server.HTMLEncode(oNode.selectSingleNode(&quot;filename&quot;).text))
  Response.Write(&quot; (&quot;)
  Response.Write(Server.HTMLEncode(oNode.selectSingleNode(&quot;size&quot;).text))
  Response.Write(&quot; bytes)&lt;/span&gt;&lt;br /&gt;&quot;)
next</pre>
<p align="left">Not much happened there until the last block. Now I have to use selectSingleNode() to get the subnodes (child nodes) and look at their text property to get the values out. This might not seem like a great problem but most people get tired of havings lots and lots of element nodes after some time.</p>
<p align="left">XPath is a quite powerful query language. You can specify in quite detail what nodes you want. For example, if I only want files that are smaller then 100kb I could just change a bit in the script to this:</p>
<pre class="brush: vb; title: ;">
set nodeCol = xmlDom.documentElement.selectNodes(&quot;files/file[@size&lt;102400]&quot;)
</pre>
<p align="left">Adding [] after a node tells that I want to evalutate something. The @ before &#8220;size&#8221; denotes that I want to look at an attribute node. It&#8217;s quite easy to understand for most. If I would like to do this using the second example the query would look like this:</p>
<pre class="brush: vb; title: ;">
set nodeCol = xmlDom.documentElement.selectNodes(&quot;files/file[size&lt;102400]&quot;)
</pre>
<p align="left">This has been a brief introduction to working with the XMLDom in ASP aswell as making some simple XPath queries. It is also my first serious blogg post ever written so I hope someone finds it interessting. It was written in one evening without testing any of the code. Next time I&#8217;ll dig a bit deeper into XPath and show how you can retrieve XML data from an external websource using XMLHTTP.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.crazybeavers.se/index.php/archive/xml-xmldom-and-asp-part-1/feed/</wfw:commentRss>
		<slash:comments>14</slash:comments>
		</item>
	</channel>
</rss>

