04

12/10

Weaning Yourself Off of Visual Studio (Part 3)

00:00 by rleahy. Filed under: Technology

Link to part 1
Link to part 2

This is the third and final part of my series on how to not use Visual Studio.  Microsoft does a pretty good job abstracting the creation of boilerplate code away from you with Visual Studio, to the point that it’s fully possible to create .NET applications (both desktop and web alike) without actually knowing anything about this boilerplate code, or what it does.

As far as I’m concerned, knowing about this code, how to write it, and what it does, and being therefore able to not use Visual Studio should the need arise, enriches your understanding of the .NET Framework, and ultimately makes you a better .NET developer.

Today I’m going to talk about ASP.NET, and how to create ASP.NET pages without using Visual Studio.

The first important thing about creating ASP.NET pages that’s important to understand, is the idea of an “ASP.NET application“.  An ASP.NET application is a folder on the IIS web server that has been converted—by way of the IIS management MMC—into an application. Only within ASP.NET applications may ASP.NET pages et cetera run.  When using things like HttpServerUtility.MapPath() (referred to from within Pages etc. as “Server.MapPath()” due to the fact the HttpServerUtility of the current HttpContext is pointed to by the Server property of Pages), the root directory of the current application is referred to as “~” (i.e. tilde).

Each ASP.NET application has at least one important directory at its root: “bin“.  Within this directory, all *.dlls for the application must be placed.  You can put pages etc. in any subdirectory, any number of subdirectories deep, but anytime a page requires *.dlls these *.dlls must be in ~/bin/, where “~” is—again—the root of the application.  To elaborate, whenever a page—an *.aspx, for example—is compiled, it is linked to all the *.dlls in ~/bin/.

The above is important because you may wish to create *.dlls to use across multiple pages, and because code-behind files (i.e. *.aspx.cs) must be compiled to *.dlls and placed in ~/bin/ for their corresponding *.aspx to compile properly.

Depending on the complexity of the page that you’re creating, you’re going to be looking at one or more files.  The first file will be the *.aspx file, and the second will likely be a *.aspx.cs file (i.e. the code-behind file), and the others will likely by *.cs files that you create just to split things up nicely (this would be a good time to laugh in Java’s face because it doesn’t support partial classes (along with many other things…)).

You’ve probably gathered this from using Visual Studio, but just as a recap, the *.aspx file contains normal HTML (i.e. HTML, JavaScript, CSS, etc.) alongside ASP.NET mark-up, which is XML-style tags that begin with “asp:“—for controls—as well as tags beginning with “<%” and ending with “%>”—for directives and in-line code.

The first line of an *.aspx page should always be a directive which tells ASP.NET what kind of page it is.  Directives are contained by “<%@” and “%>“.  For *.aspxs this will—at minimum—look like this:

<%@ Page Language="C#" %>

And if you’re doing anything remotely complicated, will likely look something like this:

<%@ Page Language="C#" AutoEventWireUp="true" CodeBehind="example.aspx.cs" Inherits="examplepage" %>

Each of these attributes does something different:

  • Page – Tells ASP.NET that this is a page.  Some other options here are “Handler” and “MasterPage“.
  • Language – Tells ASP.NET what language this page’s code blocks will be written in.  Can be “C#” or “VB“.
  • AutoEventWireUp – Allows you to handle events with specific naming conventions.  Such as a function Page_Load for when the page is loaded.  Not really necessary, but could be useful.  This is—and should be—set to “false” when working in Visual Studio, since Visual Studio automatically wires events itself (through automatically-generated designer code), and does not need the Framework wiring the events up again.
  • CodeBehind – Specifies the name of the code-behind file.
  • Inherits – Specifies what class the page inherits from.  More on this later.

Using what I’ve already told you, you can already create ASP.NET pages that do simple things, using in-line code using “<% [...] %>“.

This, for example, is an ASP.NET page which, when saved as a *.aspx and placed on an IIS web server in an application, will display “Hello, world!” (original, I know):

<%@ Page Language="C#" %>
<html>
    <head>
        <title>Hello, world!</title>
    </head>
    <body>
        <%    Response.Write("Hello, world!");    %>
    </body>
</html>

But this isn’t too useful. In order to write bigger, better, and more complicated pages etc., we’re going to want to separate the *.aspx and the code. We already know how to point an *.aspx at a code behind file, and specify what it inherits from, let’s discover how that all fits together.

The first thing to understand, is the idea of “Inherits“.  This is literal—the code infront page doesn’t represent an extension of the class it “Inherits“, it very literally inherits from that class. This is important because it means that methods etc. that you want exposed to the code infront page are going to have to be protected, not private (if you aren’t an accessibility level Nazi like me, and just make everything public, then you need not worry yourself over this detail).

Once you understand this, you need to understand that supplying the “Inherits” directive doesn’t make the page start inheriting from something, it makes it inherit from something other than the default.  By default pages inherit from System.Web.UI.Page, so when writing your code behind file, you need to make the class you define inherit from this.

