Tuesday, December 30, 2008

Add RSS Feeds in 2 seconds

Hi All, 

Just a short post to show you how to add RSS to your website in 2 easy steps.

Step 1 : Create an XML file in your solution and add a link to it from your page.

Step 2 : Use this format to make RSS posts 


Hope this helps, 

 - Tim 

Dynamically Load Controls onto Page

Hi All, 

I was recently asked to dynamically load usercontrols onto a page based on what other controls were on the page. Here is how you do it :

DynamicMenu.ascx



DynamicMenu.ascx.cs


Hope this helps, 

 - Tim

Becoming your own Contracting Agency

Hi All, 

Recently, I have considered starting my own contracting agency, so I would not have to always go through a recruitment agency for new contracts. Seeing that I have recently had an influx of contracts thrown my way, I thought it was time to start looking at having my own business where I could contract under my own company name. There is one problem, there really isn't a lot of information out there to help with exactly what I wanted. After some snooping around, some networking and talking to colleages I have composed this for anyone considering the same avenue.

There seems to be 4-5 ways of approaching the idea and they can be summarised into

1. Going through a Recruiter
2. Rent-A-Coder Approach
3. Your own Company
4. Management Company
5. Cough...Cough...Under the table approach.


Going through a recruiter.
The advantages of going through a recruiter include services that are often neglected when taking on a contracting job. This includes the management of Tax, Super, Payroll, Insurance and other HR/Employments needs. Sure you pay a bit of money to the recruitment agency, but in return you get the assurance, that all you have to do is your job and you will get paid.

Rent a Coder Approach
This approach is based on the idea that you get work off sites like www.rentacoder.com and simply set up a bank account that business pay money into. There are pitfalls with this approach. 

A) You aren't guareenteed any work
B) I have personally been stung with this before, and was not paid for my work
C) You may need to diversify your tech skills to keep this as a steady stream of revenue.

Your Own Company approach
Let's face it, every developer would like to answer the question "What do you do for a living?" with "oh, I own insert company name here, an IT contracting company"......right? Some of the advantages of this approach include

A) Tax breaks
B) You are your own boss - could be bad if you are not motivated
C) Work from home
D) Acquire a reputation - could also be bad :)
E) Work on new products all the time
F) Great hourly rates
G) Easier to avoid work place "politics"
H) Easy to walk away after a contract.

However with all the advantages come many disadvantages being

A) You have to organise everything....paperwork, insurance, contracts, super etc.
B) No paid leave
C) Usually pay for your own training
D) Work locations can vary

Management Company
There are plenty of companies out there (not recruitment) that will do all the management for you (super, insurance etc) however the only difference is that they will not find you jobs. If you are the kind of person that finds a lot of work through friends, people in the industry, then i would definitely recommend this. They do not charge as much as recruitment agencies and from my research, do just as good a job. Some agencies within Australia include :


Under the table approach
In no way do I condone tax dodges...if anything I simply suggest people do them :)

This approach bsaically involves working with people you know, people you have network with for less money, however in return you are payed in cash.

Hope this helps, 

 - Tim

Sunday, December 28, 2008

My Brothers Web Site

Hi All, 

In the short time off I had over Christmas (very busy) I was able to find a few hours to build my brothers new web site. He wanted something simple, something stylish and something easy for him to maintain. Ben (my Brother) is a creative graphic artist and required something to send around as a resume. Here is what a couple of bored hours over Christmas produced :


If anyone wants, I can put up the code for all the jQuery etc. (Just leave a comment)

Thanks, 

 - Tim

Sunday, December 7, 2008

Bad Characters in XML

I was recently asked by a friend, "How to ignore bad characters in an XML file?" Two ways of doing it include, using XSLT to transform the document to only use nodes that have good characters in it, or you can simply use the tags around the characters that are of a different encoding standard and the XMLDoc object will ignore it.

Creating Custom HTTP Handlers

Hi all, 

