In my previous two articles describing my writing a no-framework ASP.NET file, I described how ASP.NET handles encoding and how a
.aspx file should be structured.
In my third article, I will discuss how we can make code reuseable.
Making code reusable in classic ASP, PHP, etc.
Here, I will use the example that I showed in my second article and discuss how we could reuse the
In PHP, you reuse code by placing it in a separate file and using the
import method to include it into all the files where you want to use it.
You can use this (and variants like
require) to reuse libraries, or reuse HTML fragments (i.e. common headers and footers of the pages in the website).
In classic ASP, you use the
include syntax to the same effect.
ASP.NET is different. There isn’t a single method to reuse code but instead there are several ways that each have its own intended use-cases. Coming from a PHP background, it was quite confusing; I didn’t know which method I should be using. This article give you a good idea of the options that you have.
The important thing is that ASP.NET makes the distinction between what kind of code you intend to reuse. If you are going to reuse libraries which contains functions, then you should put them in App_Code. On the other hand, if you want to reuse HTML fragments, then you should use user controls.
The App_Code must be created at the root of you web site. All files in this directory or any subdirectories that have the extension
.cs will be treated as Virtual Basic or C# files respectively.
The code in App_Code will be available in every ASP.NET file that is in this application. Hence this is the ideal location to store libraries. In our case, it’s a good place to define the
The downside to AppCode is that the files are pure Visual Basic or C#. This means that if you can’t simply write HTML code in the files. You have to generate them as strings (and there is no HEREDOC syntax in Visual Basic either). Hence, the AppCode folder are not a good place to put “partials”; large fragments of reusable HTML code.
For our example, we create the following
link.vb file in the App_Code directory.
Imports Microsoft.VisualBasic Imports System.Net Imports System.IO Private Function urlEncodeUtf8(myString As String) As String urlEncodeUtf8 = HttpUtility.UrlEncode(myString, new System.Text.UTF8Encoding) End Function Public Function link(label As String, endpoint As String, query As String(,)) as String Dim tuples As New ArrayList() Dim i As Integer For i = LBound(query) To UBound(query) tuples.Add(query(i, 0) & "=" & urlEncodeUtf8(query(i, 1))) Next Dim href As String = "http://api.example.com/api.php?ep=" & endpoint & "&" & Join(tuples.ToArray(), "&") link = "<a>" & label + "</a>" End Function
Then then we simply use the
link function as we did in our previous article.
Reusing HTML fragments
Another way to reuse code in ASP.NET is User Controls.
Instead of putting
link function in the App_Code directory, let’s see how we use reuse it with User Controls.
To implement the
link function using User Controls, we would create the following control
link.ascx file and place it in a “Controls” directory that we create at the root of the web site. Unlike the “AppCode” directory which always has to be at the root-level of the web site and named exactly “AppCode”, the location and name of the “Controls” directory is arbitrary because we specify the file path whenever we use our controls.
' code for "~Controlslink.ascs" ' Public label As String Public endpoint As String Public query As String(,) Protected href As String Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) link(label, endpoint, query) End Sub Private Function urlEncodeUtf8(myString As String) As String urlEncodeUtf8 = HttpUtility.UrlEncode(myString, new System.Text.UTF8Encoding) End Function Public Sub link(label As String, endpoint As String, query As String(,)) as String Dim tuples As New ArrayList() Dim i As Integer For i = LBound(query) To UBound(query) tuples.Add(query(i, 0) & "=" & urlEncodeUtf8(query(i, 1))) Next href = "http://api.example.com/api.php?ep=" & endpoint & "&" & Join(tuples.ToArray(), "&") End Function <a href=""></a>
Then, to use this control in a page, we would do the following;
src attribute of the
Register directive declares where the source code for the user control exists (“~Controlslink.ascx” where “~” indicates the root level of the web site).
TagName are used to define the name of the tag we will use for this control. This tag indicates where the user control will be inserted.
is where the link is going to be inserted in the resulting HTML. You can see that we are providing the
label and the
endpoint values using attributes. Notice that in
endpoint are defined as public accessible attributes in the
link.ascs user control.
Ideally, we would like to send value for the
query attribute to the user control in the same manner. However, it is not possible to send complex values as attributes. You have to do this programmatically on the user control object which is available as the
link_1 variable (specified in the
id attribute of the
tag). That’s why we set the value of
link_1.query on a separate line and not inside the
This code example illustrates the strengths and the weaknesses of user controls. User controls are good if you have a lot of HTML that you want to output because you can simply write down the HTML in the
.ascx file. They are also good if the values that you want to pass in are simple. Hence they are ideal for header and footer fragments on your web page.
On the other hand, our example simply the weaknesses of user controls. The link example outputs only a short fragment of HTML, so the strengths of User Controls are not being used. On the other hand, passing in complex values is cumbersome, so User Controls are not a good idea if you need to do a lot of this.
If your intention was to reuse large fragments of HTML, user controls would definitely be the way to go.
Summary of the whole project
In my series “Writing No-Framework ASP.NET”, I wrote about my experience in writing simple ASP.NET code to add a few features to otherwise static HTML files.
Coming from a PHP background, these were the things to look out for;
- ASP.NET will do charset encoding and decoding in the background. Make sure that it doesn’t meddle with your encodings in a way that you don’t expect it to.
- ASP.NET forces you to put different parts of your code in different places. Know where you should put your function definitions and your string output statements.
- Passing complex arguments to functions in a terse way is not common in most code examples that you can find. Compared to PHP, Ruby, etc., it can be downright ugly. It is possible to make it acceptable though.
- There are different ways to reuse code based on whether you want to share libraries or whether you want to share HTML fragments. This can be confusing.
In closing, I would like to review an occasion where this No-Framework approach would be necessary. A typical case would be the following;
- The original website is build with static HTML and is hosted on IIS.
- The IIS server is run with default settings by a cautious administrator. The most we can do is persuade him to activate ASP.NET or ASP. We cannot persuade him to install non-Microsoft extensions like PHP.
- We only need to add some simple code to pre-existing static HTML pages to make them easier to manage, or to pull-in some content from an API.
- After setting the code up, the web-designer will edit the file more frequently than you do, using an editor that is completely out of your control. The encoding of the file and the encoding of the output is their decision, not the programmers.
- Maybe we need some simple single-page stuff like contact forms.
- You, the programmer, mostly spend your time in PHP, Ruby, Python and other cool web languages. You’re worried that even if you managed to learn enough ASP.NET to use webform postbacks, you’ll forget how to do it in half-a-year. You don’t want to use postbacks. You want to write code that resembles PHP code.
I’m sure that this is quite a common situation but I couldn’t find web sites that guided me through the steps. I hope that this series will help others in a similar situation.