Another thing to understand, is that if you want to access controls from the code behind file, they need to be declared—if you root around, you’ll find that Visual Studio does this in its designer code file.  Their name needs to be the same as the “id” tag in their ASP.NET markup—best practice is to declare them as protected.  If you don’t need to access them from the code behind, you don’t need to declare them (or even give them an “id” tag for that matter).

As long as a method in the code-behind is protected or public, you can access it from in-line code in the code infront file just as you would any other function (useful for cutting long in-line code blocks down—just turn them into one method call and put the rest of the code in the method in the code behind file).

Once you’re done with your code-behind file, use csc.exe to compile it to a *.dll, and put it in ~/bin/.  If you don’t do this, the Framework won’t be able to find the class your *.aspx inherits from, and will become angry.

If you want to see how it all works, I wrote a “URL Lengthener” for fun last night (it’s takes those annoying bit.ly, etc. links and tells you where they really point by following the trail of 3xx codes) using the methods I’ve outlined in these part few articles (i.e. not using VS):

As usual, copyleft (on the source), et cetera.

01

12/10

ASHX

00:00 by rleahy. Filed under: Technology
Tags: , ,

The thing that I love most about ASP.NET is the fact that it’s very clean, very well-organized, and gives you exceptional control over the web server.

Working closely with the web server—ending the current response, sending a redirect, transferring seamlessly to a different page, sending a custom HTTP status code, et cetera—is so easy and seamless with ASP.NET that I often take it for granted, and am mortified when I somehow wind up coding PHP:

Yes, it looks like that.

The problem with a lot of these useful methods linked above is the fact that they’re seemingly quick and easy, but are actually woefully inefficient.  If you prematurely end the processing of an *.aspx, ASP.NET accomplishes this by throwing an exception, which bubbles up through the stack and is eventually caught—it is obviously not of the type to bubble all the way up and cause a 500.  If you know anything about exception generation/handling, you know that exceptions have a sizeable overhead.  Not to say that they should be avoided, merely that they’re not good for all situations—specifically, the situation of ending an HTTP response prematurely.  Imagine—for example—socket programming without exceptions.  Inversely, imagine if a StreamReader threw an exception—rather than returning null—when you called ReadLine and there was nothing to read.

Bottom line: There’s a time and a place for everything—including exceptions.  Conventional “should I use an exception?” logic dictates that ending an HTTP response is not a place for an exception.

The narrow use case of ending a response prematurely aside, there are many things that you want to do programmatically with the power of ASP.NET which don’t require the ridiculous number of features you get from a PagePages are extremely robust, and have a lot of features and flexibility, but features and flexibility come with a trade off—i.e. overhead.

So what about when you want something lightweight to see if a user is authenticated before allowing him to access a page?  It’s bad HCI to just wantonly throw 4xx status codes in the user’s face, but if the user is going out of his or her way to request pages that require a login when he’s not logged in, it’s not such a bad idea—why waste server processing time/bandwidth generating and sending him actual HTML?  However, generating the abstraction of a Page just to destroy it without actually using any of it except for the PreInit event doesn’t really make sense, does it?

Fortunately, there’s a way around this: *.ashx files.

An *.ashx file is an ASP.NET HTTP handler file, and contains code that is used to process—or pre-process, depending on your use of it—an HTTP connection.  The interface that all *.ashx files implement—IHttpHandler—contains only one method—ProcessRequest—which is called when the *.ashx file is requested.  This single method takes as an argument an HttpContext, which allows you to perform all of the granular manipulation you can in an *.aspx page without the associated overhead.  In fact, an *.ashx page is up to 10 times as fast as an *.aspx (assuming, of course, you were using the *.aspx for something which the paradigm was not intended for, as discussed above).

The other advantage to this is that since all the page’s processing is done in one method—rather than in a bunch of functions pointed to by a bunch of delegates and called as events happen—there’s no need for a “kill switch” like Response.End().  You need only to use structured programming techniques to make these conditions which would otherwise require a call to Response.End() fall to the end of the function, and you’ve accomplished the goal of skipping further processing and ending the response without any messy exception throwing/catching down within the Framework.

21

11/10

Referrer Harvesting For ASP.NET

23:17 by rleahy. Filed under: Technology

So I’m happy that I can now see who’s linking to my blog—whether they use PingBacks et cetera or not—which got me thinking that it’d be somewhat cool to do the same thing for my homepage, which is written in ASP.NET.