I am now at the stage in my project where I need to find ways of fine tune the loading times. Of course I have used tools like Firbug etc to run diagnosis on what is taking a long time to load etc. One thing I did find, was that a lot of the time I was using .ASPX files to load something that really only need a method call, and not all the overhead that comes with an ASPX page. So what else to use, but a custom HTTP Handler!

I decided that I would use a ASHX file to load my CSS into the pag
e instead of just adding a reference within the ASPX page and making .net do all the work. The payoff, was a load time of the CSS that was about half!!!!

Here is how you do it.

Create a Generic Handler file in your Website or Web Application.

Call the file "CSSHttpHandler"



You will be presented with the following code :


By default you only have to implement one method and a property when implementing the IHttpHandler interface

public void ProcessRequest (HttpContext context) {
        context.Response.ContentType = "text/plain";
        context.Response.Write("Hello World");
    }
 
    public bool IsReusable {
        get {
            return false;
        }
    }

Replace the code with this :

using System.IO;
using System.Text;
using System.Text.RegularExpressions;
using System.Web;
using System.IO.Compression;

public class CSSHttpHandler : IHttpHandler {

    private const string PrefixAllImagesWith = "~/";
    private readonly static TimeSpan KeepInCache = TimeSpan.FromDays(15);
    private readonly static Regex UrlCheck = new Regex(@"http(s)?://([\w-]+\.)+[\w-]+(/[\w- ./?%&=]*)?", RegexOptions.Compiled);

    public void ProcessRequest(HttpContext context)
    {
        context.Response.ContentType = "text/css";
        var themeName = context.Request["theme"];
        var themeFileNames = context.Request["files"];
        var version = context.Request["version"];

        var isCompressed = CanGZip(context.Request);

        var encoding = new UTF8Encoding(false);

        if (WriteFromCache(context, themeName, version, isCompressed)) return;
        using (var memoryStream = new MemoryStream(5000))
        {
            using (var writer = isCompressed ? (Stream)(new GZipStream(memoryStream, CompressionMode.Compress)) : memoryStream)
            {
                if (!string.IsNullOrEmpty(themeName))
                {
                    var themeCssNames = themeFileNames.Split(',');
                    foreach (var fileName in themeCssNames)
                    {
                        var fileBytes = GetCss(context,
                                                  "~/App_Themes/" + themeName + "/" + fileName,
                                                  PrefixAllImagesWith, version, encoding);
                        writer.Write(fileBytes, 0, fileBytes.Length);
                    }
                }

                writer.Close();
            }

            var responseBytes = memoryStream.ToArray();
            context.Cache.Insert(GetCacheKey(themeName, version, isCompressed),
                                 responseBytes, null, System.Web.Caching.Cache.NoAbsoluteExpiration,
                                 KeepInCache);

            WriteBytes(responseBytes, context, isCompressed);
        }
    }

    private static bool WriteFromCache(HttpContext context, string themeName,
        string version, bool isCompressed)
    {
        var responseBytes = context.Cache[GetCacheKey(themeName,
            version, isCompressed)] as byte[];

        if (null == responseBytes) return false;

        WriteBytes(responseBytes, context, isCompressed);
        return true;
    }

    private static void WriteBytes(byte[] bytes, HttpContext context, bool isCompressed)
    {
        var response = context.Response;

        response.AppendHeader("Content-Length", bytes.Length.ToString());
        response.ContentType = "text/css";
        if (isCompressed)
            response.AppendHeader("Content-Encoding", "gzip");

        context.Response.Cache.SetCacheability(HttpCacheability.Public);
        context.Response.Cache.SetExpires(DateTime.Now.Add(KeepInCache));
        context.Response.Cache.SetMaxAge(KeepInCache);
        context.Response.Cache.AppendCacheExtension("must-revalidate, proxy-revalidate");

        response.OutputStream.Write(bytes, 0, bytes.Length);
        response.Flush();
    }

