|
 Friday, February 02, 2007

Force HTTPS on all requests, HttpModule

 Sometimes we have websites that are strictly HTTPS. No files whatsoever are served up through HTTP. We want our users to only access the HTTPS portion of our website but we dont want them to remember "https://" blah blah blah. Honestly, who really wants to type all of that anyway? No one. We want our users to type www.example.com and then we want the site to redirect to the local https site. I've found a few sites out there that have some very robust SSL transition handlers, this one especially , but it was just way too much for what I needed to do. I needed something simple. So I started thinking...

There are a couple ways to do this.

Force SSL through IIS.


But this wouldnt be the desired method because if the user typed in http://www.example.com/ they would be presented with a page that states this site requires SSL. We want it to redirect. Also, this means that if I move my site to another server I have to update configuration on the IIS site as well as any settings in my web.config. Mo-hassles, mo-problems, yuck.

Redirect Page
We could also leave one page not requiring SSL and execute the following code in Page_Load

// Redirect to HTTPS Site
Response.Redirect("https://www.example.com");

That works, but what if a user has a bookmark to a special part of the site such as: http://www.example.com/examplefolder/example.aspx  ??
This method would get bypassed and the user could easily access the page without SSL Encryption.

Http Module
This is the method I decided to go with.

The code implements the IHttpModule interface. Inside of the Init method we attach to the Application.BeginRequest event and then we let the handler decide what to do with the page. If the page is using a secure connection then we dont do anything with the request. If they are not using a secure connection, the code replaces the Uri scheme with "https" and then performs a redirect.

using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;

/// <summary>
/// Redirects a request to the HTTPS site.
/// </summary>
public class RedirectToHttpsModule : IHttpModule
{
#region Constants

private const string HTTPS = "https";

#endregion

#region IHttpModule Members

public void IHttpModule.Dispose()
{
// Nothing to dispose.
}

public void IHttpModule.Init(HttpApplication context)
{
context.BeginRequest += new EventHandler(context_BeginRequest);
}

void context_BeginRequest(object sender, EventArgs e)
{
HttpApplication application = sender as HttpApplication;
if (!application.Request.IsSecureConnection)
{
// Grabs the current scheme, http, and replaces with https and redirects.
application.Response.Redirect(application.Request.Url.ToString().Replace(application.Request.Url.Scheme, HTTPS));
}
}

#endregion
}



Implementation
Download the RedirectToHttpsModule.cs file below and place it into the App_Code directory located in the root of your website.
Then add the following to your system.web configuration section of your web.config file.

<httpModules>
<add type="RedirectToHttpsModule" name="RedirectToHttpsModule" />
</httpModules>

Now, each request made to your site will be pushed to https.


RedirectToHttpsModule.zip (.57 KB)
#    Comments [0] |

Prototype/Proof of Concept code is not production code!

One thing that should be burned into the heads of many developers is that Prototype/Proof of Concept (PoC) code is NOT production code. Proof of Concept code is not production code.

Prototype code is, more or less, proof of concept. When you create a prototype or PoC, it’s something that can be shown to the client to create a common understanding of what is to be delivered. Now, some people will disagree with this, but … after the client agrees to this prototype/PoC this code should only be saved for reference. It should only be referenced to ensure the client is getting what they received. It should be compared to the final app to make sure it works in the same order.

When creating Prototype/PoC the goal is to save money. It helps set its viability, expose any technical issues and express any concern over any direction of the system. Feedback can be implemented quite easily at this point. This allows the developer and business analyst to quickly identify the noted issues without incurring a high overhead of development costs.

Once the Prototype/PoC is agreed upon, the development on the prototype ceases and the design phase of the new system should begin. Under NO circumstance should the prototype be taken and converted into the actual production site. Will you take snippets of code here and there? Yes, will you grab a piece of JavaScript from the client code you created for the prototype? Yes. Will you use the entire project as your production code? No.

The reason for this is simple; prototype code is ugly, messy, and nasty. It’s a conglomerate of blog posts, mixed with MSDN How-To articles, mixed with hacks and riddled with bugs. The code in these types of projects contain code that is far from anything pretty. The code would take longer to clean up than it would to take to write it from a fresh slate.

#    Comments [0] |
 Monday, January 29, 2007

The "as" Keyword

Last week I ran into a problem with the 'as' keyword in C#. For those of you who dont know, the "as" keyword works like this:

Lets say I have a variable and I'm certain its a string, but its in the form of an object (for whatever weird reason, perhaps you're getting it out of an ArrayList or something). I want to cast it to string. I can use the "as" keyword to do this.

string stuff = objectVariable as string;



So I had a problem this week when a co-worker wrote some code that did the following:

// Get variable from session
string myId = Session["objectKey"] as string;


Each time I accessed this variable (myId) it was null. WTF? I debugged for a second and I verfied that it was being set like so:

// Save Id for later
Session["objectKey"] = theIdToSave;


The variable "theIdToSave" was set to, lets say, a number, 5. Session saves everything as an object. The "as" keyword is a shorthand version of the tenary operator,  therefore...

string stuff = objectVariable as string;

//Is the same as

objectVariable is string ? (string)objectVariable : (string)null;


The problem was that we were putting a Int32 type into an object and trying to cast it to a string. This will only work if, and only if, it was of type string. Unfortunately it was not a string, it was of type Int32. Thefore, instead of raising an exception, the "as" keyword returns a null value. The type of the object in session can be verified by reflecting into the object by using the GetType method.

// This will return: {Name = "Int32" FullName = "System.Int32"}    
Session["Test"].GetType();

Keep in mind, when working with the "as" keyword in C#, be sure to know what types your working with. If you're trying to cast a variable to a type that it is not of, the "as" keyword will internally yield a null value instead of raising an exception.


#    Comments [0] |
 Wednesday, January 17, 2007

New Lines

Lines are represented differently in different operating systems. For most non Unix Platforms the new line is represented as: "\r\n" And for Unix Platforms the new line is represented as: "\n" I've found that most developers will hard code these values into their code, for example:

string someText = String.Format("This is a line1.{0} This is line 2.", @"\n");

That works, but there is a built in property in the .NET Framework to retrieve the current platforms New Line. This property is Environment.NewLine. Here's an example, using the same code above, but with Environment.NewLine in place of the hardcoded value.

string someText = String.Format("This is a line1.{0} This is line 2.", Environment.NewLine);

This property will return the new line string defined for the environment that the application is running in.

#    Comments [0] |
 Sunday, January 14, 2007

Escaping String Literals

I've been looking through a lot of "hand me down code" (code that was written awhile ago by someone else) that did a lot of File IO. The code works well, but at times its hard to read the really long file paths that they're using. As you know, file paths in C# have to be escaped, otherwise the compiler will think that you're trying to escape a character. So a double backslash actually equates to a single backslash when compiled. This can be cleaned up a bit. Read on brethern...

This is how the file paths look now:

// Current File Paths
string path = "c:\\directory\\folder1\\folder2\\folder3\\somefile.txt";

To make this cleaner, use the "@" symbol at the beginning of the string literal and it will escape the characters for you.

// New File Path
string path = @"c:\directory\folder1\folder2\folder3\somefile.txt";

Simple, but a lot of programmers dont know this little time saver.

NOTE: using the @ symbol when you need to included \t or \r, \n will not work. It will interepret the characters just as they are "\n" will print on the screen as "\n" not the new line that you're probably expecting.

#    Comments [0] |