Cyber Security & Dot Net Security

Thursday, November 25, 2010

ASP.NET 404 ERROR PAGE - How to Configure Error 404 Page in ASPX (.NET) for IIS Server?

Error 404 Page
My previous post explained about How to create Error 404 page in asp. This method will work out for all extensions except ASPX files. In ASPX (.NET) these files pass through special parser which instead outputs a .NET error. If we want the .NET application redirect to custom Error 404 page, We have to edit our web.config file in the root of the website.


Open your Web.config file, present in the root of the site. If you do not have a web.config file create one. Copy and paste the following in the file.






<configuration>
<system.web>
<customErrors mode="On">
<error statusCode="404" redirect="/errors/error404page.aspx" />
</customErrors>
</system.web>
</configuration>



With the use of the above code we are instructing the .NET application to turn on custom errors and for 404 response code we redirect to a specific virtual page.



In the ASPX page, error404page.aspx, copy the following code to display to the user when a HTTP 404 error occurs:


<%@ Page Language="VB" runat="server" explicit="true" strict="true" %>
<%@ Register TagPrefix="UserControl" TagName="Header" Src="head.ascx" %>
<%@ Register TagPrefix="UserControl" TagName="Footer" Src="tail.ascx" %>
<%@ Import Namespace="System.Web.Mail" %>
<script language="vb" runat="server">
Sub Page_Load()
'-- Get Query from the URL
Dim strQuery As String = Request.ServerVariables("QUERY_STRING")
'-- avoid running our code if someone browses
' the 404.aspx file directly
If strQuery <> "" Then
'-- Page with the broken link
Dim strReferer As String = Request.ServerVariables("HTTP_REFERER")
'-- remove the default appended string to the url
strQuery = strQuery.Replace("404;http://", "")
'-- Find the position of the root "/" in the string
Dim intSlashPosition As Integer = strQuery.IndexOf("/")
'-- Remove all text before the "/"
strQuery = strQuery.Remove(0, intSlashPosition)
'-- set the label control's text
lblQueryString.Text = strQuery
'-- Send Email to the Webmaster
Dim objMail As New MailMessage()
Dim strEmailBody As String
strEmailBody = "Seo-Insights - 404 Page Not Found : " & DateTime.Now & "<br>" & "------------------------------------------------------" & "<br>" & "<br>"
If strReferer = "" Then strEmailBody = strEmailBody & "Someone typed in this broken link directly:" & "<br>" Else strEmailBody = strEmailBody & "The page <a href=""" & strReferer & """>" & strReferer & "</a> contains a broken link:" & "<br>"
End If
strEmailBody = strEmailBody & "<br>" & strQuery
'-- change the FROM and TO emails for your site
objMail.From = "webuser@example.com"
objMail.To = "administrator@example.com"
objMail.Subject = "Seo-Insights - 404 Page Not Found"
objMail.Priority = MailPriority.High
objMail.BodyFormat = MailFormat.Html
objMail.Body = strEmailBody
SmtpMail.SmtpServer = ""
SmtpMail.Send(objMail)
'-- strQuery = ""
Else
'-- switch panel displays to display the error
' when a user simply navigates to this file
pnlValid404.Visible = False
pnlNotValid404.Visible = True
End If
End Sub
</script>
<html>
<head>
<meta name="robots" content="noindex,nofollow">
<title>Seo-Insights - 404 Page Not
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
</head>
<body bgcolor="#FFFFFF">
<UserControl:Header runat="server" />
<h2>Page Not Found (404 Error)</h2>
<asp:panel id="pnlValid404" runat="server">
<p><asp:label id="lblQueryString" runat="server" ForeColor="#FF0000" /> could not be located.<p>
<p>An email has been sent to the webmaster about this problem, and action will be taken to fix it.</p>
</asp:panel>
<asp:panel id="pnlNotValid404" runat="server" Visible="False">
<p>This page works only as a redirect when an ASPX page is not found.</p>
</asp:panel>
<UserControl:Footer id="myFooter" runat="server" />
</body>
</html>



Note that 2 UserControls are registered to include the header and footer, to have the same look and feel of the site. Import the System.Web.Mail namespace so we can send an email to our webmaster.



When the page loads, we can track the broken link from the URL which had triggered the error404page. When a redirect to the 404 page happens, the server appends the broken link to the error404page.



For example if the broken link was /missedpage.aspx, we can track that through Request.ServerVariables("QUERY_STRING"). If the query is empty, probably it means the user found the missedpage on our site and browsed to it. In this case we do not want to run our code. All the code is nested inside the condition that the strQuery is not empty.



To inform the webmaster about the broken links in the site, an email will be send to the webmaster. The label control with ID lblQueryString outputs the strQuery from our code. And finally, the two panels switch content depending on what we want to show to the user. The pnlNotValid404 is set to not visible be default since this is our error display, and we only set it to visible if one occurs.

Thursday, November 18, 2010

Structuring a Web Page with CSS and ASP.NET

Introduction

Here we will go back to the basics and explore the finer points of structuring a web page.   We will review some of the evolution of HTML and explore the reasoning behind some of these advances.   We will explore those limitations at each step in the evolution that lead to the innovations for the next.   Finally we will describe the steps to structure a web page that it will
  • Be easy to maintain
  • Comply with standards  and best-practices,
  • meet accessibility requirements
  • support search engine optimization (SEO)

From Hyperlinks to Tables to Style sheets to Master Pages

In the beginning, HTML was devised purely as a means of displaying  content, but there was no control over the layout.   You could make text bold, italicized, or underlined.   You could make links, lists, and headers.   In the early 1990s that was all you could do. 
Then there were tables.    Tables allowed you to control the way that content was positioned on a page.   With tables, you could line up elements and you could structure content in to columns.   You could specify all sorts of details that had nothing to do with the content itself.   This started the beginning of HTML bloat.   Soon, there was more page markup that had nothing to do with the content than there was actual content.   This created a high “signal to noise ratio” for most web pages.
I was as guilty as any were of nesting tables to get the desired look.   When your design relies on as many as eight levels of nested tables, more markup code is being used for layout and format than is being used for content.  
Style sheets were introduced to help reduce the noise.   With style sheets, all markup related to formatting can easily be moved from the page.   This makes the content easier to find and edit.   Style sheets also help make our pages more standards compliant, more easily maintained, and help bring the focus back to the content.   Style sheets will also help us resolve some of the problems that came about with tables.   The positioning and layout tricks that many people use tables for can be done much more cleanly and simply with style sheets.
Style sheets solve many problems, but they are not yet universally adopted.    They also have a reputation for being more voodoo art than science.   As a result, programmers often shy away from them.    But fear not, they can be mastered or at least tamed and used for good.
Master pages were introduced to help improve consistency across a web application.    “Master page” is perhaps a bit of a misnomer.  A better name may have been page templates.   The master page provides a template for how a page should look and provides content sections where individual page’s content should go.   Master pages make it easier to have consistency across the pages in a site.   Individual pages need only contain  that page’s specific content.  All structural markup code is in the master page.  All common markup code is in the master page.  
Content that is common across several pages can be defined once in a common master page.   Items such as the header, footer, sidebar, etc can be defined in the master page and then are visible in every page using that master page.  Each individual page will be easier to create because there are fewer items to worry about.  By pushing common functionality and appearance to the master page, individual pages are easier to implement because they only have to focus on how they are different from the rest.  By pushing all formatting and layout directives from the individual pages to the style sheets, we will have dramatically less markup in our individual pages.   Because the same style sheet can be reused throughout the site, less webpage markup will need to be delivered down to the client.   The reused style sheet needs to be downloaded only once and not once for each page in your site.   This will improve load times, improve band width concerns, and lower hosting costs.

So What is Wrong with Tables?

We mentioned earlier in this article that many of the advancements in HTML have come about as a response to try and eliminate tables from our markup. So what is wrong with the use of tables?  Making the case against tables is not always easy.   They seem so natural and are so easy to understand that their problems are easily missed and not well understand.
HTML tables allow you to think of your page as a grid.   It seems so easy to think about your page as simply adding content to this grid.   The problem is that this grid has nothing to do with the content on your page.   The tables require a substantial amount of markup without providing any extra value.   This means that more data has to be transferred for your page to render properly.  Your pages will load more slowly.   Your bandwidth requirements will go up, and you get no added value for these extra hurdles.     
This extra markup also gets in the way of automated (‘bot’) processes that need to understand your page.    Search engines have to filter through meaningless table syntax to retrieve the content.   Search engines will have more difficulty ranking your pages.   The most common things that your page discusses may appear to be table data and table rows instead of the true content.   Browsers that read the content to the viewer will get bogged down in meaningless details that are entailed in trying to understand the maze of table data.   Mobile browsers will struggle with  the process of rendering your page for alternate formats.   Mobile browsers cannot easily render your page for optimal viewing because of the table definitions.    Web browsers on widescreen monitors cannot adapt to take advantage of the extra space and hardware resources available.
The browser needs to render the page in the best way to take advantage of the wide screens and to adapt to small screens. To perform well in this,  the goal is a page that has fluid design.   Fluid design is difficult under the best circumstances.  It is even harder with tables. 

Best Practices

With the exception of Master Pages, everything we will discuss here applies equally well regardless of your platform. These best practices and refactors all apply whether you are using ASP.Net, JSP, PHP, etc. Each platform provides its own mechanism for page templates. If you are not familiar with your platform’s solution, investigate it. You will be glad you did.
So what is the best way to structure our pages? How do we know that our structure is good? How do we improve upon what we have done in the past?
‘Refactoring’ code is a disciplined approach for changing existing code by modifying its internal structure without changing the external behavior. Refacoring includes techniques for brining code it in line with the best practices. The concept of refactoring html is a rather new discipline, but there is much that we can we adopt from the code-refactoring literature. Let’s borrow the term ‘smell’ to describe markup that may render satisfactorily but requires improvement. Some “Mark up Smells” with associated ‘refactors’ to consider include
Table Smell
·         Replace Table with Style sheet positioning
·         Replace Table with Explicit Width
Embedded Styling
·         Move Style Sheet to External Style Sheet
Embedded Formatting
·         Extract attributes to Style Sheet
Embedded Positioning
·         Replace Positioning with Style Sheet
Duplicate Markup
·         Move Redundant Markup to Master Page
·         Move Redundant Markup to User Control
Like code smells, markup smells imply that there may be a problem in your markup.   Every time, you see one of these smells does not necessarily mean that you have a problem, but you do have something that needs to be investigated.

Table Smell

If you see one table tag in you markup, there is probably not too much to worry about.    If you see nested tables, you start smelly markup that needs to be cleaned up.   You also need to be aware of why tables are being used.   If the table is being used to display columns of data, you have a good use for your table.   If your table is being used solely to put a border around a particular section, your table can easily be replaced with style sheet directives.    If your table is being used to line up or structure content, it is time to consider streamlining your markup.    Adding an explicit width to your style sheet classes will often suffice to make everything line up without having to resort to wrapping content in tables.

Embedded Styling

Sometimes you will find a style sheet embedded directly in a page.   This is easy to spot, if your mark up includes a style tag; you have an Embedded Styling smell.   We may often embed the style sheet to make quick changes or to test a new style.  We may also create an embedded style sheet as an intermediate step in “Extract attributes to Style Sheet” or “Replace Positioning with Style Sheet”.   Embedding the style sheet streamlines the testing, but the last step needs to be “Move Style Sheet to External Style Sheet”.   Even if this is a style sheet that only the one page will reference, move it to a separate file.    This will keep all of the style directives together and result in cleaner markup code.
It is also important to view your page in various web browsers and at various resolutions and on various devices.   If your page does not render well in a particular browser then you may be relying on browser specific markup.   If your page does not render well on a smart phone or on a wide screen monitor, then you are probably using rigid constructions and need to move towards a more fluid design.

Embedded Formatting

Embedded formatting occurs whenever you have formatting directives embedded directly in the element tags.    This could be a style attribute on any element.   This could also be a width attribute, any attribute specifying color, an align attribute, or any of the background attributes.   The first step in cleaning up this smell is to extract these attributes to an internal style sheet and then move that style sheet to an external style sheet.

Embedded Positioning

The most common source of embedded positioning is using tables, but other practices are common.    For example, you can easily create a very brittle layout with absolute positioning.    When you see elements with style attributes that include left or top directives or a position directive with a value of absolute, you are relying on embedded positioning and it will lead to problems. 
Tables are also used to explicitly provide formatting details.   The problem here lies in the extra markup needed to make the positioning work.  

Where Do We Go From Here?


Consider a basic page layout like the one here.    We have a header, footer, sidebar  navigation, and a main content area.    This can be defined in a Master Page and every page will easily share this common structure.

<body>
    <form id="form1" runat="server">
    <div id="container">
        <div id="header">
            <h4>Web Application Name</h4>
        </div>
        <div id="content">
          <asp:ScriptManager ID="script" runat="server">
          </asp:ScriptManager>
          <asp:ContentPlaceHolder ID="cphContent" runat="server">
          </asp:ContentPlaceHolder>
          <asp:ValidationSummary ID="valSummary" runat="server"             
            DisplayMode="BulletList" />
        </div>
        <div id="sidePanel">
            <asp:ContentPlaceHolder ID="cphLeftNavigation" runat="server">
            </asp:ContentPlaceHolder>
        </div>
        <div id="footer">
            <p>Common Footer Content</p>
            <asp:ContentPlaceHolder ID="cphFooter" runat="server">
            </asp:ContentPlaceHolder>
        </div>
    </div>
    </form>
</body>
There are a couple of things worth emphasizing here.   First, there are no tables.    There are no formatting directives, and there are no positioning directives.   Everything here is pure content.   Note also that the main structural elements have an explicit ID attribute specified.   Structural elements that can occur only once should be styled with an ID selector in the style sheet to further reinforce that the style directives are applicable for only a single element.  
Also, you will have noticed the content place holders.  These provide the configuration points where individual pages can provide custom content.   In the markup provided, individual pages cannot alter the header.   They can provide custom footer content but not override the common footer content.   The individual pages have complete control over the content for the Content Area and the Side Bar area but do not need to worry about styling or positioning these structures.
The master page also includes the Script Manager and defines a Validation Summary control.   These are elements that every page will most likely need.   By defining these elements in the master page, the individual pages do not need to define them.  
The layout and positioning for these structural elements may look similar to this:
#container
{
      width: 673px;
      border: solid 1px black;
      margin: 0px auto;
}

#header
{
      color: #FFFFFF;
      width: 221px;     height: 100px;
      background-color: #778CB3;
}
#sidePanel
{
      width: 213px;     height: 372px;
      margin-top: 5px;
      background-color: #778CB3;
      color: #FFFFFF;   padding: 4px;
}
#content
{
      width: 446px;     float: right;
      height: 380px;    margin-top: 5px;
      background-color: #A0AFCB;
}
#footer
{
      background-color: #F7CB33;
      padding: 12px;    width: 649px;
      color: #000000; font-size: 90%;
      text-align: center;     clear: both;
      border-top: 5px solid #FFFFFF;
}
This is a suggestion rather than a best-practice.  There are arguments to be made for using pixels, points or ’ems’ in specifying absolute lengths or widths.   The color choices are definitely a matter of preference.
The important thing to note here is that all formatting and positioning directives are isolated to the style sheet.   This has two important implications.  
  1. As a developer, you don’t need to worry about them.  
  2. The design process can be completed separately, without needing to access your individual pages.
You can now simplify development and maintenance by separating responsibilities.    If you have several people working on different parts of the project at the same time, they won’t be stepping on each other’s toes.  Even if you alone are responsible for a site in its entirety, you will benefit from this separation of responsibilities.    While working on the content, you can ignore the presentation directives, and while working on the formatting, you don’t have to get bogged down in the presentation details.

What About an Input Form?


Typically a simple input form such as the one illustrated above may be build using markup similar to this:
        <table>
            <tr>
                <td>
                    <label>Label</label>
                </td>
                <td>
                    <asp:TextBox ID="txtBox" runat="server"></asp:TextBox>
                </td>
            </tr>
            <tr>
                <td>
                    <label>Another Label</label>
                </td>
                <td>
                    <asp:TextBox ID="txtAnotherTextBox"
                      runat="server"></asp:TextBox>
                </td>
            </tr>
            <tr>
                <td>&nbsp;</td>
                <td align = "right" >
                    <asp:Button ID="btnOK" runat="server" Text = "OK" />
                </td>
            </tr>
        </table>
With just a little bit of formatting, this will look exactly like the image above, so what is wrong with it?
The first problem is the extra markup.    The table and table data elements serve no value other than to add extra markup to the page.    The other problem is the rigidity.    What has to change to go from the image shown initially to this image?

Such layout changes are often more common than you would expect, and nearly every line of the html markup using a table for layout will have to change.     There are additional problems, but these two alone should be enough to cast doubt on the virtues of using a table for positioning.
The following markup can be used to accommodate both looks.   All that has to change is a couple of changes to the style sheet.
<div class="workArea">
    <p>
        <label>Label</label>
        <asp:TextBox ID="txtBox1" runat="server"></asp:TextBox>
    </p>
    <p>
        <label>Another Label</label>
        <asp:TextBox ID="txtAnotherTextBox1" runat="server"></asp:TextBox>
    </p>
    <p>
        <asp:Button ID="btnOK" runat="server" Text="OK"  
            CssClass="commandButton" /></p>
</div>
With this markup, a style sheet similar to this will render the first image:
label
{
    display: inline-block;
    width: 10em;
}
.commandButton
{
    float: right;
}
.workArea
{
    width: 350px;
    border-top: solid 1px silver;
    border-left: solid 1px silver;
    border-right: solid 1px black;
    border-bottom: solid 1px black;
}
Simply change the style sheet to this and get the second image:
label
{
    display: block;
    width: 10em;
}
.commandButton
{
    float: right;
}
 p
{
    margin-top: 0px;
    margin-bottom: 0px;
    display:inline-block;
    width : 170px;

}
.workArea
{
    width: 350px;
    border-top: solid 1px silver;
    border-left: solid 1px silver;
    border-right: solid 1px black;
    border-bottom: solid 1px black;
}
The transformation happens by displaying the label in a block and displaying the paragraphs as an inline block.    This simple model can be extended to let the browser dynamically show as many columns of input control as the current screen resolution should reasonably support.

A Simple Custom Sql Membership Provider

The benefits of using Microsoft's new Membership Provider, and an explanation of how to configure and use them, are well documented on MSDN (http://msdn2.microsoft.com/en-us/library/yh26yfzy(VS.80).aspx).  Certainly the Sql Membership Provider, in conjunction with the suite .Net controls, does a great job providing everything needed for creating and managing user accounts for a common web application.  But sometimes your needs may be a little outside of what can be configured or coded using the Provider as is.  Fortunately, extending the provider is a very straightforward task.

I recently implemented a .Net 2.0 website using many of the providers, including Membership, Role, and Profile.  While the Membership Provider gave us industry standard security "for free", the requirements dictated that a few features needed to be changed.  One of those features was the passwords that are automatically created when using the Password Reset button.  By default, the provider creates a string of characters that is long and contains non-alphanumeric values.  Even cutting and pasting these into the browser becomes difficult (not to mention confusing) when the first character of your new password is a ":" (colon).  My requirements called for a simple string of letters and numbers, preferably 10 characters in length.  Despite the numerous configuration options available, this functionality was nowhere to be found.
The solution involved creating a CustomSqlMembershipProvider class that inherited from the existing SqlMembershipProvider to do most of the heavy lifting. 
 Below is the code that provides configurable length Password Reset function that contains only numbers and lowercase letters, leaving out ambiguous characters to avoid confusion.
 Some things to note...
  • Inherit from SqlMembershipProvider to gain access to the base implementation.
  • Read any custom config entries in the Initialize override method, but be sure to remove those entries as the base provider will not recognize them and will throw an exception.
  • Be sure to call base.Initialize to trigger the default implementation.
Hope this helps!


 
public class MembershipProvider : SqlMembershipProvider
{
    System.Random rnd;
    string[] characters;
    const int DefaultResetPasswordLength = 10;
    private int ResetPasswordLength;

    public MembershipProvider()
    {
        rnd = new Random();
        characters = FillCharacters();
    }

    public override void Initialize(string name,
        System.Collections.Specialized.NameValueCollection config)
    {
        ResetPasswordLength = DefaultResetPasswordLength;
        string ResetPasswordLengthConfig = config["resetPasswordLength"];

        if (ResetPasswordLengthConfig != null)
        {
            // Have to remove the config entry as the provider we are
            // inheriting from doesn't understand it and will throw an
            // exception
            config.Remove("resetPasswordLength");

            if (!int.TryParse(ResetPasswordLengthConfig,
                out ResetPasswordLength))
            {
                // Have to reset to default as TryParse will set it to 0
                // if the value can't be parsed
                ResetPasswordLength = DefaultResetPasswordLength;
            }
        }
        base.Initialize(name, config);
    }

    // Create a more user friendly password to avoid confusion when
    // trying to key in the new value
    public override string GeneratePassword()
    {
        string newPassword = string.Empty;
        for (int i = 0; i < ResetPasswordLength; i++)
        {
            newPassword += GetRandomAlphaNumericCharacter();
        }
        return newPassword;
    }

    /// <summary>
    /// Create an array of characters to user for password reset.
    /// Exclude confusing or ambiguous characters such as 1 0 l o i
    /// </summary>
    /// <returns></returns>
    private string[] FillCharacters()
    {
        string[] characters = new string[31];
        characters[0] = "2";
        characters[1] = "3";
        characters[2] = "4";
        characters[3] = "5";
        characters[4] = "6";
        characters[5] = "7";
        characters[6] = "8";
        characters[7] = "9";
        characters[8] = "a";
        characters[9] = "b";
        characters[10] = "c";
        characters[11] = "d";
        characters[12] = "e";
        characters[13] = "f";
        characters[14] = "g";
        characters[15] = "h";
        characters[16] = "j";
        characters[17] = "k";
        characters[18] = "m";
        characters[19] = "n";
        characters[20] = "p";
        characters[21] = "q";
        characters[22] = "r";
        characters[23] = "s";
        characters[24] = "t";
        characters[25] = "u";
        characters[26] = "v";
        characters[27] = "w";
        characters[28] = "x";
        characters[29] = "y";
        characters[30] = "z";
        return characters;
    }

    private string GetRandomAlphaNumericCharacter()
    {
        return characters[rnd.Next(characters.GetUpperBound(0))];
    }
}