Tuesday, 30 December 2008

Composite Controls in ASP.NET (Creating a simple control)

Creating composite controls is a very powerful way to create re-usable components for web sites. Once created they can be quickly and easily deployed and offer total control over the components that you use in your composite control.

Follow the steps below to create your first composite control:

1. Create a new class with a meaningful name

2. Import the following libraries (not all are needed but they will come in useful)

System.Web;
System.Web.UI;
System.Web.UI.WebControls;
System.Web.UI.HtmlControls;

3. Now make the class you have just created public and inherit from CompositeControl

public class MyControl : CompositeControl

3a. Add a label control to your composite control by overriding the CreateChildControls method in the body of your class.

protected override void CreateChildControls()
{

Label myLabel = new Label();

myLabel.text = "Hello world";

Controls.Add(myLabel);

base.CreateChildControls();
}


As you can see I have created a Label control, set the text "Hello world" and then added it to the pages Controls collection.

Any controls added to the Controls collection will be rendered in turn and as long as they are added to this collection they will be rendered.

3b. This alternative method is more of a raw and lower level way of creating content in your composite control

Instead of overriding the CreateChildControls method override the RenderContents method in the body of your class.

protected override void RenderContents(HtmlTextWriter output)
{
output.Write("Hello world");

}

Both of these methods achive exactly the same thing but are very different ways of doing things. and both have their advantages and disadvantages.

4. Now you have to add the control to a (*.aspx) web page so firstly register the assembly (your composite control). Below is an example but depending on how your project and namespace is named and arranged it will vary.

<%@ Register Assembly="MyControls" TagPrefix="MyControl" Namespace="MyControls" %>

5. Add the control to your page. Again the actual code witll vary depending on how you have named things but below is an exaple.



Now when you view your page in the browser "Hello world" should be written to the screen. Not very useful but shows the basics to creating your own composite controls.

Monday, 22 December 2008

Creating a dynamic site map using ASP.NET and VS 2008

Site maps are an integral part of Search Engine Optimisation (SEO) and if used along with Google Web Master tools provides an easy and powerful way to automatically get all your pages indexed.

Creating a sitemap XML file by hand is very easy but what if you have a site where content is being added all the time, it would be very time consuming to add a new entry to your site map file everytime a new item was added to your site. This is a requirement a client had q while back and so I took the following steps to create them a dynamic site map and I now use this code all all applicable sites I create.

1. Open up your website project in Visual Studio (I use 2008)

2. Add a new Item to your project, choose "Web Form" and give the file a name (e.g. "sitemap.aspx")

3. Once VS has created and opened your new file remove everything from *.aspx file apart from the page declaration line (enclosed in <% %>)

4. Open the *.aspx.cs file and make sure you have imported the "System.Xml" namespace

5. Add the following code to the "Page_Load"

Response.Clear();

XmlTextWriter xmlWriter = new XmlTextWriter(Response.OutputStream, Encoding.UTF8);

xmlWriter.WriteStartDocument();
xmlWriter.WriteStartElement("urlset");
xmlWriter.WriteAttributeString("xmlns",
http://www.sitemaps.org/schemas/sitemap/0.9);

xmlWriter.WriteEndElement();
xmlWriter.WriteEndDocument();
xmlWriter.Close();


This is the basis of your site map file and all its doing is clearing the Response stream (this is what is going to be written to the browser), creates a new Xml text writer and tells that to write it's output to the response stream.

This means that the actual output will be an XML rather than HTML.

6. For static pages add an entry like the following (replaing the parts between the <> with the apropriate information):

xmlWriter.WriteStartElement("url");
xmlWriter.WriteElementString("loc", "http:///.aspx");
xmlWriter.WriteElementString("changefreq", "weekly");
xmlWriter.WriteEndElement();


Add as many entries like this as you need and feel free to change the "changefreq" value to anything you want.

8. Dynamically add other pages. Now the specifics of this will vary depending on how you store and retrieve information but for my example I have an object named "Article" which holds information about an article (ID, title, body and date created) and I have a collection of "Article" objects stored in a generic list called "ListArticles" which is fed straight from the database.

foreach (Article article in listArticles)
{
xmlWriter.WriteStartElement("url");
xmlWriter.WriteElementString("loc", "http:///ViewArticle.aspx?articleID=" + article.ArticleID.ToString());
xmlWriter.WriteElementString("lastmod", article.DateCreateD.ToString("yyyy-MM-dd"));
xmlWriter.WriteEndElement();
}


As you can see I am looping round all the "Article" objects in my list and writing each one using my Xml Writer to the response stream.



Below is the complete example code:


protected void Page_Load(object sender, EventArgs e)
{
Response.Clear();

XmlTextWriter xmlWriter = new XmlTextWriter(Response.OutputStream, Encoding.UTF8);

xmlWriter.WriteStartDocument();

xmlWriter.WriteStartElement("urlset");
xmlWriter.WriteAttributeString("xmlns", "http://www.sitemaps.org/schemas/sitemap/0.9");
xmlWriter.WriteStartElement("url");

xmlWriter.WriteElementString("loc", "http:///Default.aspx");
xmlWriter.WriteElementString("changefreq", "daily");
xmlWriter.WriteEndElement();


ListArticles listArticles = new ListArticles();

foreach (Article article in listArticles)
{
xmlWriter.WriteStartElement("url");
xmlWriter.WriteElementString("loc", "http:///ViewArticle.aspx?articleID=" + article.ArticleID.ToString());
xmlWriter.WriteElementString("lastmod", article.DateCreate.ToString("yyyy-MM-dd"));
xmlWriter.WriteEndElement();
}


xmlWriter.WriteEndElement();
xmlWriter.WriteEndDocument();
xmlWriter.Close();
}