<?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; Code samples</title>
	<atom:link href="http://blog.crazybeavers.se/index.php/archive/category/code-samples/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>Geocoding with Google Maps API</title>
		<link>http://blog.crazybeavers.se/index.php/archive/geocoding-with-google-maps-api/</link>
		<comments>http://blog.crazybeavers.se/index.php/archive/geocoding-with-google-maps-api/#comments</comments>
		<pubDate>Fri, 22 Oct 2010 10:45:22 +0000</pubDate>
		<dc:creator>Karl</dc:creator>
				<category><![CDATA[.Net]]></category>
		<category><![CDATA[c#]]></category>
		<category><![CDATA[Code samples]]></category>
		<category><![CDATA[coordinates]]></category>
		<category><![CDATA[geodesy]]></category>
		<category><![CDATA[google maps]]></category>
		<category><![CDATA[sample]]></category>

		<guid isPermaLink="false">http://blog.crazybeavers.se/?p=178</guid>
		<description><![CDATA[It has been many months since I posted something here so finally today I wrote a small function that I thought I could share to get this blog going again. It&#8217;s a small snippet that takes an address and tries to geocode it (convert it to coordinates) using the Google Maps API. public class Coordinate [...]]]></description>
			<content:encoded><![CDATA[<p>It has been many months since I posted something here so finally today I wrote a small function that I thought I could share to get this blog going again. It&#8217;s a small snippet that takes an address and tries to geocode it (convert it to coordinates) using the Google Maps API.</p>
<pre class="brush: csharp; title: ;">
public class Coordinate
{
    public double Latitude { get; set; }
    public double Longitude { get; set; }

    public static Coordinate[] GeocodeAddress(string address)
    {
        List&lt;Coordinate&gt; coordinates = new List&lt;Coordinate&gt;();

        string response = new WebClient().DownloadString(string.Format(&quot;http://maps.googleapis.com/maps/api/geocode/xml?address={0}&amp;sensor=false&quot;, HttpUtility.UrlEncode(address)));

        XmlDocument xmlDoc = new XmlDocument();
        xmlDoc.LoadXml(response);

        string status = xmlDoc.DocumentElement.SelectSingleNode(&quot;status&quot;).InnerText;

        switch (status.ToLowerInvariant())
        {
            case &quot;ok&quot;:
                // Everything went just fine
                break;
            case &quot;zero_results&quot;:
                return coordinates.ToArray();
            case &quot;over_query_limit&quot;:
            case &quot;invalid_request&quot;:
            case &quot;request_denied&quot;:
                throw new Exception(&quot;An error occured when contacting the Google Maps API.&quot;); // Should probably be refined to something more useful like throwing specific exceptions for each error
        }

        XmlNodeList nodeCol = xmlDoc.DocumentElement.SelectNodes(&quot;result&quot;);
        foreach (XmlNode node in nodeCol)
        {
            double lat = Convert.ToDouble(node.SelectSingleNode(&quot;geometry/location/lat&quot;).InnerText, CultureInfo.InvariantCulture);
            double lng = Convert.ToDouble(node.SelectSingleNode(&quot;geometry/location/lng&quot;).InnerText, CultureInfo.InvariantCulture);

            Coordinate wgs84 = new Coordinate() { Latitude = lat, Longitude = lng };
            coordinates.Add(wgs84);
        }

        return coordinates.ToArray();
    }
}
</pre>
<p>For more info on the Google Maps Geocoding API you can visit <a href="http://code.google.com/apis/maps/documentation/geocoding/" title="Visit the Google Maps Geocoding API">http://code.google.com/apis/maps/documentation/geocoding/</a>.</p>
<p>I&#8217;ve been working heavly with Google Maps and transforming coordinates at work this summer and when I get the time I&#8217;m going to make a nice package of the things I&#8217;ve created. I have a few helper functions in .Net for transforming between grid-based coordinates (X, Y) and geodesic coordinates (latitude, longitude) using the GaussKruger-formula as well as some snippets for Google Maps to handle large amounts of markers on a map (by hiding markers outside of the viewport) and some basic layer support for the markers.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.crazybeavers.se/index.php/archive/geocoding-with-google-maps-api/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<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>Drag &#8216;n Drop with Google Gears</title>
		<link>http://blog.crazybeavers.se/index.php/archive/drag-n-drop-with-google-gears/</link>
		<comments>http://blog.crazybeavers.se/index.php/archive/drag-n-drop-with-google-gears/#comments</comments>
		<pubDate>Wed, 23 Sep 2009 19:24:04 +0000</pubDate>
		<dc:creator>Karl</dc:creator>
				<category><![CDATA[Code samples]]></category>
		<category><![CDATA[jquery]]></category>
		<category><![CDATA[google gears]]></category>
		<category><![CDATA[javascript]]></category>

		<guid isPermaLink="false">http://blog.crazybeavers.se/?p=121</guid>
		<description><![CDATA[A lot of people saw the cool drag &#8216;n drop features on the Google Wave demonstration a few weeks ago and started wondering how to create that stuff yourselves. Being in the middle of my work on Imager Gallery.Net I was really excited about it and started looking at it. There are a few samples [...]]]></description>
			<content:encoded><![CDATA[<p>A lot of people saw the cool drag &#8216;n drop features on the Google Wave demonstration a few weeks ago and started wondering how to create that stuff yourselves. Being in the middle of my work on Imager Gallery.Net I was really excited about it and started looking at it. There are a few samples out there but some doesn&#8217;t work and one was even obfuscated. I&#8217;ve assembled the following sample which just takes the dropped file and shows a thumbnail (if an image, a generic icon else) of it. Later on it will be extended to upload files aswell and if successful also rewritten as a jQuery plugin. The current sample works with IE and Firefox with Google Gears 0.5.32 installed.</p>
<p><a href="http://blog.crazybeavers.se/wp-content/demos/Google.Gears/drop.html" title="Google Gears Drag 'n Drop sample">http://blog.crazybeavers.se/wp-content/demos/Google.Gears/drop.html</a></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.crazybeavers.se/index.php/archive/drag-n-drop-with-google-gears/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Reading EXIF with extension methods</title>
		<link>http://blog.crazybeavers.se/index.php/archive/reading-exif-with-extension-methods/</link>
		<comments>http://blog.crazybeavers.se/index.php/archive/reading-exif-with-extension-methods/#comments</comments>
		<pubDate>Thu, 20 Aug 2009 12:44:49 +0000</pubDate>
		<dc:creator>Karl</dc:creator>
				<category><![CDATA[.Net]]></category>
		<category><![CDATA[c#]]></category>
		<category><![CDATA[Code samples]]></category>
		<category><![CDATA[exif]]></category>
		<category><![CDATA[extensionmethods]]></category>
		<category><![CDATA[imagergallery]]></category>
		<category><![CDATA[sample]]></category>

		<guid isPermaLink="false">http://blog.crazybeavers.se/?p=110</guid>
		<description><![CDATA[I&#8217;m still putting quite a lot of work into Imager Gallery.Net. I have a alpha up an running at www.kallesbildarkiv.se though it still lacks quite a lot of features. Keeping my earlier commitment to release interesting code created for the project I can now present you with my next piece of code. I&#8217;ve had problems [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;m still putting quite a lot of work into Imager Gallery.Net. I have a alpha up an running at <a href="http://www.kallesbildarkiv.se/" title="Visit www.kallesbildarkiv.se">www.kallesbildarkiv.se</a> though it still lacks quite a lot of features.</p>
<p>Keeping my earlier commitment to release interesting code created for the project I can now present you with my next piece of code. I&#8217;ve had problems with finding a good class to read EXIF-information from images that isn&#8217;t written in VB.Net, really poorly written or licensed under GPL so I decided I had to write my own. After looking into the subject I found that it would be quite easy to implement this as extension methods on the regular Image class. I&#8217;ve decided to release the code under the Creative Commons Attribution-Share Alike license to allow people to use it anywhere as long as they can admit that they are using it.</p>
<pre class="brush: csharp; title: ;">
/*
 * Creative Commons Attribution-Share Alike 3.0 Unported
 * You are free:
 *   to Share — to copy, distribute and transmit the work
 *   to Remix — to adapt the work
 *
 * Under the following conditions:
 *   Attribution — You must attribute the work in the manner
 *   specified by the author or licensor (but not in any way
 *   that suggests that they endorse you or your use of the work).
 *
 *   Share Alike — If you alter, transform, or build upon this work,
 *   you may distribute the resulting work only under the same, similar
 *   or a compatible license.
 *
 * For more information, see http://creativecommons.org/licenses/by-sa/3.0/
 */
using System;
using System.Collections.Generic;
using System.Drawing.Imaging;
using System.Text;
using System.Drawing;

/*
 * This class is completely based on the documentation
 * of the EXIF format found here: http://www.exif.org/Exif2-2.PDF
 */

namespace CrazyBeavers.Extensions
{
    public static partial class ImageExtensions
    {
        #region Enumerations
        #pragma warning disable 1591

        private enum PropertyType
        {
            ByteArray = 1,
            AsciiString = 2,
            UnsignedShort = 3,
            UnsignedLong = 4,
            UnsignedLongPair = 5,
            Any = 6,
            SignedLongArray = 7,
            UnsignedLongPairArray = 10
        }

        public enum PropertyTag
        {
            ImageWidth = 0x100,
            ImageLength = 0x101,
            NBitsPerSample = 0x102,
            Compression = 0x103,
            PhotometricInterpretation = 0x106,
            Orientation = 0x112,
            SamplesPerPixel = 0x115,
            PlanarConfiguration = 0x11C,
            YCbCrSubSampling = 0x212,
            YCbCrPositioning = 0x213,
            XResolution = 0x11A,
            YResolution = 0x11B,
            ResolutionUnit = 0x128,
            StripOffsets = 0x111,
            RowsPerStrip = 0x116,
            StripByteCounts = 0x117,
            JPEGInterchangeFormat = 0x201,
            JPEGInterchangeFormatLength = 0x202,
            TransferFunction = 0x12D,
            WhitePoint = 0x13E,
            PrimaryChromaticities = 0x13F,
            YCbCrCoefficients = 0x211,
            ReferenceBlackWhite = 0x214,
            DateTime = 0x132,
            ImageDescription = 0x10E,
            Make = 0x10F,
            Model = 0x110,
            Software = 0x131,
            Artist = 0x13B,
            Copyright = 0x8298,
            ExifVersion = 0x9000,
            FlashpixVersion = 0xA000,
            ColorSpace = 0xA001,
            ComponentsConfiguration = 0x9101,
            CompressedBitsPerPixel = 0x9102,
            PixelXDimension = 0xA002,
            PixelYDimension = 0xA003,
            MakerNote = 0x927C,
            UserComment = 0x9286,
            RelatedSoundFile = 0xA004,
            DateTimeOriginal = 0x9003,
            DateTimeDigitized = 0x9004,
            SubSecTime = 0x9290,
            SubSecTimeOriginal = 0x9291,
            SubSecTimeDigitized = 0x9292,
            ImageUniqueID = 0xA420,
            ExposureTime = 0x829A,
            FNumber = 0x829D,
            ExposureProgram = 0x8822,
            SpectralSensitivity = 0x8824,
            ISOSpeedRatings = 0x8827,
            OECF = 0x8828,
            ShutterSpeedValue = 0x9201,
            ApertureValue = 0x9202,
            BrightnessValue = 0x9203,
            ExposureBiasValue = 0x9204,
            MaxApertureValue = 0x9205,
            SubjectDistance = 0x9206,
            MeteringMode = 0x9207,
            LightSource = 0x9208,
            Flash = 0x9209,
            FocalLength = 0x920A,
            SubjectArea = 0x9214,
            FlashEnergy = 0xA20B,
            SpatialFrequencyResponse = 0xA20C,
            FocalPlaneXResolution = 0xA20E,
            FocalPlaneYResolution = 0xA20F,
            FocalPlaneResolutionUnit = 0xA210,
            SubjectLocation = 0xA214,
            ExposureIndex = 0xA215,
            SensingMethod = 0xA217,
            FileSource = 0xA300,
            SceneType = 0xA301,
            CFAPattern = 0xA302,
            CustomRendered = 0xA401,
            ExposureMode = 0xA402,
            WhiteBalance = 0xA403,
            DigitalZoomRatio = 0xA404,
            FocalLengthIn35mmFilm = 0xA405,
            SceneCaptureType = 0xA406,
            GainControl = 0xA407,
            Contrast = 0xA408,
            Saturation = 0xA409,
            Sharpness = 0xA40A,
            DeviceSettingDescription = 0xA40B,
            SubjectDistanceRange = 0xA40C
        }

        public enum Compression
        {
            NotSpecified = 0,
            Uncompressed = 1,
            JpegCompression = 6
        }

        public enum PhotometricInterpretation
        {
            RGB = 2,
            YCbCr = 6
        }

        public enum Orientation
        {
            TopLeft = 1,
            TopRight = 2,
            BottomRight = 3,
            BottomLeft = 4,
            LeftTop = 5,
            RightTop = 6,
            RightBottom = 7,
            LeftBottom = 8
        }

        public enum ExposureMode
        {
            AutoExposure = 0,
            ManualExposure = 1,
            AutoBracket = 2
        }

        public enum ExposureProgram
        {
            Undefined = 0,
            Manual = 1,
            Normal = 2,
            AperturePriority = 3,
            ShutterPriority = 4,
            CreativeProgram = 5,
            ActionProgram = 6,
            PortraitMode = 7,
            LandscapeMode = 8
        }

        public enum MeteringMode
        {
            Unknown = 0,
            Average = 1,
            CenterWeightedAverage = 2,
            Spot = 3,
            MultiSpot = 4,
            Pattern = 5,
            Partial = 6,
            Other = 255
        }

        public enum Flash
        {
            FlashDidNotFire = 0x0000,
            FlashFired = 0x0001,
            StrobeReturnNotDetected = 0x0005,
            StrobeReturnDetected = 0x0007,
            FlashFiredCompulsoryMode = 0x0009,
            FlashFiredCompulsoryModeStrobeReturnNotDetected = 0x000D,
            FlashFiredCompulsoryModeStrobeReturnDetected = 0x000F,
            FlashDidNotFireCompulsoryMode = 0x0010,
            FlashDidNotFireAutoMode = 0x0018,
            FlashFiredAutoMode = 0x00019,
            FlashFiredAutoModeStrobeReturnNotDetected = 0x001D,
            FlashFiredAutoModeStrobeReturnDetected = 0x001F,
            NoFlash = 0x0020,
            FlashFiredRedEyeReduction = 0x0041,
            FlashFiredRedEyeReductionStrobeReturnNotDetected = 0x0045,
            FlashFiredRedEyeReductionStrobeReturnDetected = 0x0047,
            FlashFiredCompulsoryModeRedEyeReduction = 0x0049,
            FlashFiredCompulsoryModeRedEyeReductionStrobeReturnNotDetected = 0x004D,
            FlashFiredCompulsoryModeRedEyeReductionStrobeReturnDetected = 0x004F,
            FlashFiredAutoModeRedEyeReduction = 0x0059,
            FlashFiredAutoModeRedEyeReductionStrobeReturnNotDetected = 0x005D,
            FlashFiredAutoModeRedEyeReductionStrobeReturnDetected = 0x005F
        }

        public enum WhiteBalance
        {
            Auto = 0,
            Manual = 1
        }

        public enum SceneCaptureType
        {
            Standard = 0,
            Landscape = 1,
            Portrait = 2,
            NightScene = 3
        }

        public enum LightSource
        {
            Unkown = 0,
            Daylight = 1,
            Fluorescent = 2,
            Tungsten = 3,
            Flash = 4,
            FineWeather = 9,
            CloudyWeather = 10,
            Shade = 11,
            DaylightFluorescent = 12,
            DayWhiteFluorescent = 13,
            CoolWhiteFluorescent = 14,
            WhiteFluorescent = 15,
            StandardLightA = 17,
            StandardLightB = 18,
            StandardLightC = 19,
            D55 = 20,
            D65 = 21,
            D75 = 22,
            D50 = 23,
            ISOStudioTungsten = 24,
            OtherLightSource = 255
        }

        public enum GainControl
        {
            None = 0,
            LowGainUp = 1,
            HighGainUp = 2,
            LowGainDown = 3,
            HighGainDown = 4
        }

        public enum Contrast
        {
            Normal = 0,
            Soft = 1,
            Hard = 2
        }

        public enum Saturation
        {
            Normal = 0,
            LowSaturation = 1,
            HighSaturation = 2
        }

        public enum Sharpness
        {
            Normal = 0,
            Soft = 1,
            Hard = 2
        }

        public enum SubjectDistanceRange
        {
            Unknown = 0,
            Macro = 1,
            CloseView = 2,
            DistantView = 3
        }

        #pragma warning restore 1591
        #endregion

        #region Properties

        public static DateTime ExifDateTime(this Image image)
        {
            return GetPropertyDateTime(image, PropertyTag.DateTime);
        }

        public static DateTime ExifDateTimeDigitized(this Image image)
        {
            return GetPropertyDateTime(image, PropertyTag.DateTimeDigitized);
        }

        public static DateTime ExifDateTimeOriginal(this Image image)
        {
            return GetPropertyDateTime(image, PropertyTag.DateTimeOriginal);
        }

        public static string ExifMake(this Image image)
        {
            return GetPropertyString(image, PropertyTag.Make);
        }

        public static string ExifModel(this Image image)
        {
            return GetPropertyString(image, PropertyTag.Model);
        }

        public static string ExifImageDescription(this Image image)
        {
            return GetPropertyString(image, PropertyTag.ImageDescription);
        }

        public static string ExifSoftware(this Image image)
        {
            return GetPropertyString(image, PropertyTag.Software);
        }

        public static string ExifArtist(this Image image)
        {
            return GetPropertyString(image, PropertyTag.Artist);
        }

        public static Orientation ExifOrientation(this Image image)
        {
            return (Orientation)GetPropertyUInt16(image, PropertyTag.Orientation);
        }

        public static Flash ExifFlash(this Image image)
        {
            return (Flash)GetPropertyUInt16(image, PropertyTag.Flash);
        }

        public static SceneCaptureType ExifSceneCaptureType(this Image image)
        {
            return (SceneCaptureType)GetPropertyUInt16(image, PropertyTag.SceneCaptureType);
        }

        public static WhiteBalance ExifWhiteBalance(this Image image)
        {
            return (WhiteBalance)GetPropertyUInt16(image, PropertyTag.WhiteBalance);
        }

        public static MeteringMode ExifMeteringMode(this Image image)
        {
            return (MeteringMode)GetPropertyUInt16(image, PropertyTag.MeteringMode);
        }

        public static Compression ExifCompression(this Image image)
        {
            return (Compression)GetPropertyUInt16(image, PropertyTag.Compression);
        }

        public static ExposureMode ExifExposureMode(this Image image)
        {
            return (ExposureMode)GetPropertyUInt16(image, PropertyTag.ExposureMode);
        }

        public static ExposureProgram ExifExposureProgram(this Image image)
        {
            return (ExposureProgram)GetPropertyUInt16(image, PropertyTag.ExposureProgram);
        }

        public static PhotometricInterpretation ExifPhotometricInterpretation(this Image image)
        {
            return (PhotometricInterpretation)GetPropertyUInt16(image, PropertyTag.PhotometricInterpretation);
        }

        public static LightSource ExifLightSource(this Image image)
        {
            return (LightSource)GetPropertyUInt16(image, PropertyTag.LightSource);
        }

        public static GainControl ExifGainControl(this Image image)
        {
            return (GainControl)GetPropertyUInt16(image, PropertyTag.GainControl);
        }

        public static Contrast ExifLightContrast(this Image image)
        {
            return (Contrast)GetPropertyUInt16(image, PropertyTag.Contrast);
        }

        public static Saturation ExifSaturation(this Image image)
        {
            return (Saturation)GetPropertyUInt16(image, PropertyTag.Saturation);
        }

        public static Sharpness ExifSharpness(this Image image)
        {
            return (Sharpness)GetPropertyUInt16(image, PropertyTag.Sharpness);
        }

        public static SubjectDistanceRange ExifSubjectDistanceRange(this Image image)
        {
            return (SubjectDistanceRange)GetPropertyUInt16(image, PropertyTag.SubjectDistanceRange);
        }

        public static Rational ExifExposureTime(this Image image)
        {
            return GetPropertyRational(image, PropertyTag.ExposureTime);
        }

        public static double ExifFNumber(this Image image)
        {
            return GetPropertyRational(image, PropertyTag.FNumber).ToDouble();
        }

        public static double ExifAperture(this Image image)
        {
            return GetPropertyRational(image, PropertyTag.ApertureValue).ToDouble();
        }

        public static Rational ExifSubjectDistance(this Image image)
        {
            return GetPropertyRational(image, PropertyTag.SubjectDistance);
        }

        public static double ExifFocalLength(this Image image)
        {
            return GetPropertyRational(image, PropertyTag.FocalLength).ToDouble();
        }

        public static UInt16 ExifISOSpeedRating(this Image image)
        {
            return GetPropertyUInt16(image, PropertyTag.ISOSpeedRatings);
        }

        public static Rational ExifDigitalZoomRatio(this Image image)
        {
            return GetPropertyRational(image, PropertyTag.DigitalZoomRatio);
        }

        #endregion

        public static bool HasProperty(this Image image, PropertyTag property)
        {
            return Array.IndexOf(image.PropertyIdList, (Int32)property) &gt; -1;
        }

        public static DateTime GetPropertyDateTime(this Image image, PropertyTag property)
        {
            if (!image.HasProperty(property))
                return DateTime.MinValue;

            string value = GetPropertyString(image, property);

            // If first char is blank or string is empty no DateTime is present
            if (value == string.Empty || value[0] == ' ')
                return DateTime.MinValue;

            // DateTime is written as YYYY:MM:DD HH:MM:SS
            // and needs to be converted to YYYY-MM-DD HH:MM:SS
            // to be convertable to a .Net DateTime
            string datePart = value.Substring(0, 10).Replace(':', '-');
            string timePart = value.Substring(11);
            return Convert.ToDateTime(datePart + ' ' + timePart);
        }

        public static string GetPropertyString(this Image image, PropertyTag property)
        {
            if (!image.HasProperty(property))
                return string.Empty;

            PropertyItem item = image.GetPropertyItem((Int32)property);
            if (item.Type != (short)PropertyType.AsciiString)
                return string.Empty;

            byte[] buffer = item.Value;
            return Encoding.ASCII.GetString(buffer).Trim('&#92;&#48;');
        }

        public static UInt32 GetPropertyUInt32(this Image image, PropertyTag property)
        {
            if (!image.HasProperty(property))
                return 0;

            PropertyItem item = image.GetPropertyItem((Int32)property);
            if (item.Type != (short)PropertyType.UnsignedLong)
                return 0;

            byte[] buffer = item.Value;
            return BitConverter.ToUInt32(buffer, 0);
        }

        public static UInt16 GetPropertyUInt16(this Image image, PropertyTag property)
        {
            if (!image.HasProperty(property))
                return 0;

            PropertyItem item = image.GetPropertyItem((Int32)property);
            if (item.Type != (short)PropertyType.UnsignedShort)
                return 0;

            byte[] buffer = item.Value;
            return BitConverter.ToUInt16(buffer, 0);
        }

        public static Rational GetPropertyRational(this Image image, PropertyTag property)
        {
            if (!image.HasProperty(property))
                return Rational.Zero;

            PropertyItem item = image.GetPropertyItem((Int32)property);
            if (item.Type != (short)PropertyType.UnsignedLongPair)
                return Rational.Zero;

            byte[] buffer = item.Value;
            Int32 numerator = BitConverter.ToInt32(buffer, 0);
            Int32 denominator = BitConverter.ToInt32(buffer, 4);

            Rational rational = new Rational(numerator, denominator);
            return rational;
        }
    }

    public struct Rational
    {
        private Int32 _numerator;
        public Int32 Numerator
        {
            get
            {
                return _numerator;
            }
            set
            {
                _numerator = value;
            }
        }

        private Int32 _denominator;
        public Int32 Denominator
        {
            get
            {
                return _denominator;
            }
            set
            {
                if (value == 0)
                    throw new ArgumentOutOfRangeException(&quot;Denominator&quot;, 0, &quot;Denominator can't be zero.&quot;);

                _denominator = value;
            }
        }

        public static Rational Zero
        {
            get
            {
                return new Rational(0, 1);
            }
        }

        public Rational(Int32 numerator, Int32 denominator)
        {
            _numerator = 0;
            _denominator = 1;
            Numerator = numerator;
            Denominator = denominator;
        }

        public override string ToString()
        {
            return string.Format(&quot;{0}/{1}&quot;, Numerator, Denominator);
        }

        public double ToDouble()
        {
            return (double)Numerator / Denominator;
        }
    }
}
</pre>
<p>This introduces several new methods to the Image class starting with &#8220;Exif&#8221; such as ExifDateTime, ExifMake and ExifExposureTime. The Rational class was inserted into the same code block in this sample, in the main project it has it&#8217;s own file under CrazyBeavers.Math. Hope you enjoy this piece of code!</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.crazybeavers.se/index.php/archive/reading-exif-with-extension-methods/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>jQuery Tag Editor</title>
		<link>http://blog.crazybeavers.se/index.php/archive/jquery-tag-editor/</link>
		<comments>http://blog.crazybeavers.se/index.php/archive/jquery-tag-editor/#comments</comments>
		<pubDate>Mon, 06 Jul 2009 12:39:24 +0000</pubDate>
		<dc:creator>Karl</dc:creator>
				<category><![CDATA[Code samples]]></category>
		<category><![CDATA[imagergallery]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[jquery]]></category>

		<guid isPermaLink="false">http://blog.crazybeavers.se/?p=102</guid>
		<description><![CDATA[Something I really like with WordPress is the really nice tag editor. It works so smooth and looks way better then just having a textbox with comma-separated list of tags so for ImagerGallery.Net I decided to write one of my own. I&#8217;ve put up a demo of it for now for those interested, it&#8217;s available [...]]]></description>
			<content:encoded><![CDATA[<p>Something I really like with WordPress is the really nice tag editor. It works so smooth and looks way better then just having a textbox with comma-separated list of tags so for ImagerGallery.Net I decided to write one of my own. I&#8217;ve put up a demo of it for now for those interested, it&#8217;s available at the following url:</p>
<p><a href="http://blog.crazybeavers.se/wp-content/demos/jquery.tag.editor/">http://blog.crazybeavers.se/wp-content/demos/jquery.tag.editor/</a></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.crazybeavers.se/index.php/archive/jquery-tag-editor/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>RFC2047 decoder in C#</title>
		<link>http://blog.crazybeavers.se/index.php/archive/rfc2047decoder-in-c-sharp/</link>
		<comments>http://blog.crazybeavers.se/index.php/archive/rfc2047decoder-in-c-sharp/#comments</comments>
		<pubDate>Wed, 17 Jun 2009 20:26:46 +0000</pubDate>
		<dc:creator>Karl</dc:creator>
				<category><![CDATA[.Net]]></category>
		<category><![CDATA[c#]]></category>
		<category><![CDATA[Code samples]]></category>
		<category><![CDATA[RFC2047]]></category>
		<category><![CDATA[sample]]></category>
		<category><![CDATA[sourcecode]]></category>

		<guid isPermaLink="false">http://blog.crazybeavers.se/?p=91</guid>
		<description><![CDATA[Just spent the evening writing a class to decode RFC2047 strings in C#. It was requested by a user on ASPSidan, a Swedish site dedicated to ASP, ASP.Net and other Microsoft technologies but before I was done someone had already found another implementation on the net. Anyway, the code shouldn&#8217;t go to waste so I&#8217;m [...]]]></description>
			<content:encoded><![CDATA[<p>Just spent the evening writing a class to decode <a href="http://www.faqs.org/rfcs/rfc2047">RFC2047</a> strings in C#. It was requested by a user on ASPSidan, a Swedish site dedicated to ASP, ASP.Net and other Microsoft technologies but before I was done someone had already found another implementation on the net. Anyway, the code shouldn&#8217;t go to waste so I&#8217;m posting it here if anyone needs it.</p>
<pre class="brush: csharp; title: ;">
using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Globalization;

namespace CrazyBeavers.Net.Mail
{
    public static class RFC2047Decoder
    {
        public static string Parse(string input)
        {
            StringBuilder sb = new StringBuilder();
            StringBuilder currentWord = new StringBuilder();
            bool readingWord = false;

            Int32 i = 0;
            while (i &lt; input.Length)
            {
                char currentChar = input[i];
                char peekAhead;
                switch (currentChar)
                {
                    case '=':
                        peekAhead = (i == input.Length - 1) ? ' ' : input[i + 1];

                        if (peekAhead == '?')
                            readingWord = true;
                        break;

                    case '?':
                        peekAhead = (i == input.Length - 1) ? ' ' : input[i + 1];

                        if (peekAhead == '=')
                        {
                            readingWord = false;

                            currentWord.Append(currentChar);
                            currentWord.Append(peekAhead);

                            sb.Append(ParseEncodedWord(currentWord.ToString()));
                            currentWord = new StringBuilder();

                            i += 2;
                            continue;
                        }
                        break;
                }

                if (readingWord)
                {
                    currentWord.Append(currentChar);
                    i++;
                }
                else
                {
                    sb.Append(currentChar);
                    i++;
                }
            }

            return sb.ToString();
        }

        private static string ParseEncodedWord(string input)
        {
            StringBuilder sb = new StringBuilder();

            if (!input.StartsWith(&quot;=?&quot;))
                return input;

            if (!input.EndsWith(&quot;?=&quot;))
                return input;

            // Get the name of the encoding but skip the leading =?
            string encodingName = input.Substring(2, input.IndexOf(&quot;?&quot;, 2) - 2);
            Encoding enc = Encoding.GetEncoding(encodingName);

            // Get the type of the encoding
            char type = input[encodingName.Length + 3];

            // Start after the name of the encoding and the other required parts
            Int32 i = encodingName.Length + 5;

            switch (char.ToLowerInvariant(type))
            {
                case 'q':
                    while (i &lt; input.Length)
                    {
                        char currentChar = input[i];
                        char[] peekAhead = new char[2];
                        switch (currentChar)
                        {
                            case '=':
                                peekAhead = (i &gt;= input.Length - 2) ? null : new char[] { input[i + 1], input[i + 2] };

                                if (peekAhead == null)
                                {
                                    sb.Append(currentChar);
                                    i++;
                                    break;
                                }

                                string decodedChar = enc.GetString(new byte[] { Convert.ToByte(new string(peekAhead, 0, 2), 16) });
                                sb.Append(decodedChar);
                                i += 3;
                                break;
                            case '?':
                                if (input[i + 1] == '=')
                                    i += 2;
                                break;
                            default:
                                sb.Append(currentChar);
                                i++;
                                break;
                        }
                    }
                    break;
                case 'b':
                    string baseString = input.Substring(i, input.Length - i - 2);
                    byte[] baseDecoded = Convert.FromBase64String(baseString);
                    sb.Append(enc.GetString(baseDecoded));
                    break;
            }
            return sb.ToString();
        }
    }
}
</pre>
]]></content:encoded>
			<wfw:commentRss>http://blog.crazybeavers.se/index.php/archive/rfc2047decoder-in-c-sharp/feed/</wfw:commentRss>
		<slash:comments>2</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>For each (FOR IN) dropped file in batchfile</title>
		<link>http://blog.crazybeavers.se/index.php/archive/for-each-for-in-dropped-file-in-batchfile/</link>
		<comments>http://blog.crazybeavers.se/index.php/archive/for-each-for-in-dropped-file-in-batchfile/#comments</comments>
		<pubDate>Wed, 20 May 2009 05:22:57 +0000</pubDate>
		<dc:creator>Karl</dc:creator>
				<category><![CDATA[Code samples]]></category>
		<category><![CDATA[Misc]]></category>
		<category><![CDATA[batchfiles]]></category>
		<category><![CDATA[ffmpeg]]></category>
		<category><![CDATA[scripting]]></category>

		<guid isPermaLink="false">http://blog.crazybeavers.se/?p=72</guid>
		<description><![CDATA[I&#8217;m a huge fan of batchfiles (.bat) in Windows. They are usually so simple to write and can help you out with automating tasks that otherwise would be a pain in your ass. As an example, here is a little file I&#8217;ve set up at work for my coworkers to be able to convert movieclips [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;m a huge fan of batchfiles (.bat) in Windows. They are usually so simple to write and can help you out with automating tasks that otherwise would be a pain in your ass. As an example, here is a little file I&#8217;ve set up at work for my coworkers to be able to convert movieclips to .wmv.</p>
<pre class="brush: plain; title: ;">
@echo off
&quot;J:\PathToOurMovieArchive\ffmpeg.exe&quot; -i %1 -b 1024k -vcodec wmv2 -acodec wmav2 -ar 44100 -ab 48000 -ac 1 -y %1-convertedHQ.wmv
pause
</pre>
<p>It&#8217;s simple enough. Don&#8217;t output anything and then execute ffmpeg,exe with the specified parameters taking the first of the dropped files as input. Works great and produces a wmv-movieclip in the same folder as the original file. The problem with this file is that it if you drop two files on this batch it will only convert the first one, which forces you to drag them one by one and then have them run simultaneously which might not be desirable on a slow computer.</p>
<p>To solve this problem I went to the all mighty <a href="http://www.google.com/" title="Visit Google">Google</a> and found the FOR IN command. My problem was that it I couldn&#8217;t find any samples with it working with dropped files and I couldn&#8217;t get it working by just doing FOR %i in (%*). The problem (according to the help for the FOR-command availabile in FOR /?) was that if used in a batchfile I need to designate my variable as %%i instead of %i. After changing that it all worked like charm. So this is how my batchfile ended up, it supports any number of dropped files (well I guess it has a built in limit such as 65335 or something though I&#8217;m pretty sure my coworkers won&#8217;t drop more then 10 files) and then executes each file in order and not all at once.</p>
<pre class="brush: plain; title: ;">
@echo off
for %%i in (%*) do &quot;J:\PathToOurMovieArchive\ffmpeg.exe&quot; -i %%i -b 1024k -vcodec wmv2 -acodec wmav2 -ar 44100 -ab 48000 -ac 1 -y %%i-convertedHQ.wmv
pause
</pre>
<p>I hope that this was to some help for somebody. If you have any other good tips on scripting with batchfiles then please add a comment about it as I&#8217;m always eager to learn new things with this great technique.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.crazybeavers.se/index.php/archive/for-each-for-in-dropped-file-in-batchfile/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Recursive generic extensionmethods are fun! (Recursive FindControl)</title>
		<link>http://blog.crazybeavers.se/index.php/archive/recursive-generic-extensionmethods-are-fun/</link>
		<comments>http://blog.crazybeavers.se/index.php/archive/recursive-generic-extensionmethods-are-fun/#comments</comments>
		<pubDate>Wed, 12 Nov 2008 21:39:16 +0000</pubDate>
		<dc:creator>Karl</dc:creator>
				<category><![CDATA[.Net]]></category>
		<category><![CDATA[c#]]></category>
		<category><![CDATA[Code samples]]></category>
		<category><![CDATA[asp.net]]></category>
		<category><![CDATA[extensionmethods]]></category>
		<category><![CDATA[findcontrol]]></category>
		<category><![CDATA[genererics]]></category>
		<category><![CDATA[recursive]]></category>

		<guid isPermaLink="false">http://www.beaverblogg.com/index.php/archive/recursive-generic-extensionmethods-are-fun/</guid>
		<description><![CDATA[Just thought I should share a little piece of code with you this evening. It&#8217;s a little extension method (i.e it requires .Net 3.5) that extends Control and helps you find all instances of a certain controltype under the Control on which you invoke the method. Just put the following code in an assembly (or [...]]]></description>
			<content:encoded><![CDATA[<p>Just thought I should share a little piece of code with you this evening. It&#8217;s a little extension method (i.e it requires .Net 3.5) that extends Control and helps you find all instances of a certain controltype under the Control on which you invoke the method. Just put the following code in an assembly (or a .cs-file in App_Code).</p>
<pre class="brush: csharp; title: ;">
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;

/// &lt;summary&gt;
/// Holderclass for extension methods
/// &lt;/summary&gt;
public static class ExtensionMethods
{
    /// &lt;summary&gt;
    /// Recursively searchs for all instances of a specified control type.
    /// &lt;/summary&gt;
    /// &lt;typeparam name=&quot;T&quot;&gt;The type of control to search for.&lt;/typeparam&gt;
    /// &lt;param name=&quot;control&quot;&gt;The control to search from.&lt;/param&gt;
    /// &lt;returns&gt;A List&lt;&gt; with the found controls.&lt;/returns&gt;
    public static List&lt;T&gt; FindControls&lt;T&gt;(this Control control) where T : Control
    {
        List&lt;T&gt; myList = new List&lt;t&gt;();
        FindControls&lt;/t&gt;&lt;t&gt;(control, ref myList);
        return myList;
    }

    private static void FindControls&lt;T&gt;(Control control, ref List&lt;T&gt; controlList) where T : Control
    {
        for (int i = 0; i &lt; control.Controls.Count; i++)
        {
            Control currentControl = control.Controls[i];
            if (currentControl is T)
            {
                T typedControl = control.Controls[i] as T;
                controlList.Add(typedControl);
            }

            FindControls&lt;T&gt;(currentControl, ref controlList);
        }

    }
}
</pre>
<p>To call it you just invoke FindControls&lt;Control&gt;() on any object that derives from Control (i.e. Page, Label, Calendar, the list can go on forever), see the sample below. Hope you find some use for it!</p>
<pre class="brush: csharp; title: ;">
List&lt;HtmlMeta&gt; meta = Page.FindControls&lt;HtmlMeta&gt;();
</pre>
]]></content:encoded>
			<wfw:commentRss>http://blog.crazybeavers.se/index.php/archive/recursive-generic-extensionmethods-are-fun/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Uploading multiple files and form fields in .Net</title>
		<link>http://blog.crazybeavers.se/index.php/archive/uploading-multiple-files-and-form-fields-in-net/</link>
		<comments>http://blog.crazybeavers.se/index.php/archive/uploading-multiple-files-and-form-fields-in-net/#comments</comments>
		<pubDate>Wed, 23 Jan 2008 15:37:27 +0000</pubDate>
		<dc:creator>Karl</dc:creator>
				<category><![CDATA[.Net]]></category>
		<category><![CDATA[c#]]></category>
		<category><![CDATA[Code samples]]></category>
		<category><![CDATA[fileupload]]></category>
		<category><![CDATA[form]]></category>
		<category><![CDATA[formfields]]></category>
		<category><![CDATA[httpupload]]></category>
		<category><![CDATA[mimetype]]></category>
		<category><![CDATA[upload]]></category>
		<category><![CDATA[webclient]]></category>

		<guid isPermaLink="false">http://www.beaverblogg.com/index.php/archive/uploading-multiple-files-and-form-fields-in-net/</guid>
		<description><![CDATA[Recently while building a small application for a friend of mine I came across a part where I needed something that I just couldn&#8217;t find in the .Net framework. I needed to upload two files (and specify their fieldnames) and a few form fields to a webpage. I thought this would be easy just using [...]]]></description>
			<content:encoded><![CDATA[<p>
  Recently while building a small application for a friend of mine I came across a part where I needed something that I just couldn&#8217;t find in the .Net framework. I needed to upload two files (and specify their fieldnames) and a few form fields to a webpage. I thought this would be easy just using the provided WebClient class but after looking closer at it I found that it didn&#8217;t really offer anything of what I needed. Trying not to feel let down by this I started to write my own extended version of WebClient with a few new tricks that the old one couldn&#8217;t do.
</p>
<p>
  I tried to keep it as simple as possible so instead of writing new classes to hold form and file data I used two Dictionary&lt;string, string&gt; to pass the values. The Key is the fieldname and the Value the value or the path to the file. An example of uploading a few files and adding a few fields to that could look like this:</p>
<pre class="brush: csharp; title: ;">Dictionary&lt;string, string&gt; FormFiles = new Dictionary&lt;string, string&gt;();

FormFiles.Add(&quot;mypet&quot;, &quot;C:\\cat.jpg&quot;);
FormFiles.Add(&quot;me&quot;, &quot;C:\\myself.jpg&quot;);

Dictionary&lt;string, string&gt; FormFields = new Dictionary&lt;string, string&gt;();

FormFields.Add(&quot;age&quot;, &quot;22&quot;);
FormFields.Add(&quot;location&quot;, &quot;Sweden&quot;);

WebClientEx WC = new WebClientEx();

try
{
    WC.UploadData(&quot;http://www.myserver.com/upload.aspx&quot;, FormFiles, FormFields);
}
catch(WebException E)
{
    System.Console.WriteLine(&quot;Upload failed with HTTP-Code&quot; + ((HttpWebResponse)E.Response).StatusCode.ToString());
    System.Console.ReadKey();
    return;
}</pre>
<p>
  It doesn&#8217;t look that hard does it? It&#8217;s perfect to use if you need to &#8220;submit&#8221; a form on a webpage from your c# application or just need to send several files to a webserver in the same request. Below is the complete code for WebClientEx displayed. You may use it for anything you want as long as you don&#8217;t claim it as your own. If you use it in a project of yours then please write a comment or send me an email about it!
</p>
<pre class="brush: csharp; title: ;">using System;
using System.Collections.Generic;
using System.Text;
using System.Net;
using System.IO;
using CrazyBeavers.Utils;

namespace CrazyBeavers.Net
{
    /// &lt;summary&gt;
    /// Provides common methods for sending data to and receiving data from a resource identified by a URI. This version comes with extended support for uploading files and formfields.
    /// &lt;/summary&gt;
    public class WebClientEx : WebClient
    {
        public byte[] UploadData(string Address, Dictionary&lt;string, string&gt; Files, Dictionary&lt;string, string&gt; Fields)
        {
            string Boundary = &quot;----------&quot; + DateTime.Now.Ticks.ToString(&quot;x&quot;);
            byte[] BoundaryEnd = Encoding.ASCII.GetBytes(&quot;\r\n--&quot; + Boundary + &quot;--&quot;);

            MemoryStream MS = new MemoryStream();
            byte[] Buffer;

            foreach (KeyValuePair&lt;string, string&gt; Field in Fields)
            {
                StringBuilder Header = new StringBuilder();
                Header.Append(&quot;\r\n&quot;);
                Header.Append(&quot;--&quot;);
                Header.Append(Boundary);
                Header.Append(&quot;\r\n&quot;);
                Header.Append(&quot;Content-Disposition: form-data; name=\&quot;&quot;);
                Header.Append(Field.Key);
                Header.Append(&quot;\&quot;&quot;);
                Header.Append(&quot;\r\n&quot;);
                Header.Append(&quot;\r\n&quot;);
                Header.Append(Field.Value);

                byte[] PostHeaderBytes = Encoding.UTF8.GetBytes(Header.ToString());

                MS.Write(PostHeaderBytes, 0, PostHeaderBytes.Length);
            }

            foreach (KeyValuePair&lt;string, string&gt; File in Files)
            {
                StringBuilder Header = new StringBuilder();
                Header.Append(&quot;\r\n&quot;);
                Header.Append(&quot;--&quot;);
                Header.Append(Boundary);
                Header.Append(&quot;\r\n&quot;);
                Header.Append(&quot;Content-Disposition: form-data; name=\&quot;&quot;);
                Header.Append(File.Key);
                Header.Append(&quot;\&quot;; filename=\&quot;&quot;);
                Header.Append(Path.GetFileName(File.Value));
                Header.Append(&quot;\&quot;&quot;);
                Header.Append(&quot;\r\n&quot;);
                Header.Append(&quot;Content-Type: &quot;);
                Header.Append(MimeHelper.GetMimeTypeForExtension(Path.GetExtension(File.Value)));
                Header.Append(&quot;\r\n&quot;);
                Header.Append(&quot;\r\n&quot;);

                byte[] PostHeaderBytes = Encoding.UTF8.GetBytes(Header.ToString());

                FileStream FS = new FileStream(File.Value, FileMode.Open, FileAccess.Read);

                MS.Write(PostHeaderBytes, 0, PostHeaderBytes.Length);

                Buffer = new Byte[checked((UInt32)Math.Min(4096, (Int32)FS.Length))];
                Int32 BytesRead = 0;
                while ((BytesRead = FS.Read(Buffer, 0, Buffer.Length)) != 0)
                    MS.Write(Buffer, 0, BytesRead);

                FS.Close();
            }

            MS.Write(BoundaryEnd, 0, BoundaryEnd.Length);
            MS.Position = 0;

            if (this.Headers[&quot;Content-Type&quot;] != null)
                this.Headers.Remove(&quot;Content-Type&quot;);

            this.Headers.Add(&quot;Content-Type&quot;, &quot;multipart/form-data; boundary=&quot; + Boundary);

            Buffer = new byte[MS.Length];
            MS.Read(Buffer, 0, (Int32)MS.Length);

            return this.UploadData(Address, &quot;POST&quot;, Buffer);
        }
    }
}</pre>
<p>
  I won&#8217;t go in explaining line of this code as I&#8217;ve done in a few other samples. The code isn&#8217;t that hard to understand if you have moved beyond the &#8220;beginner stage&#8221; of coding. The thing worth mentioning is the part with <em>MimeHelper.GetMimeTypeForExtension()</em> which is a small function I wrote which checks the registry for any available mimetype for a given extension. I&#8217;ve included that code below aswell since it&#8217;s needed for WebClientEx.
</p>
<pre class="brush: csharp; title: ;">using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using Microsoft.Win32;

namespace CrazyBeavers.Utils
{
    public static class MimeHelper
    {
        public static string GetMimeTypeForExtension(string FileExt)
        {
            if (!FileExt.StartsWith(&quot;.&quot;))
                FileExt = &quot;.&quot; + FileExt;

            string Mime = &quot;application/octet-stream&quot;;

            RegistryKey Classes = Registry.ClassesRoot;

            RegistryKey FileKey = Classes.OpenSubKey(FileExt);
            if (FileKey != null)
            {
                Mime = (string)FileKey.GetValue(&quot;Content Type&quot;, &quot;application/octet-stream&quot;);
                FileKey.Close();
            }
            Classes.Close();
            return Mime;
        }
    }
}</pre>
<p>Enjoy!</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.crazybeavers.se/index.php/archive/uploading-multiple-files-and-form-fields-in-net/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

