About Me

"I love being the underdog"

Anthony DeSalvo

Dad, Husband, Roller Derby Widow, Triathlete, Web Developer and RCRD Volunteer!

301 Moved Permanently - Redirecting URLs with C# / ASP.NET

by adesalvo 26. May 2007 01:45

I recently attended the 7 Secrets to High Google Rankings seminar at the RMSC. The seminar was sponsored by the AMA Rochester chapter and was presented by Stephan Spencer, President of Netconcepts.

Stephen gave an excellent presentation of seven SEO concepts to better optimize a web site. One of the ones that really stuck out for me was the 301 Redirect. A 301 Redirect is a search engine friendly way to move pages without forfeiting hard earned search engine placement. Redirecting your Domain foo.com to www.foo.com is also a common use for a 301 redirection. What makes a 301 important is it merges all your searched and indexed pages into one domain, thus increasing your PageRank.

After the seminar I went back and tested one of the corporate sites I manage using a 301 redirect checker only to find out that I was not using this SEO method.

Below is the code I used to implement the 301 Redirect. I know there are many ways to do this, DNS, URL_REWRITE, etc, but the easiest most controlling method was to use code. This would allow me to manage from a CMS what domains will be redirected and where. There is a future business requirement to internationalize the site using different languages and domains. Another requirement was to maintain the state of the Query String. Below is the c# code I placed on a web control that is present on every page of the site. A more optimal way to implement this would be to extend the System.Web.UI.UserControl on every page and overide the page_load event to containg the below code.