    private static bool CanGZip(HttpRequest request)
    {
        var acceptEncoding = request.Headers["Accept-Encoding"];
        return !string.IsNullOrEmpty(acceptEncoding) &&
               (acceptEncoding.Contains("gzip") || acceptEncoding.Contains("deflate"));
    }

    private static byte[] GetCss(HttpContext context, string virtualPath,
        string imagePrefix, string version, Encoding encoding)
    {
        var physicalPath = context.Server.MapPath(virtualPath);
        var fileContent = File.ReadAllText(physicalPath, encoding);

        var imagePrefixUrl = imagePrefix +
            VirtualPathUtility.GetDirectory(virtualPath).TrimStart('~').TrimStart('/');
        var cssContent = UrlCheck.Replace(fileContent,
            new MatchEvaluator(delegate(Match m)
            {
                var imgPath = m.Groups["path"].Value.TrimStart('\'').TrimEnd('\'').TrimStart('"').TrimEnd('"');

                if (!imgPath.StartsWith("http://"))
                {
                    return "url('" + imagePrefixUrl 
                        + imgPath 
                        + (imgPath.IndexOf('?') > 0 ? "&version=" + version : "?version=" + version)
                        + "')";
                }
                else
                {
                    return "url('" + imgPath + "')";
                }
            }));

        return encoding.GetBytes(cssContent);
    }

    private static string GetCacheKey(string themeName, string version, bool isCompressed)
    {
        return "CssHttpHandler." + themeName + "." + version + "." + isCompressed;
    }

    public bool IsReusable
    {
        get
        {
            return true;
        }
    }
}

Then in the Render Method of the Page you are loading e.g. Default.aspx simply use this code

 var themeName = Page.Theme;
        if (string.IsNullOrEmpty(themeName)) return;
        var linksToRemove = new List();
        foreach (Control c in Page.Header.Controls)
            if (c is HtmlLink)
                if ((c as HtmlLink).Href.Contains("App_Themes/" + themeName))
                    linksToRemove.Add(c as HtmlLink);

        string themeCssNames = "";
        linksToRemove.ForEach(delegate(HtmlLink link)
                                  {
                                      Page.Header.Controls.Remove(link);
                                      themeCssNames += VirtualPathUtility.GetFileName(link.Href) + ',';
                                  });

        var linkTag = new Literal();

        var cssPath = CSS_PREFIX + "CssHttpHandler.ashx?theme=" + themeName
                      + "&files=" + HttpUtility.UrlEncode(themeCssNames.TrimEnd(','))
                      + "&version=" + CSS_VERSION;

        linkTag.Text = string.Format(@"&ltlink href=""{0}"" type=""text/css"" rel=""stylesheet"" /%gt", cssPath);
        Page.Header.Controls.Add(linkTag);

Hope this Helps, 

 - Tim

Validation

There are so many ways to do validation these days and all have their benefits. I have been working with the built in .net Validation Controls and from this have defined a list of tips : 

Here are the built in controls you recieve from the framework



Here is the form I am dealing with :



Required Field Validator

This control is simply used to make sure another control, such as a textbox will error if the page tries to redirect without the textbox having anything entered in it.

Tips

Set the error message as something descriptive
Set the text to "*"
Set the ControlTo Validate as the Textbox you wish to control

Range Validator

This control makes sure that the control that this validator is controlling falls within a bounds. 

Regular Expression Validator

This control uses Regular Expressions to Validate another control

Tips

There are built int Regula
r Expressions for commonly used validation types e.g. Phone Numbers, Email Address' etc.

Compare Validator

This control is used to compare to controls to each other. This a great control to use for password and confirm password controls.

Custom Validator

This control is used for complex validation that the other validation controls cannot perform. For example, if you wanted to check if the number entered in a textbox is divisble by 2.

ASPX

CODE BEHIND

protected void IsDivisibleByTwo(object sender, ServerValidateEventArgs e)
{
 // Some Code
}

Validation Summary

I always use this control at the bottom of the page. It basically grabs all the validation controls on the page and displays their error messages in a summary format.

Hope this helps,

 - Tim