Archive for ASP.NET:
Recently I got this error message, basically telling me I was using an unknown server control. In this case, the ListView control. First thing that comes to mind is if the control itself exists in .NET 3.5, which I was using. Of course it does!
Next thing, I was reading about the solution to this being to completely reinstall .NET Framework 3.5 and .NET Framework 3.5 SP1.
However, I solved it by adding two lines to the Web.Config controls element instead, saving me a lot of time.
Here's the code:
<pages>
<controls>
<add tagPrefix="asp" namespace="System.Web.UI" assembly="System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
<add tagPrefix="asp" namespace="System.Web.UI.WebControls" assembly="System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
</controls>
</pages>
Developers often ask me what they can do to improve web standards on their ASP.NET website. There are a number of tricks available and I thought I'd share them with you.
Web.Config magic
First thing to do, is to make sure you've got your Web.Config ready for web standards. This is really simple, as there's only some copy and paste needed. What you want to do is setting xhtmlConformance mode to Strict and make use of browserCaps, both in the system.web section, like this:
<system.web>
<xhtmlConformance mode="Strict" />
<browserCaps>
<case match="W3C_Validator*">
TagWriter = System.Web.UI.HtmlTextWriter
W3CDomVersion = 1.0
</case>
</browserCaps>
....
</system.web>
Use the best .NET controls at your disposal
Countless of times you see .NET controls such as Label and Panel used. Not good, since both render extra HTML output. A label renders an extra span and a Panel renders an extra div, thus affecting the markup of the website - and at worst even breaking the layout.
To the rescue, comes the Literal and PlaceHolder controls. The Literal and PlaceHolder don't render extra markup, and I've never ran into a single problem using them instead.
Also, I like to use the Repeater as often as I can, since I don't always trust third party controls.
Set CSS class on the first listing item
You might have seen class="first" set on the first item in a listing, a number of times. For some, this is a pain to address. However, nothing could be easier than setting a specific CSS class on the first item in a listing. You just have to use the onItemDataBound event on your control. Here's how it might look:
<asp:Repeater ID="rptListing" OnItemDataBound="cssAddons" runat="server">
<ItemTemplate>
<li<asp:Literal ID="cssClass" Visible="false" runat="server"> class="first"</asp:Literal>>
<%#Eval("Item") %>
</li>
</ItemTemplate>
</asp:Repeater>
And the codebehind:
protected void cssAddons(object sender, RepeaterItemEventArgs e)
{
ListItemType type = e.Item.ItemType;
if (type == ListItemType.Item)
{
if (e.Item.ItemIndex == 0)
{
Literal litCssClass = (Literal)e.Item.FindControl("cssClass");
if (litCssClass != null) litCssClass.Visible = true;
}
}
}
You should never be forced to rebuild a project when doing layout changes - that's why one would prefer to use a hidden Literal with the CSS class in the ItemTemplate, and toggling the visibility if it's the first item in a listing.
Customized web controls and CompositeControl
A lot of you are perhaps writing your own web controls. Take note though, inheriting from CompositeControl will make your web controls render an extra span. There's a simple solution to this - just override the Render method in your control, like this, and you're set:
protected override void Render(HtmlTextWriter writer)
{
RenderContents(writer);
}
Some reminders - naming conventions and id's
When it comes to ASP.NET and naming web controls, things can get messy. You want to name your controls as short as possible, without making the name totally meaningless. You particularly want to name your ContentPlaceHolders in a smart way, to avoid id's like this:
ctl00_ContentPlaceHolderContent_ContentPlaceHolderMain_ContentPlaceHolderWidePageWithoutTopImage_ContentPlaceHolderWidePage_ContentPlaceHolderPageContent_ButtonSend
I regularly prefix my web controls, rpt for Repeater, cph for ContentPlaceHolders and so on.
Another problem in ASP.NET Web Forms is id's. If you use runat="server" with a HTML element, the id might look like in the example above. You must avoid this as much as you can, since the altered id's might break the layout. Some might say you should use CSS classes instead, but that's not the way to go. CSS classes aren't meant to be used instead of id's.
In ASP.NET 4, you can actually choose how your id's are rendered, through the ClientIdMode property. A welcome change!
More reading
Remember this is aimed at ASP.NET Web Forms websites, even though part of the tricks can be used in an MVC environment too!
Very often you add a namespace or register an assembly on top of an ASP.NET page, like this:
<%@ Page Language="C#"
AutoEventWireup="True"
CodeBehind="Default.aspx.cs"
Inherits="ProjectName._Default" %>
<%@ Import Namespace="System.IO" %>
<%@ Import Namespace="ProjectName.Classes" %>
<%@ Register Assembly="ProjectName" Namespace="ProjectName.Controls" TagPrefix="cc" %>
It works to do once or twice, but when you need to add these namespaces and controls on several different pages, it quickly becomes maintenance hell.
What to do? Use Web.Config instead.
You just have to declare your namespaces and controls in the system.web section, like this:
<system.web>
<pages>
<namespaces>
<add namespace="System.IO" />
<add namespace="ProjectName.Classes" />
</namespaces>
<controls>
<add assembly="ProjectName" namespace="ProjectName.Controls" TagPrefix="PN" />
</controls>
</pages>
</system.web>
Then you will be able to write code like
<%=Toolbox.FormatHtml("....") %>
instead of code like
<%=ProjectName.Classes.Toolbox.FormatHtml("....") %>
A clear improvement. You also won't need to register your controls everywhere to use them.
If you haven't been using this feature (it already came in ASP.NET 2.0!) it's time now!
When you want to put together a number of strings in ASP.NET, the StringBuilder is very handy. Instead of using concatenation, StringBuilder both looks better and improves performance. You can simply append a set of strings to the StringBuilder and return it, like this:
public static string BuildNumbers()
{
StringBuilder sb = new StringBuilder();
sb.Append("<ul>");
for (int i=0; i<500; i++)
{
sb.Append(string.Format("<li>{0}</li>",i));
}
sb.Append("</ul>");
return sb.ToString();
}
However, sometimes you might want to add a web control to the StringBuilder. A bit more tricky.
What you want to do, is to dynamically create the control and use StringWriter together with HtmlTextWriter to render the control inside the StringBuilder. Like this, when you want a LinkButton:
public static string BuildNumbers()
{
StringBuilder sb = new StringBuilder();
sb.Append("<ul>");
for (int i=0; i<500; i++)
{
sb.Append(string.Format("<li>{0}</li>",i));
}
LinkButton lnkBtn = new LinkButton();
lnkBtn.ID = "lnkBtnSubmit";
lnkBtn.Text = "Submit";
using (StringWriter sw = new StringWriter(sb))
{
using (HtmlTextWriter tw = new HtmlTextWriter(sw))
{
lnkBtn.RenderControl(tw);
}
}
sb.Append("</ul>");
return sb.ToString();
}
I ran into problems with IIS and ASP.NET after I installed Windows 7, so I thought I'd share my then successful installation process with you.
Clean install of Win 7
First of all, a clean installation of Windows 7 is preferred. I recommend you this because it's otherwise possible you encounter a strange problem which has to do with an upgrade.
A clean installation of Windows 7 will always minimize your problems, plus it's the best start you can get.
First instructions
To minimize upcoming problems, the best thing to do is to install the .NET developer tools before you install anything else.
Make sure you install these tools before anything else and your installation will probably as smooth as anything.
My successful installation process went like this:
- Enable IIS and ASP.NET
- Install SQL Server 2008 + Management Studio (plus ASP.NET MVC)
- Install Visual Studio 2008 + Service Pack 1
Enable IIS and ASP.NET
After the installation of Windows 7 is done, it's first time for IIS and ASP.NET.
You'll have to enable these features through Windows Features which is located under Programs and Features in the Control Panel.
In the Windows Features window, make sure the following options are ticked:
- Internet Information Services (you can also activate IIS 6 under Web Management Tools->IIS 6 Management Compatibility)
- ASP.NET (under World Wide Web Services->Application Development Features)

