Pages

Sunday, September 23, 2012

Edypository has moved

This blog has moved, you are about to be redirected...



Hi guys,
I now have a new website located at http://www.edmundyeung.com
This website contains two separate blogs:

Why?
It was a good chance to use some exciting new technologies; My new website was built using Orchard and hosted on Windows Azure.

What will happen to this Blogger website?
Nothing. I'll leave this site as it is, its got enough visitors that I don't think Google is going to shut it down, so any existing links to this site should continue to work. But I do plan on migrating some of the content over to my new site. I haven't decided whether there will be a link or a redirect to the new page.

Monday, November 15, 2010

Snow Season 2010 Rookie Report

This year was my first year Snowboarding. Managed to get up the mountain 5 times, and Snowplanet twice.

I learnt some of the basic skills: falling leaf, stopping, linking turns. I even decided to buy my own set of gear: gloves, pants, jackets, helmet, goggles, boots, snowboard, bindings. Below I will make a few suggestions to anyone out there who wants to start snowboarding, and get their own gear.

Learn How To Snowboard


  1. First you want to be prepared and have appropriate gear. You don't need all the proper stuff, especially if you're not sure whether you'll be doing it again. I went in some sports track pants, a down jacket, and a beanie. I rented the board, boots and bindings, which is a pretty standard thing to do and fairly affordable ($45 on the mountain and $25 at the bottom). The one thing I did buy though, were the gloves. I bought a cheap pair for $20 will do. You just gotta make sure your stuff is water proof.

  2. The next thing to consider as you go up the mountain is a lesson, either from the instructors, or a nice friend.

  3. Now the first thing you gotta figure out is whether you are regular or goofy. I knew I was regular from my skateboarding days, but its up to you to experiment. The best way is to see which foot you lead with if you were to run and slide along the ground. If its your left foot, you're regular, if its your right, you're goofy.

  4. When you get on your board, you're gonna want to learn to travel around with one foot in the bindings. This is how snowboards get around the lifts and things.

  5. Then its time to learn the falling leaf, which involves balancing on the board and traveling down the mountain with the board perpendicular to the way you are traveling. Get practice on both heelside and toeside. When going down front first (and with your back to the top of the mountain), its called heelside as you lift your toes and balance on your heel. Toeside is when you balance facing up the mountain, balancing on your toes. As you get more confident, try leaning left and right to follow a "falling leaf" path.

  6. Now its time to learn to turn. The hardest thing I had to get used to here was leaning forward and keeping my weight on my front foot. I had the tendency (as many beginners do) to lean back which doesn't give you enough control. To turn from heelside to toe side, shift your weight forward and rotate around until your weight is on your toes. This should swing your board including your back foot such that you will now be facing the other way, going down the mountain toeside. To go from toe to heel, do the same but rotate the other way.

  7. After getting used to turning, try linking the turns from left to right to form an "S" path down the mountain.

  8. And thats it! well thats all I learnt. Next season I'll be practicing my switching, and traversing the mountain fakie. I also want to learn ollies and rails.

Buying gear


  • Snowboarding gear can be expensive, especially the latest gear. With everything combined, and the cost of travel/accommodation, snowboard can be expensive.

  • If you want to get everything, expect to pay some $1000+ for new gear. Thats assuming $600 on board, boots, bindings, and the rest on clothes. Thats very good new gear, but last seasons, or on discount pricing. Expect to pay double that if you get it at the start of the season. You can make heavy savings by buying second hand. You might be able to get a complete package (board boots bindings) for under $150-$200, and spend around $200-$300 on the rest of your clothes.

  • The two most important pieces of equipment are boots and gloves. No matter what kind of snowboard or bindings you have, if your boots suck, so will you. Boots that fit and are comfortable go a long way towards your snowboarding experience so don't go cheap here. Chose from a descent brand, and try them on a shops to get a feel for them. Then try and buy them online where it might be cheaper. As for gloves, get some good waterproof ones. Having wet and cold hands can make you seriously miserable. I found a good cheap pair of Gore-tex gloves ($50). Gore-tex is a fabric that guarantees to keep you dry, and from my experience, it has lived up to its hype.

  • Board and Bindings. There are a tonne of manufacturers and brands out there, and a lot of different types of boards. Do some research, if you can try some and demos, rentals, shops and see what style you like. If I could chose my next board, it would be a Bataleon.

  • Getting goggles is not absolutely necessary, but its good for keeping wind and snow out, and does work better than sunnies by themselves.

Thursday, November 4, 2010

