Combined plain and HTML email

This article explains how you can combine both a plain text and a HTML message in one EMail by defining its content type.

Setting the “Content-Type:” of an email message as “Multipart/Alternative” tells the mail system you are creating the email message in parts, one text/plain and the other text/html. Which part is displayed is left up to the client email program.

View the email

There are a couple of problems with this method, first of which is the filesize can more than double and every recipient has to download the whole thing. The second issue is that the majority of mail readers that understand multipart also understand HTML!

Having said that it is still a useful technique in some circumstances. Check out the below example script which demonstrates loading a template email and replaces keywords. I use a text file creation technique to show how you can implement this with a wide variety of smtp servers regardless of wether they support the multipart functionality directly or not.

Multilingual ASP.NET CodePages and Character Sets

If you try to display content in a foreign character set and language to your own you will find that ASP.NET displays lots of squares and squiggles that just don’t look right. This is because you need to inform the browser how the content should be displayed. This code snippet shows how this is done.

In order to set the content correctly we need to apply a CodePage and a Charset.

Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

Response.Charset = GetCharset(Request(“lang”))

Session.CodePage = GetCodePage(Request(“lang”))

End Sub

The functions used above select the relevant codepages and character sets from the ISO standard lists.

Function GetCodePage(ByVal country As String) As Integer

Dim CodePages As New Hashtable()

CodePages.Add(“au”, “1252”)

CodePages.Add(“at”, “1252”)

CodePages.Add(“bh”, “1252”)

CodePages.Add(“be”, “1252”)

CodePages.Add(“bl”, “1252”)

CodePages.Add(“ca”, “1252”)

CodePages.Add(“cf”, “1252”)

CodePages.Add(“cn”, “936”)

CodePages.Add(“hr”, “1250”)

CodePages.Add(“cy”, “1252”)

CodePages.Add(“cz”, “1250”)

CodePages.Add(“dk”, “1252”)

CodePages.Add(“fi”, “1252”)

CodePages.Add(“fr”, “1252”)

CodePages.Add(“de”, “1252”)

CodePages.Add(“gr”, “1253”)

CodePages.Add(“hk”, “1252”)

CodePages.Add(“hu”, “1252”)

CodePages.Add(“ic”, “1252”)

CodePages.Add(“in”, “1252”)

CodePages.Add(“il”, “1255”)

CodePages.Add(“it”, “1252”)

CodePages.Add(“jp”, “51932”)

CodePages.Add(“jo”, “1252”)

CodePages.Add(“kw”, “1252”)

CodePages.Add(“lm”, “1252”)

CodePages.Add(“lb”, “1252”)

CodePages.Add(“mt”, “1252”)

CodePages.Add(“my”, “1250”)

CodePages.Add(“nl”, “1252”)

CodePages.Add(“nz”, “1252”)

CodePages.Add(“no”, “1252”)

CodePages.Add(“om”, “1252”)

CodePages.Add(“pl”, “1252”)

CodePages.Add(“qa”, “1252”)

CodePages.Add(“ro”, “1252”)

CodePages.Add(“ru”, “28595”)

CodePages.Add(“sa”, “1252”)

CodePages.Add(“sk”, “1250”)

CodePages.Add(“za”, “1252”)

CodePages.Add(“es”, “1252”)

CodePages.Add(“se”, “1252”)

CodePages.Add(“tw”, “1252”)

CodePages.Add(“th”, “874”)

CodePages.Add(“tr”, “1252”)

CodePages.Add(“ae”, “1252”)

CodePages.Add(“us”, “1252”)

CodePages.Add(“uk”, “1252”)

Return CInt(CodePages(LCase(country)))

CodePages = Nothing

End Function

Function GetCharset(ByVal country As String) As String

Dim Charsets As New Hashtable()

Charsets.Add(“au”, “ISO-8859-1”)

Charsets.Add(“at”, “iso-8859-1”)

Charsets.Add(“bh”, “windows-1256”)

Charsets.Add(“be”, “ISO-8859-1”)

Charsets.Add(“bl”, “ISO-8859-1”)

Charsets.Add(“ca”, “ISO-8859-1”)