So here’s code that does exactly the same thing as the PHP code I posted in my last blog post, except with ASP.NET (and C#):

try {

    if (Request.UrlReferrer!=null) {

        Response.Write(
            "<div class=\"categorybox\">You were linked to here from <a href=\""+
            Request.UrlReferrer.ToString()+
            "\">here</a>.</div>"
        );

        Boolean exists=false;
        using (System.IO.StreamReader read=new System.IO.StreamReader(
            new System.IO.FileStream(
                System.IO.Path.Combine(
                    Server.MapPath(null),
                    "referrerlist.txt"
                ),
                System.IO.FileMode.OpenOrCreate,
                System.IO.FileAccess.Read,
                System.IO.FileShare.Read
            )
        )) {

            String holdthis;
            while ((holdthis=read.ReadLine())!=null) {

                if (Request.UrlReferrer.Host==holdthis) {

                    exists=true;
                    break;

                }

            }

        }

        if (!exists) {

            using (System.IO.StreamWriter write=new System.IO.StreamWriter(
                new System.IO.FileStream(
                    System.IO.Path.Combine(
                        Server.MapPath(null),
                        "referrerlist.txt"
                    ),
                    System.IO.FileMode.Append,
                    System.IO.FileAccess.Write,
                    System.IO.FileShare.None
                )
            )) {

                write.WriteLine(Request.UrlReferrer.Host);

            }

            System.Net.Mail.SmtpClient mail=new System.Net.Mail.SmtpClient("192.168.50.4",25);
            mail.Send(
                "noreply@rleahy.ca",
                "rleahy@rleahy.ca",
                "Your Website Has Been Linked To",
                "The domain "+
                    Request.UrlReferrer.Host+
                    " has started linking to your site from "+
                    Request.UrlReferrer.ToString()+
                    "."
            );

        }

    }

} catch { }

Since .NET’s SmtpClient doesn’t pull from a configuration file–unlike PHP’s mail, which pulls SMTP settings from php.ini—there are few more “fill in the blanks” as opposed to yesterday:

  • Your SMTP server’s IP/hostname.
  • Your SMTP server’s port.
  • The from address for your server.
  • The to address (just like the PHP script).

If you want to be a real keener—or if it just fits in with your application—you can replace these “blanks” with calls to ConfigurationManager.AppSettings and store all of that in your web.config file.

Other than that, just put it between <% and %> anywhere in your *.aspx file, and you’re set.

If your environment uses authentication or SSL for SMTP, read the SmtpClient documentation and adjust the mailer portion accordingly.

Afterthought: This is the first blog post I’ve made before midnight…what a night owl I am…

20

11/10

mod_mono Installation Instructions

03:09 by rleahy. Filed under: Technology

So, for this Linux Systems Administration course I’m currently taking, we had the pleasure (?) of choosing a “project” and doing it on Linux servers that we’d been carefully building, adding to, and maintaining throughout the term.

I—being an unashamed M$ fanboy—chose to install and configure mono, XSP, and mod_mono.

Turns out that this was a bad idea.  Then again, being that it’s Linux we’re dealing with, what wouldn’t've been a bad idea?  Being like half the class and just typing yum install webmin?

No…that’s just not how I roll…

Anyway, we were making a wiki, so I couldn’t just install and then configure, and then tinker and tinker until it was just right, and then call it a day, which has pretty much been my approach with all the labs so far.  I had to get the installation and configuration down to a science.  So it makes a good blog post to save other souls from my 3 hour ordeal.

That’s right.  3 hours to make Linux do something Windows Server 2008 R2 does just by adding the IIS “feature“.  But that’s to be expected—it’s Linux.

Anyway.  You’ll find a lot of tutorials on-line which give you horribly convoluted information on how to get mono/mod_mono installed and working.  Being that they’re horribly convoluted, they’re not of much help.  I’m pretty sure they’re the result of people taking the approach I spoke of, and then trying to convert that into instructions…

…which doesn’t go so well.

So you’re going to want to install mono itself—and all its components—on CentOS (which is what we’re using) this is yum groupinstall mono.

Then you’re going to want to get XSP.  If you’re using CentOS this is yum install xsp.  Be careful if you’ve installed the mono repos, however, when you try and yum install xsp, the CentOS repos will feed you a CentOS version, and the mono repos will try and feed you the RHEL version, and then you’ll have two versions, and it won’t work at all—first-hand experience talking here—so for the love of your sanity, be pro-active using yum list to see if there are two packages, and then just use yum install with the specific one that’s suited to you.

Last, you need mod_mono itself.  If you’re using CentOS this is yum install mod_mono.  The advisory from above still applies.

Now that you’re got everything installed, you’re ready to configure.

You’re probably expecting me to launch into lines and lines of things copy pasted from httpd.conf, but that’s just not how I roll.

I’m going to give you the link that saved my ass (that’s it right there).  After 2 hours getting mod_mono working (albeit barely), I got in my head to tinker with it (this usually happens to me…I’m too curious for my own good) and wound up somehow, mysteriously, breaking it.  Then it was another hour (or an hour-and-a-half…time just melts away while you’re fighting with Linux) going back through all those horribly convoluted instructions, which wound up all being bunk in the end.

So use the link, and don’t read those other instructions.

Oh, and don’t forget to restart Apache after you do your configuration.

There’s the proof.