C# Email Helper for sending out HTML Emails with data

Summary


The following article contains code to send data via a dictionary to a Mail Helper which builds an html email based on an Email template defined by a user control.

Premise


At work, I have had to build websites which send out html emails. We already had some code which loaded a user control into an html writer, which gave a html string to be placed in the html body for sending .Net mail. I wanted to abstract the logic out so that I could reuse it in any of my projects without having to modify all the parameters etc.

Essentially the things that were different were the HTML template, and the data to be bound to the template. Everything else; the building, the sending all had the same logic.

The Code


First we have the MailHelper class, which will build and send the email. We pass in the path of the email template, and basic email parameters such as to, from and subject. The dictionary is a string object pair for convenience. Use the string as a key to reference your objects similar to a ViewState or ViewModel.

Then you will see the EmailControl class which extends UserControl. We want to place a method there for setting the key value pairs. And then we want all Email templates to extend from this class.


public static class MailHelper
    {

        public static void SendEmail(string controlPath, 
                                     string to, 
                                     string from, 
                                     string subject, 
                                     Dictionary<string, object> keyValuePairs)
        {
            var body = GenerateContactEmailBody(controlPath, keyValuePairs);
 
            var officeMessage = new MailMessage(from, to)
            {
                Subject = subject,
                IsBodyHtml = true,
                Body = body
            };
 
            var client = new SmtpClient();
 
            client.Send(officeMessage);
        }
 
        private static string GenerateContactEmailBody(string path, 
                                  Dictionary<string, object> keyValuePairs)
        {
            Page pageHolder = new Page();
            var emailControl = (EmailControl)pageHolder.LoadControl(path);
            emailControl.SetKeyValuePairs(keyValuePairs);
            var writer = new StringWriter(CultureInfo.CurrentCulture);
            emailControl.RenderControl(new Html32TextWriter(writer));
            return writer.ToString();
        }
    }
 
    public class EmailControl : System.Web.UI.UserControl
    {
        public virtual void SetKeyValuePairs(Dictionary<string,object> value)
        {
            throw new NotImplementedException();
        }
    }

So now we can create a new HTML Email template. Create a new UserControl, make this extend EmailControl instead of extending UserControl directly. Then override the SetKeyValuePairs method. In my example below, I have a ContactUs email template where I accept values for Name, Email, Telephone, and Question. These are all strings but could have been other objects.

Then in my ascx file, I create the html template as per a design, and bind the properties where they are needed. The override for RenderControl is needed when we generate the html in the MailHelper.

public partial class ContactUs : EmailControl
    {
 
        public override void SetKeyValuePairs(Dictionary<string, object> value)
        {
            Name = value["Name"].ToString();
            Email = value["Email"].ToString();
            Telephone = value["Telephone"].ToString();
            Question = value["Question"].ToString();
        }
 
 
        public string Name { get; set; }
 
        public string Email { get; set; }
 
        public string Telephone { get; set; }
 
        public string Question { get; set; }
 
        public override void RenderControl(HtmlTextWriter writer)
        {
            DataBind();
            base.RenderControl(writer);
        }
    }

Finally, the bit of code which I call on my page which actually calls the MailHelper and sends out the email.

var kvp = new Dictionary<string, object>();
            kvp.Add("Name", name);
            kvp.Add("Email", email);
            kvp.Add("Telephone", telephone);
            kvp.Add("Question", question);
 
            var to = ConfigurationManager.AppSettings["ContactTo"];
            var from = ConfigurationManager.AppSettings["ContactFrom"];
            var subject = ConfigurationManager.AppSettings["ContactSubject"];
 
            MailHelper.SendEmail("~/ContactUs.ascx", to, from, subject, kvp);

Sunday, October 17, 2010

C# Random Password Generator

This blog post has moved to my new blog, you are about to be redirected...




In an earlier post, I wrote a Random Password Generator class intended for anyone interested to plug into their application.

Following some input I received, I have refactored the code a bit:

using System;
using System.Security.Cryptography;


namespace Security
{

    public class RandomPasswordGenerator
    {
        // Define default password length.
        private static int DEFAULT_PASSWORD_LENGTH = 8;

        //No characters that are confusing: i, I, l, L, o, O, 0, 1, u, v