Charsets.Add(“cf”, “ISO-8859-1”)

Charsets.Add(“cn”, “gb2312”)

Charsets.Add(“hr”, “windows”)

Charsets.Add(“cy”, “ISO-8859-1”)

Charsets.Add(“cz”, “windows-1250”)

Charsets.Add(“dk”, “ISO-8859-1”)

Charsets.Add(“fi”, “ISO-8859-1”)

Charsets.Add(“fr”, “ISO-8859-1”)

Charsets.Add(“de”, “20106”)

Charsets.Add(“gr”, “windows-1253”)

Charsets.Add(“hk”, “big5”)

Charsets.Add(“hu”, “ISO-8859-1”)

Charsets.Add(“ic”, “ISO-8859-1”)

Charsets.Add(“in”, “ISO-8859-2”)

Charsets.Add(“uk”, “ISO-8859-1”)

Charsets.Add(“il”, “iso-8859-8”)

Charsets.Add(“it”, “ISO-8859-1”)

Charsets.Add(“jp”, “euc-jp”)

Charsets.Add(“jo”, “windows-1256”)

Charsets.Add(“kw”, “windows-1256”)

Charsets.Add(“lm”, “ISO-8859-1”)

Charsets.Add(“lb”, “windows-1256”)

Charsets.Add(“mt”, “ISO-8859-1”)

Charsets.Add(“nl”, “ISO-8859-1”)

Charsets.Add(“nz”, “ISO-8859-1”)

Charsets.Add(“no”, “ISO-8859-1”)

Charsets.Add(“om”, “windows-1256”)

Charsets.Add(“pl”, “ISO-8859-2”)

Charsets.Add(“qa”, “windows-1256”)

Charsets.Add(“ro”, “ISO-8859-1”)

Charsets.Add(“ru”, “windows-1251”)

Charsets.Add(“sa”, “windows-1256”)

Charsets.Add(“my”, “ISO-8859-2”)

Charsets.Add(“sk”, “ISO-8859-2”)

Charsets.Add(“za”, “ISO-8859-1”)

Charsets.Add(“es”, “ISO-8859-1”)

Charsets.Add(“se”, “ISO-8859-1”)

Charsets.Add(“tw”, “big5”)

Charsets.Add(“th”, “windows-874”)

Charsets.Add(“tr”, “iso-8859-9”)

Charsets.Add(“ae”, “windows-1256”)

Charsets.Add(“us”, “ISO-8859-1”)

Return Charsets(LCase(country))

Charsets = Nothing

End Function


Setting the ASP.NET Page Title and Meta Tags

In this article we will look at how to set the page title, meta description and meta keywords at runtime with a small about of code.

When you first look at using ASP.NET it seems that the only page objects you have access to are the ones within the FORM tags. Actually with a tiny amount of work you can set other page properties.

The two types of information are set slightly differently. The TITLE is basically a literal tag and it’s value is whatever is put between the starting and ending tags.

Meta tags have their values set as attributes, so these need to be set with another approach.

The example script shows what we need to do in action. It allows the user to enter some text which resets the page title.

See it in action!

If you now take a look at the source we will see both pieces of work that need to be done.

First, in the ASPX file we need to set IDs and RUNAT attributes for each of the items we want to control.

In the codebehind file we first declare new controls for each of the items. We create them as HTMLGenericControls which seems to work fine.

To set the values we use InnerText for the Title, which sets the text that appears between its opening and closing tags, and we set the “content” attribute value for the two Meta tags.


News Service 2: Reading the DB

Last time I showed how with just a few lines written in notepad we can create an ASP.NET Web Service. This article shows how we read the news out of the database with ADO.NET.

If you view the source you will see at first the code does not look all that different from Classic ASP and ADO using Recordsets.

Using the System.Date namespaces, in particular the SQLClient which is specific to SQL Server, we need to create a Connection, a Command and a DataReader.

The connection sets the server, database, username and password to use. Using the command we perform our SQL query which the DataReader reads the results from.

In this example I response.write the string (after removing the string “News:” from it).


Using Amazon’s XML data with ASP.NET