protected void Page_Load(object sender, EventArgs e)

      /* 301 redirect with query string support.*/

      string c_absUri = Request.Url.DnsSafeHost;
      string c_absPath = Request.Url.AbsolutePath;

      // shorthand to set query string value
      string c_queryString = Request.QueryString.ToString().Length > 0 
             ? Request.QueryString.ToString() : String.Empty;

      //Only Redirect if Doain is not int he NoRedirect List
      if (!isNoRedirectUrl(c_absUri))
          // eventualy I would create a hash to lookup 
          //the redirect instead of hardcoding it
          string newUrl = "http://www.foo.com" + c_absPath;

          //is querystring is not empty Append to redirect url
          if (!c_queryString.Equals(string.Empty))
              //add query string
              newUrl += "?" + c_queryString;

          Response.Status = "301 Moved Permanently";


  public static bool isNoRedirectUrl(string Url)
      // This could be an externally managed list - CMS maybe?
      string[,] a_noRedirectUrl = new string[,] {

      bool isNoRedirectUrl = false;
      foreach (string s in a_noRedirectUrl)
          if (Url.Contains(s))
              isNoRedirectUrl = true;

      return isNoRedirectUrl;


Tags: , , ,


Ajax , Gridviews and Hover Menu Extenders ohh my!!

by adesalvo 12. April 2007 23:05

A few months ago I was designing a custom CMS for my current employer. The system will primarily be used to manage there retail products and all the attributes that relate to them. EX: color, size, retail location, etc.

In the current system these attributes, like any poorly manage application, have spun out of control. The only way to clean up these attributes was for me to write some custom SQL and pass the results off to marketing to mark up, correct and send back to my intern to make the SQL changes.

To avoid this tedious task (I like my interns), I decided to build in a viewable/clickable relationship between each attribute and its products in the new CMS. Considering its user base, I wanted to make it as easy as possible to view this parent child relationship.

Initially we just added a VIEW button embedded in the gridviews that would take you to a page that lists which products relate to it’s clicked attribute. From there you could click again to manage a specific product within the list. This wasn’t an optimal solution but solved the problem.

While looking at the page I thought an embedded hoverMenuExtender control that popped up another gridview of each of the attributes related products would allow for a faster and easier workflow for managing products and attributes.

So below is the code that I developed. It’s strictly asp.net no codeBehinds, using the business logic DAL pattern for the Data Access as well as generics.

<asp:ObjectDataSource ID="odsFeatures" runat="server" OnSelected="ObjectDataSource1_FeatureSelected"
OnDeleted="ObjectDataSource1_FeatureDeleted" UpdateMethod="UpdateFeature" InsertMethod="InsertFearure"
DeleteMethod="DeleteFeature" DataObjectTypeName="com.safes.Feature" TypeName="com.safes.FeatureDAL"

<asp:ControlParameter ControlID="ddlCategories" Name="categoryID" PropertyName="SelectedValue"
Type="Int32" />

<asp:GridView ID="GridView2" runat="server" Width="100%" CssClass="smallCopy" DataSourceID="odsFeatures"
AutoGenerateColumns="False" DataKeyNames="FeatureId">

<asp:CommandField ButtonType="Button" ItemStyle-Width="95" ShowEditButton="True"
ShowDeleteButton="True" ControlStyle-CssClass="cmsButton" CausesValidation="false" />

<asp:BoundField DataField="Name" ItemStyle-Width="600" ControlStyle-Width="600" HeaderText="Name"
SortExpression="Name" />

<asp:TemplateField HeaderStyle-HorizontalAlign="Center" ItemStyle-HorizontalAlign="Center"

<asp:Panel ID="pnlFeatureTarget" runat="server">
<asp:Button ID="btnFeatureView" CausesValidation="false" OnClientClick="return false;"
ToolTip='<%# Eval("FeatureId") %>
' Text='View' CssClass="cmsSelectButton" runat="server" /></asp:Panel>
<ajaxToolkit:HoverMenuExtender ID="hmeFeature" runat="Server" HoverCssClass="popupHover"
PopupControlID="pnlFeatureView" PopupPosition="Left" TargetControlID="pnlFeatureTarget"
PopDelay="100" />

<asp:ObjectDataSource ID="ObjectDataSource4" runat="server" SelectMethod="getSafesByFeatureId"

<asp:ControlParameter ControlID="btnfeatureView" Name="FeatureId" PropertyName="tooltip"
Type="Int32" />

<asp:Panel ID="pnlFeatureView" runat="server" CssClass="popupControl">
<asp:GridView EmptyDataText="No Safes Found" EmptyDataRowStyle-BackColor="#EEEEEE"
EmptyDataRowStyle-ForeColor="black" EmptyDataRowStyle-CssClass="smallCopy" ID="FeatureGridView2"
runat="server" AutoGenerateColumns="False" DataSourceID="ObjectDataSource4" CssClass="smallCopy cmsAlignRight"
Width="0" BorderColor="#333333" BorderStyle="Solid" BorderWidth="1px" CellPadding="3"

<asp:HyperLinkField DataTextField="ModelNo" HeaderText="Model" SortExpression="ModelNo"
ItemStyle-HorizontalAlign="center" DataNavigateUrlFields="ModelNo" DataNavigateUrlFormatString="editSafeRedirect.aspx?m={0}" />

<RowStyle BackColor="#EEEEEE" ForeColor="Black" />
<SelectedRowStyle BackColor="Gray" Font-Bold="True" ForeColor="White" />
<PagerStyle BackColor="#999999" ForeColor="Black" HorizontalAlign="Center" />
<HeaderStyle BackColor="#D23127" Font-Bold="True" ForeColor="White" CssClass="mediumCopy" />
<AlternatingRowStyle BackColor="Gainsboro" />
<RowStyle BackColor="#EEEEEE" ForeColor="Black" />
<SelectedRowStyle BackColor="Gray" Font-Bold="True" ForeColor="White" />
<PagerStyle BackColor="#999999" ForeColor="Black" HorizontalAlign="Center" />
<HeaderStyle BackColor="#D23127" Font-Bold="True" ForeColor="White" CssClass="mediumCopy" />
<AlternatingRowStyle BackColor="Gainsboro" />

Below is a screen shot of the final rendered product. As you can see you can select a feature and get its attributes, and from there you can hover over the view button on the attribute to see what products belong to its respected attribute. I also added a link to the product for easy editing.

One of the things I struggled with was how to set the select selectparameters of the hovering objectdatasource/gridview. What I ended up doing is setting the tooltip parameter of the button to the featuredID of the attribute. Then I referenced the tooltip parameter using the controlParamter. From there I could write a custom query to get the products associated with the attribute.

Tags: , ,