        public static string PASSWORD_CHARS_ALPHA = 
                                "abcdefghjkmnpqrstwxyzABCDEFGHJKMNPQRSTWXYZ";
        public static string PASSWORD_CHARS_NUMERIC = "23456789";
        public static string PASSWORD_CHARS_SPECIAL = "*$-+?_&=!%{}/";
        public static string PASSWORD_CHARS_ALPHANUMERIC = 
                                PASSWORD_CHARS_ALPHA + PASSWORD_CHARS_NUMERIC;
        public static string PASSWORD_CHARS_ALL = 
                                PASSWORD_CHARS_ALPHANUMERIC + PASSWORD_CHARS_SPECIAL;
        
        //These overloads are only necesary in versions of .NET below 4.0
        #region Overloads

        /// 
        /// Generates a random password with the default length.
        /// 
        /// Randomly generated password.
        public static string Generate()
        {
            return Generate(DEFAULT_PASSWORD_LENGTH,
                            PASSWORD_CHARS_ALL);
        }

        /// 
        /// Generates a random password with the default length.
        /// 
        /// Randomly generated password.
        public static string Generate(string passwordChars)
        {
            return Generate(DEFAULT_PASSWORD_LENGTH, 
                            passwordChars);
        }

        /// 
        /// Generates a random password with the default length.
        /// 
        /// Randomly generated password.
        public static string Generate(int passwordLength)
        {
            return Generate(passwordLength,
                            PASSWORD_CHARS_ALL);
        }

        /// 
        /// Generates a random password.
        /// 
        /// Randomly generated password.
        public static string Generate(int passwordLength,
                                      string passwordChars)
        {
            return GeneratePassword(passwordLength, 
                                    passwordChars);
        }

        #endregion


        /// 
        /// Generates the password.
        /// 
        /// 
        private static string GeneratePassword(int passwordLength,
                                               string passwordCharacters)
        {
            if (passwordLength < 0) 
                throw new ArgumentOutOfRangeException("Password Length");

            if (string.IsNullOrEmpty(passwordCharacters)) 
                throw new ArgumentOutOfRangeException("Password Characters");
            
            var password = new char[passwordLength];

            var random = GetRandom();

            for (int i = 0; i < passwordLength; i++)
                password[i] = passwordCharacters[
                                          random.Next(passwordCharacters.Length)];

            return new string(password);
        }



        

        /// 
        /// Gets a random object with a real random seed
        /// 
        /// 
        private static Random GetRandom()
        {
            // Use a 4-byte array to fill it with random bytes and convert it then
            // to an integer value.
            byte[] randomBytes = new byte[4];

            // Generate 4 random bytes.
            new RNGCryptoServiceProvider().GetBytes(randomBytes);

            // Convert 4 bytes into a 32-bit integer value.
            int seed = (randomBytes[0] & 0x7f) << 24 |
                        randomBytes[1] << 16 |
                        randomBytes[2] << 8 |
                        randomBytes[3];

            // Now, this is real randomization.
            return new Random(seed);
        }


    }
}


Thursday, September 30, 2010

What are TFS Labels for?

Just some interesting reading in the following links:

http://iworkonsoftware.blogspot.com/2010/04/tfs-labels.html

http://www.notionsolutions.com/notionmedia/articles/Pages/VirtuesandPitfallsoftheTFSLabel.aspx

How do you use TFS Labels?

Thursday, September 9, 2010

C# ASP.NET CheckBoxList selecting items on OnDataBinding doesn't work, set it on OnDataBound instead

When I try to bind some objects to a CheckBoxList in the OnDataBinding method, it never seems to select it when I tell it to do so:

protected override void OnDataBinding(EventArgs e)
 {
    base.OnDataBinding(e);
 
    chkBxLstProducts.DataSource = Product.GetAll();
    chkBxLstProducts.DataBind();
 
    foreach (var item in chkBxLstProducts.Items.Cast())
    {
         item.Selected = ((ICollection)FieldValue).Cast()
                         .Any(p => p.ProductId == Convert.ToInt32(item.Value));
    }
 }

 

When I move the selection code into the OnDataBound method, it works:

protected override void OnDataBinding(EventArgs e)
 {
    base.OnDataBinding(e);
    
    chkBxLstProducts.DataSource = Product.GetAll();
    chkBxLstProducts.DataBind();
 }

 protected void OnDataBound(object sender, EventArgs e)
 {
    foreach (var item in chkBxLstProducts.Items.Cast())
    {
        item.Selected = ((ICollection)FieldValue).Cast()
                        .Any(p => p.ProductId == Convert.ToInt32(item.Value));
    }
 }


I’m not 100% sure, but I think it’s because the OnDataBinding event occurs before the CheckBoxList is rendered. So after it’s rendered, everything is wiped clean and we lose the selection. Selecting items after OnDataBound ensures it gets rendered.

