Custom web controls for your ASP.NET application are a brilliant way to separate, reuse and “refactor” your code pieces. In that sense I consider myself to be a control freak and that's a good thing!

In our product Headlight we use a lot of create flows (here’s an example) that are built using tables with 3 columns. The two first are somewhat static text and the third can be any kind of HTML and ASP.NET controls.

 

It’s a pretty standard way of building create flows and it works even better with custom controls. This is the code used to create the table above:

<%@ Register Namespace="CustomControls" TagPrefix="cc" %>

 

<cc:CreateFlow runat="server" ID="createflow">

 

  <cc:CreateFlowItem runat="server" Title="Country" Description="Select your country.">

    <asp:DropDownList runat="server" ID="dd1">

      <asp:ListItem Text="-- Select country --" />

    </asp:DropDownList>

  </cc:CreateFlowItem>

 

  <cc:CreateFlowItem runat="server" Title="Upload image" Description="Add an image of yourself.">

    <input type="file" />

  </cc:CreateFlowItem>

 

  <cc:CreateFlowItem runat="server" Title="Text" Description="This is simple text.">

    Simple text

  </cc:CreateFlowItem> 

</cc:CreateFlow>

You can also add create flow items programmatically like the following example where a hyperlink is added:

CreateFlowItem item = new CreateFlowItem();

item.Title = "Website";

item.Description = "Some hyperlink";

 

HtmlAnchor a = new HtmlAnchor();

a.InnerHtml = "Hyperlink";

a.HRef = "#";

item.Controls.Add(a);

 

createflow.Controls.Add(item);

That’s a pretty easy and uniform way of building them and the best part is, that when something is changed, it applies to all the different create flows – and we use a lot of them. Even though it is not the exact implementation we use in Headlight, it is very similar but also simpler.

This is the source code for the CreateFlow and CreateFlowItem. Just put it in the App_Code folder or a custom control assembly if you prefer.

Download

CreateFlowTemplate.zip (0,52 KB)

After reading a post on The Cafes about the lack of dynamics in the CSS language, I found myself inspired to do something about it. It became clear that something had to be done and that we couldn’t wait for the W3C to come up with a new standard and browser vendors to incorporate them.

There were two things I wanted to enrich the CSS language with:

  • Variables
  • Scripting

To make it work, I created an HttpHandler for ASP.NET that is able to parse these two new features and apply them to the stylesheet. It does not interfere with any CSS standards because everything is handled by the server.

Here is an example of a .css file that uses these new capabilities.

define BACKCOLOR = #00FFFF;

define FORECOLOR = pink;

define TOTALWIDTH = 550;

define RIGHTWIDTH = browser == "IE" & version >= 6 ? "150px" : "170px";

define LEFTWIDTH = TOTALWIDTH / 2 + "px";

 

body{

  background-color: BACKCOLOR;

  color: FORECOLOR;

  width: TOTALWIDTHpx;

}

 

#RightColumn{

  width: RIGHTWIDTH;

}

 

#LeftColumn{

  width: LEFTWIDTH;
}

This will then be outputted as this standard compliant stylesheet:

body{

  background-color: #00FFFF;

  color: pink;

  width: 550;

}

 

#RightColumn{

  width: 150px;

}

 

#LeftColumn{

  width: 275px;

}

All the lines beginning with "define" will be treated as a variable declaration, parsed and then deleted from the parsed stylesheet. Notice the two variable names "browser" and "version". Those two variables are built in properties that return the browser name and major version number respectively.

The scripting syntax is 100% C# because it is compiled by the CodeDom into C# code in-memory. No new syntax of any kind is invented. The reason to use C# and not VB.NET is that developers or designers writing stylesheets probably also know JavaScript which also uses the C style syntax like C#. So, if you are comfortable writing JavaScript, it should be no problem to add scripting to the new CSS variables.

Remember, like JavaScript, these features are case-sensitive. However, that is not why the variable names are upper cased, I just thought it makes sense to let them stick out from the rest of the styles.

Implementation

There are two versions of the HttpHandler – one to use if you can control the IIS and one if you can’t.

If you are able to let the IIS send .css files to the ASP.NET engine you should download the CssHandler.cs file below and add it to the App_Code folder and then add the following to the web.config:

<httpHandlers>

  <add type="CssHandler" verb="*" path="*.css" />
</httpHandlers>

If you can’t access the IIS, you need to download the CssHandler.ashx below and then call that file while passing the .css file as a query string in the URL like this:

<link rel="stylesheet" type="text/css" href="csshandler.ashx?path=style.css" />

Total feature list

This is the total feature list of the handler:

  • Add variables to CSS (feature)
  • Use scripting capabilities (feature)
  • Server and client side caching (performance)
  • Cache dependant of the source .css file (performance)
  • Whitespace and comment removal (performance)
  • Works only on .css files (security)
  • Blocks the System namespace (security)

Word of caution

Because the scripting language is pure C#, it also means that you have to take injection attacks into account. I’ve already made sure that any scripting using anything in the System namespace will be rejected. That means that you can’t use any System.File.IO commands or anything else that has the word “System.” in it. That eliminate probably 99% of the obvious attack surface, but it is not totally secure.

Download

CssHandler (.cs - for IIS access).zip (1,96 KB)
CssHandler (.ashx - for non IIS access).zip (1,91 KB)