Quite a few people have asked how I did the Amazon .NET book chart, here is the source code and how it works.

Take a look at the chart and you will see it is simply a datagrid.

Take a look at the source

It’s all pretty straight forward, the only bits that may not be immediately obvious are

  • The data source for the grid is set to the XML feed formatted URL (shown below)
  • Grid columns are custom so to allow more flexible formatting
  • On my homepage the page size is set to only show 1 row, so it always shows the most popular book

If you register with Amazon associates you will see links to the XML instructions. At their most basic they take the following form:

This can be changed to reflect a different search by changing the search= value to your keyword. Obviously I would love for you to use my associates ID but if you must change it, alter the t= value.

Line 80 reads this XML into a DataSet, and this is then set as the data source for the Grid.

My columns in the grid are set up using ItemTemplates, with the values displayed using Container.DataItem() which brings down the requested field value from the current row in the data sources set (container being the grid).

Download Source


Integrate RichTextBox with IBS and Forums

When you discover a cool new server control you will immediately start thinking of where and how you can make use of it. RichTextBox has lots of useful example code to get started from scratch, but how easy is it to put to use to enhance your existing code? In this article I attempt to put it to use in my IBuySpy Portal and ASP.NET Forums projects.

First I want to try it out with my personal web site, – the project closest to my heart and also the place I could really do with web-based HTML editing.

My site is a customised version of the IBuySpy portal. This example code allows some content management, but requires HTML to be hand coded. Not that much of a pain, but a perfect place to try out RichTextBox.

IBuySpy Portal

I am glad to say, 5 minutes after looking at the code I had it up and working. The process is simply a case of

  1. Open your Visual Studio project and copy the RichTextBox.dll and XML file to your project Bin directory with “add existing item(s)”
  2. Add�the the control to your toolbox (right click, customise)
  3. swap the existing TextBox in /DesktopModules/EditHtml.aspx with a RichTextBox. (Remember to set the id of the control as “DesktopText”
  4. Enter�your license key
  5. Compile and upload the .aspx and /bin files
  6. Test!

ASP.NET Forums

With the ASP.NET forums, the user interface is mostly handled by the files in the Skins folder. The user control�file that looks after the entering, preview and editing of users forums posts is “Skin-Post.ascx”.

The process to switch this text box (“PostBody”) over to use a RichTextBox is very much the same. A couple more modifications to the code do however need to be made.

If you compile and run the project and test, you will receive an error saying that we are trying to cast our RichTextBox as a plain ol’ TextBox. The offending code is found in Engine/Controls/CreateEditPost.cs where there are several places with statements like the below which is�for the “post editing” routine.

// Set the Body
textbox = (TextBox) controlTemplate.FindControl(“PostBody”);
textbox.Text = post.Body;

We need to change this so it is like the following:

// Set the Body
RichTextBox richtextbox;
richtextbox = (RichTextBox) controlTemplate.FindControl(“PostBody”);
richtextbox.Text = post.Body;

This will swap the code to refer to a RichTextBox instance instead of a TextBox.

Post and Preview routines will also need to be altered In “PostButton_Click” change to the following

RichTextBox richtextbox = (RichTextBox)(form.FindControl(“PostBody”));
postToAdd.Body = richtextbox.Text;

Then find the code where it says “// Preview the post body” and alter the code to reflect the following.

label = (Label) form.FindControl(“PreviewBody”);
RichTextBox richtextbox = (RichTextBox)(form.FindControl(“PostBody”));
label.Text = Globals.FormatPostBody(richtextbox.Text) + Globals.FormatSignature(user.Signature);

You can download my copy of the file below:


So how easy was it in the end?

I guess the answer is .. pretty easy! It is certainly encouraging to see how simple it can be to add a vanilla RichTextBox to existing projects. This is mainly due to the fact that most of the normal�operations involve reading and writing the .Text property which both controls support.

In this article I haven’t done any customisation other than replacing the plain text input box with a shiny new RichTextBox. Obviously once your users get over the pleasant suprise of HTML editing I am sure they will demand more functionality. This may be where the real challenge arises!