Tuesday, September 7, 2010

C# Random Password Generator

Below is a class for you to plug into your projects.

It generates random passwords by using actual random seed and omits those pesky letters that look similar to one another.

You can reuse the class by passing in options such as password length and the different characters you want to include. And since its the source code, you can extend/adapt it to your needs.

Enjoy

This blog post has moved to my new blog, you are about to be redirected...



using System;
using System.Security.Cryptography;
 
 
namespace Security
{
    public enum RandomPasswordOptions
    {
        Alpha = 1,
        Numeric = 2,
        AlphaNumeric = Alpha + Numeric,
        AlphaNumericSpecial = 4
    }
 
    public class RandomPasswordGenerator
    {
        // Define default password length.
        private static int DEFAULT_PASSWORD_LENGTH = 8;
 
        //No characters that are confusing: i, I, l, L, o, O, 0, 1, u, v
 
        private static string PASSWORD_CHARS_Alpha = 
                                   "abcdefghjkmnpqrstwxyzABCDEFGHJKMNPQRSTWXYZ";
        private static string PASSWORD_CHARS_NUMERIC = "23456789";
        private static string PASSWORD_CHARS_SPECIAL = "*$-+?_&=!%{}/";
 
        #region Overloads
 
        /// 
        /// Generates a random password with the default length.
        /// 
        /// Randomly generated password.
        public static string Generate()
        {
            return Generate(DEFAULT_PASSWORD_LENGTH, 
                            RandomPasswordOptions.AlphaNumericSpecial);
        }
 
        /// 
        /// Generates a random password with the default length.
        /// 
        /// Randomly generated password.
        public static string Generate(RandomPasswordOptions option)
        {
            return Generate(DEFAULT_PASSWORD_LENGTH, option);
        }
 
        /// 
        /// Generates a random password with the default length.
        /// 
        /// Randomly generated password.
        public static string Generate(int passwordLength)
        {
            return Generate(DEFAULT_PASSWORD_LENGTH, 
                            RandomPasswordOptions.AlphaNumericSpecial);
        }
 
        /// 
        /// Generates a random password.
        /// 
        /// Randomly generated password.
        public static string Generate(int passwordLength, 
                                      RandomPasswordOptions option)
        {
            return GeneratePassword(passwordLength, option);
        }
 
        #endregion
 
 
        /// 
        /// Generates the password.
        /// 
        /// 
        private static string GeneratePassword(int passwordLength, 
                                               RandomPasswordOptions option)
        {
            if (passwordLength < 0) return null;
 
            var passwordChars = GetCharacters(option);
 
            if (string.IsNullOrEmpty(passwordChars)) return null;
 
            var password = new char[passwordLength];
 
            var random = GetRandom();
 
            for (int i = 0; i < passwordLength; i++)
            {
                var index = random.Next(passwordChars.Length);
                var passwordChar = passwordChars[index];
 
                password[i] = passwordChar;
            }
 
            return new string(password);
        }
 
 
 
        /// 
        /// Gets the characters selected by the option
        /// 
        /// 
        private static string GetCharacters(RandomPasswordOptions option)
        {
            switch (option)
            {
                case RandomPasswordOptions.Alpha:
                    return PASSWORD_CHARS_Alpha;
                case RandomPasswordOptions.Numeric:
                    return PASSWORD_CHARS_NUMERIC;
                case RandomPasswordOptions.AlphaNumeric:
                    return PASSWORD_CHARS_Alpha + PASSWORD_CHARS_NUMERIC;
                case RandomPasswordOptions.AlphaNumericSpecial:
                    return PASSWORD_CHARS_Alpha + PASSWORD_CHARS_NUMERIC + 
                                 PASSWORD_CHARS_SPECIAL;
                default:
                    break;
            }
            return string.Empty;
        }
        
        /// 
        /// Gets a random object with a real random seed
        /// 
        /// 
        private static Random GetRandom()
        {
            // Use a 4-byte array to fill it with random bytes and convert it then
            // to an integer value.
            byte[] randomBytes = new byte[4];
 
            // Generate 4 random bytes.
            RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();
            rng.GetBytes(randomBytes);
 
            // Convert 4 bytes into a 32-bit integer value.
            int seed = (randomBytes[0] & 0x7f) << 24 |
                        randomBytes[1] << 16 |
                        randomBytes[2] << 8 |
                        randomBytes[3];
 
            // Now, this is real randomization.
            return new Random(seed);
        }
 
 
    }
}