Use Web Platform Installer to install SQL Server and ASP.NET MVC
Microsoft Web Platform Installer is an awesome tool which will help you install programs, modules and much more related to .NET development. Use Web Platform Installer to install the following:
- SQL Server 2008 + SP1
- SQL Server Management Studio Express
- ASP.NET MVC
Once you've downloaded and installed Web Platform Installer, activate the features under the Web Platform tab:

The installer will automatically download and install all your selected features. Gone are the days with meaningless steps in the SQL Server installation process!
Mind, you can also choose to install a whole lot of other features, but I recommend you to save them for later.
Install Visual Studio 2008 + SP1
Final step is to install Visual Studio 2008 and Service Pack 1.
Once this is done, you should be set and everything should be fine.
If problems occur
If you encounter any problems, it's always a good shot to use your search engine to find anything related to the problem.
I tried a lot of different solutions though and no solution helped me - a clean installation and the above installation flow solved my problems.
If you've been looking for an ASP.NET Twitter module, look no further. I've coded a C# module in order to consume a given Twitter feed. Download the Twitter module for easy use in your own project.
How to use
You can either show the latest Twitter message or any given number of Twitter messages with this module - all you have to do is to point out a Twitter username and the number of messages to show.
Here's a code example on how you can show 5 Twitter messages in a Repeater.
Code-behind:
string userName = "dileno";
List<TwitterFeed> messages = TwitterFeed.Fetch(userName, 5);
if (messages.Count>0)
{
rptTwitterMessages.DataSource = messages;
rptTwitterMessages.DataBind();
}
Repeater in code-front (aspx/ascx):
<asp:Repeater ID="rptTwitterMessages" runat="server">
<HeaderTemplate><ul></HeaderTemplate>
<FooterTemplate></ul></FooterTemplate>
<ItemTemplate><li><%#((TwitterFeed)Container.DataItem).Message %> (<a href="<%#((TwitterFeed)Container.DataItem).Link %>"><%#((TwitterFeed)Container.DataItem).PubDate %></a>)</li></ItemTemplate>
</asp:Repeater>
Download the Twitter module
You can download the C# module with complete source code and code examples:
(zip, 16 kB)
Short instructions for implementation
- Drop the TwitterFeed.cs file into your project.
- Use the code in Default.aspx.cs to customize the Twitter messages.
- Update your appSettings.Config with the key TwitterFeedUrl, which you find in this project's appSettings.Config file.
Using different locales
When I developed this blog, I wanted to use the en-GB locale to be able to present correct formats for dates and numbers.
It is simple to set a specific locale for a whole web application - you just have to add the <globalization> tag under <system.web> in Web.Config and set the culture and uiCulture attributes, like this:
<globalization culture="en-gb" uiCulture="en-gb"/>
So far - so good. Dates and numbers have the correct format and everything looks well - until in comes the database.
I use Sweden's best web hosting provider (according to a study published in 2009) and this means the SQL Server database's collation is set to Finnish_Swedish_CI_AS - as it should be.
Having a website and a database with different locales gives you problems. Trust me.
Out-of-range datetime value
The main problem I ran into was a database insert of an incorrect date - the date I tried to insert obviously had an en-GB format while my database expected a date with sv-SE format. This generated an out-of-range datetime value error.
At first, I tried rewriting the date to a correct format, but quickly realized it was wrong to do so. I ended up with one of the two correct solutions for this problem.
Solutions
The two solutions are:
- Update database collation to match your website locale
- Update SQL query to use parameters
I ended up with the latter one - updating my SQL query to use paremeters instead.
This is also how you want to insert and update your database tables - by using parameters with your command object (unless you use any ORM solution like NHibernate, but that's another blog post).
Here's a SQL query where parameters are used (disregard the lousy error handling):
string strSQL = "INSERT INTO mytable(user,password) VALUES(@user,@password)";
SqlConnection objConn = new SqlConnection(connString);
SqlCommand objCmd = new SqlCommand(strSQL, objConn);
objCmd.Parameters.AddWithValue("@user", "username");
objCmd.Parameters.AddWithValue("@password", "secretpassword");
try
{
objConn.Open();
objCmd.ExecuteNonQuery();
}
catch { }
finally
{
objConn.Close();
}
Conclusion
When developing a database driven website, make sure you know the website's locale and the database's collation. Also, use parameters with your SQL queries, not only when dealing with dates and numbers, but always. You don't know what input might try to sneak into the database otherwise.
The DataBinder.Eval method is often used when you want to bind data to a control's template. What DataBinder.Eval really does is to cast Container.DataItem to its specific type, like this:
<%# DataBinder.Eval(Container.DataItem, "Heading") %>
DataBinder.Eval uses .NET reflection in order to cast Container.DataItem to its specific type. The use of reflection in this method will give you a performance loss.
If performance is of importance in your application or if you know what type Container.DataItem is, it's better to use an explicit cast instead:
<%# ((DbDataRecord)Container.DataItem)["Heading"] %>