How to Build SEO friendly Website In Asp.net

in #utopian-io7 years ago (edited)

What Will I Learn?

You will learn Building SEO friendly Website In Asp.net

Requirements

  1. ASP.Net Core
  2. .NET Framework
  3. Visual Studio
  4. Northwind DB

Difficulty

Intermediate

Tutorial Contents

  1. Search Engine Friendly URL Routing
  2. URL mapping and URL re-writing
  3. Introducing URL routing
  4. Exemplifying URL routing

How to Build SEO friendly Website In Asp.net

In this tutorial, we are going to mainly explore the SEO related goodies introduced in ASP.NET.

NOTE

The sample test environments in this article involve:

  • ASP.Net Core
  • .NET Framework
  • Visual Studio
  • Northwind DB

As is known, ASP.NET has introduced a couple of more effective features and powerful enhancements than the existing versions. Especially, towards optimizing your site for SEO, the following new runtime features are added:

  • URL Routing support towards ASP.NET Web Forms
  • MetaKeywords and MetaDescription, of the Page class
  • Response.RedirectPermanent() method

Let's next detail into the implementations of these SEO friendly functionalities.

Search Engine Friendly URL Routing

Search engine friendly URL routing means creating URLs that are more friendly and descriptive. With the new introduction of System.Web.Routing namespace in ASP.NET, this is no more a daunting and tedious task. Dozens of a bit ugly URLs built up with querystring in previous ASP.NET versions can now be converted meaningful and descriptive in Web Forms, which will not only be easy to remember but also will improve the search engine rank.

In some situations, you might want to have several URLs lead to the same page. This might be the case for a number of reasons - maybe you want to implement your logic in one page and use query string arguments but still provide shorter and easier-to-remember URLs to your website users (often called friendly URLs). Or maybe you have renamed a page, but you want to keep the old URL functional so it doesn't break user bookmarks. Although web servers sometimes provide this type of functionality, ASP.NET includes its own URL mapping feature.

NOTE

Ever since the birth of ASP.NET MVC, it has taken into account the routing optimization problem. So, the URL routing in this article mainly dwells upon ASP.NET Webforms.

About URL mapping and URL re-writing

Before the introduction of the new routing capabilities, it's necessary for you to have an idea of URL mapping and URL re-writing.

1- URL mapping

The basic idea behind ASP.NET URL mapping is that you map a request URL to a different URL. The mapping rules are stored in the web.config file, and they're applied before any other processing takes place.

We should define URL mapping in the section of the web.config file. And also, we need supply two pieces of information - the request URL (as the attribute url) and the new destination URL (mappedUrl). Here's an example:

<?xml version="1.0" ?>
<configuration>
  <system.web>
    <urlMappings enabled="true">
      <add
          url="~/Category.aspx"
          mappedUrl="~/Default.aspx?category=default" />
      <add
          url="~/Autos.aspx"
          mappedUrl="~/Default.aspx?category=autos" />
      <add
          url="~/Games.aspx"
          mappedUrl="~/Default.aspx?category=games" />
      <add
          url="~/Health.aspx"
          mappedUrl="~/Default.aspx?category=health" />
      <add
          url="~/News.aspx"
          mappedUrl="~/Default.aspx?category=news" />
    </urlMappings>
  </system.web>
</configuration>

2- URL re-writing

Before the introduction of the new routing capabilities, URL re-writing was typically used to redirect users from friendly (display) URL to a handler.

To perform URL rewriting, you are suggested to follow these steps:

  1. Download the URL Rewriting Engine by visiting the Microsoft Web site

  2. Run the MSDNURLRewriting.msi file. Some source code files will be installed.

  3. Open the URLRewriter solution in Visual Studio, and then build the solution. The URLRewriter.dll file is generated in the debug folder.

  4. Create a new Web application project, and then add to your project a reference to the URLRewriter.dll file.

  5. Modify the Web.config file to set up URL rewriting. For example, you can set up URL rewriting by adding the following tags to the Web.config configuration file:

<configSections>
    <section name="RewriterConfig" type="URLRewriter.Config.RewriterConfigSerializerSectionHandler, URLRewriter" />
</configSections>
  <RewriterConfig>
    <Rules>
      <RewriterRule>
        <LookFor>~/Default.aspx</LookFor>
        <SendTo>~/SendToPage.aspx</SendTo>
      </RewriterRule>
    </Rules >
   </RewriterConfig>

For more details concerning URL mapping and URL re-writing, you can refer to MSDN. Let's next focus upon the new URL routing in ASP.NET.

Introducing URL routing

URL routing is a feature first introduced in ASP.NET SP1, which has been widely used by the ASP.NET MVC applications to render clean and SEO friendly "Web 2.0" URL. URL routing lets you configure an application to accept the request URL that does not map to a physical file. In another word, you can use the routing for users to define semantically more meaningful URLs, which finally helps to implement search engine optimization (SEO).

Using routing, developers can now easily eliminate long URL's and hide file extensions too (like .aspx). Another advantage of URL routing is that developers can now easily hide the physical path/location of web pages residing in the web server.

For example, a traditional Web page that displays product classification is URL might look like this:

http://www.mysite.com/products.aspx?category=software

Using the URL-driven engine in ASP.NET, you can now configure the application to accept this URL to display the same information:

http://www.mysite.com/products/software

What deserves noticing is that, in ASP.NET URL like the above can not only be mapped to the ASP.NET MVC Controller class, but also can be mapped to the ASP.NET Web Forms page. You can even have an application based upon both Web Forms and MVC controllers, using a single set of routing rules to achieve URL mapping between them.

Unlike URL mapping and URL re-writing, URL routing is not implemented in the web.config file. Instead, URL routing is implemented by coding. A typical URL routing solution in ASP.NET Web forms is define routes globally using the global.ascx file to register all the routes for your application.

Exemplifying URL routing

Now, let's build up a concrete example to show how to achieve the above-mentioned advantages via URL routing in ASP.NET.

1- Register the routes

To do this, please follow up the following steps:

(1) Start up Visual Studio to open the sample ASP.NET Web application AspNet_SEO_Gooides that targets the framework.

(2) Open up the global.ascx file and add a method that will register the routing table, as well as calling this method in the Application_Start method.

(3) Inside the global.ascx file, add a reference to System.Web.Routing and then register the routes inside the Application_Start method:

//others omitted...
using System.Web.Routing;
namespace AspNet4_SEO_Gooides
{
    public class Global : System.Web.HttpApplication
    {
        void Application_Start(object sender, EventArgs e)
        {
            RouteTable.Routes.MapPageRoute("CategoryRoute", "Category/{Name}", "~/ProductViewer.aspx");
        }
//...

In the above code, the first parameter CategoryRoute specifies the route name; the second parameter Category/{Name} denotes the url structure, here the url which starts /Category/{Name} (for instance: /Category/Beverages) will point physically to the following path ~/ ProductViewer.aspx.

NOTE

Notice in the above snippet, we used the simplest form. In fact, you can not only define the route and parameters, but also optional constraints for these parameters. As for more on this, please refer to MSDN.

Now, once we have our routes defined and registered, we need to create our form that will handle all requests that map to our specified route.

2- Create An Ajax-based Web form

In this case, we are going to create an ASP.NET Ajax based Web form named ProductViewer.aspx. We will leverage the mature ScriptManager + UpdatePanel controls to achieve a category selection based product viewer. Figure 1 indicates one of the running-time snapshots.

The Ajax-based sample page using URL routing in action

In the above figure, we use two ListView controls. The top one will output the product categories from table Categories; the bottom one will be used to output the related products corresponding to the category clicked from the top one. Both of the two ListView controls are enclosed with an UpdatePanel respectively. The most worth-noticing point here is when you move the mouse over any hyperlink a faked url, such as http://localhost:1284/Category/Beverages, will appear. This is just what users care for and the search engine is interested in. All this owes to the URL routing newly-introduced in ASP.NT.

Now, let's look more closely at the related programming. First is the main content of file ProductViewer.aspx (unimportant stuff is filtered out).

 <form id="form1" runat="server">
    <asp:ScriptManager ID="ScriptManager1" runat="server">
    </asp:ScriptManager>
    <asp:UpdatePanel ID="UpdatePanel2" runat="server" UpdateMode="Conditional">
    <ContentTemplate>
        <asp:ListView ID="lvCategoryList" runat="server" DataSourceID="SqlDataSourceCategory">
            <ItemTemplate>
                <li style="background-color: #E0FFFF;color: #333333;">
                     <a id="A1"
                       href="<%= ResolveUrl("~/Category/")%><%#Eval("CategoryName")%>">   <%# Eval("CategoryName")%></a>
                    <br />
                </li>
            </ItemTemplate>
        </asp:ListView>
    </ContentTemplate>
    </asp:UpdatePanel>
    <asp:SqlDataSource ID="SqlDataSourceCategory" runat="server" 
        ConnectionString="<%$ ConnectionStrings:ConnectionString %>" 
        SelectCommand="SELECT [CategoryID], [CategoryName] FROM [Categories]"></asp:SqlDataSource>
       <asp:sqldatasource id="SqlDataSourceProduct" runat="server" connectionstring="<%$ ConnectionStrings:ConnectionString %>"
            SelectCommand="SELECT Products.ProductName, Products.UnitPrice FROM Products INNER JOIN Categories ON Products.CategoryID = Categories.CategoryID WHERE  (Categories.CategoryName= @CategoryRoute)">
            <selectparameters>
              <asp:routeparameter name="CategoryRoute" RouteKey="Name"  />
            </selectparameters>
      </asp:sqldatasource>
        <asp:UpdateProgress ID="UpdateProgress1" runat="server" 
            AssociatedUpdatePanelID="UpdatePanel1">
        <ProgressTemplate>
            <table width="291">
                <tr>
                    <td style="width: 28px">
                        <img alt="imageplaceholder" src="Images/Loading1.gif" /></td>
                    <td style="width: 253px; color: red;">
                        Loading data...</td>
                </tr>
            </table>
        </ProgressTemplate>
        </asp:UpdateProgress>
      <asp:UpdatePanel ID="UpdatePanel1" runat="server" UpdateMode="Conditional">
          <ContentTemplate>
              <fieldset>
              <legend>Product List of Category (<asp:Label ID="lblRouteData" runat="server" text="<%$RouteValue:Name%>" ></asp:Label>)</legend>
             <asp:DataList ID="DataListProduct" runat="server" DataSourceID="SqlDataSourceProduct">
                <ItemTemplate >
                    Product Name:
                    <asp:Label ID="ProductNameLabel" runat="server" Text='<%# Eval("ProductName") %>' />
                       
                    UnitPrice:
                    <asp:Label ID="UnitPriceLabel" runat="server" Text='<%# Eval("UnitPrice") %>' /> <br />
                </ItemTemplate>
          </asp:DataList>
          </fieldset>
      </ContentTemplate>
    </asp:UpdatePanel>
    </form>
</body>
</html>

Although a bit lengthy, I believe most of the statements should not be strange to you. So, I don't want to address the Ajax related stuff, as well as the binding between SqlDataSource and ListView, but dwell upon the url routing related things. First, the most important statements lie in the following that forms the components in the ItemTemplate template of the ListView control:

<a id="A1"
   href="<%= ResolveUrl("~/Category/")%><%#Eval("CategoryName")%>">   <%# Eval("CategoryName")%></a>

To gain a better understanding with it, let's look into the final HTML code related to the above statement:

<a id="A1"   href="/Category/Beverages">   Beverages</a>
(html comment removed: ......others omitted)
<a id="A1"  href="/Category/Condiments">   Condiments</a>
(html comment removed: ......others omitted)

According to my dissection, the above may be the simplest form to dynamically apply the preceding url routing definition.

By the way, you may have found couples of forms like the following:

<asp:HyperLink
    NavigateUrl="<%$RouteUrl:RouteName=Contact_Details, id=1%>"
    runat="server">John Doe
</asp:HyperLink>

This, in fact, represents the simplest form of using url routing. The behind url resolution rests upon Expression Builders introduced in ASP.NET. This kind of sample bears a fatal shortcoming. The value of id is a constant. However, the practical cases often require dynamically generating the value of id. So, how about the form below?

<asp:HyperLink ID="HyperLink1" NavigateUrl='<%$ RouteUrl:RouteName=Weather, name=<%#Eval("id")%> %>' runat="server"><%# Eval("loc_text")%></asp:HyperLink>

The bold part above is just what we really want. But regrettably this won't work. As pointed out a moment ago, the form may be the shortest answer.

The second important point above may be the second SqlDataSource definition, as follows:

<asp:sqldatasource id="SqlDataSourceProduct" runat="server" connectionstring="<%$ ConnectionStrings:ConnectionString %>"
      SelectCommand="SELECT Products.ProductName, Products.UnitPrice FROM Products INNER JOIN Categories ON Products.CategoryID = Categories.CategoryID WHERE  (Categories.CategoryName= @CategoryRoute)">
      <selectparameters>
        <asp:routeparameter name="CategoryRoute" RouteKey="Name"  />
      </selectparameters>
</asp:sqldatasource>

Here, we use the RouteParameter object to supply the values for the query parameters. The value of the route URL parameter Name is passed to the query parameter @CategoryRoute, while CategoryRoute specifies the route name defined in the file Global.asax.cs.

At last, one disadvantage of the above solution is when the category contains the symbol "/", an HTTP error will be throw out at the running time. This is because the the symbol "/" conflicts with the url routing connection symbol "/". For this, to pass through the above test you should first modify the category name in the table Categories in the Northwind database. For instance, you can change the category from Grains/Cereals to Grains-Cereals. I've not tested Scott Mitchell's solution with this special case. Interested readers can take it as an exercise.

3- Retrieve URL routing data from a Page

As is seen above, url routing is frequently used in the case navigating from one page to another with some related parameters (early implementation typically rested on the querystring means which resulted in search engine unfriendly form). So, how can we receive route parameters from the source page? This is easy, as shown below.

protected void Page_Load(object sender, EventArgs e) 
{ 
//Using a loop to grab all the key-value-pairs that is accessible via 
//Page.RouteData.Values collection. 
foreach (KeyValuePair<string, object> kvp in Page.RouteData.Values) 
{ 
lblAllValues.Text += "Key: " + kvp.Key + " Value: " + kvp.Value + "<br />"; 
}
}

In the simple cases, grabbing the routing values using a loop might not be too useful. In fact, you can access them individually, like the following.

Int32 articleid = Convert.ToInt32(RouteData.Values["aid"]); 
string articlename = RouteData.Values["artname"].ToString(); 
}

However, in our case, we have not considered the above case – our sample interested things takes place only in one page, which owes to Ajax.

As implies previously, there are several forms of the method RouteTable.Routes.MapPageRoute. For more complex control over url routing, such as enforcing some constraints for the parameters, you can refer to MSDN.

NOTE

UrlRouting, relative to the Url rewriting, is a relatively new thing, Although url routing helps to achieve the bi-directional conversion in the direct and searching engine friendly form between the route setup side and the accepting side, it also has its own shortcomings. For example, when the domain name part is also required to be overridden, it may be rather difficult for url routing to accomplish this. In this case, you may have to fall back upon UrlRewrite.

Starting from the next section, we'll look into another simple yet good search engine friendly feature.

New MetaKeywords and MetaDescription Properties of the Page Class

ASP.NET introduces two new properties in the Page class, Keywords and Description, with which you can improve your search engine ranking. This is based upon a common sense that HTML meta elements can be used to improve search-engine listings. Hence, we can use the Keywords property to specify a bunch of keywords related to surfers' searching, while we can use another property Description of the Page class to specify a text that describes the corresponding keywords.

Note if there is no "keywords" meta element in the head element of the page markup, the meta element will be added to the page when the page is rendered. If the page markup already has a "keywords" meta element, the property Keywords can get or set the content attribute of the meta element.

In ASP.NET applications, we can achieve the above goal either in the behind-code programmatically or in the markup code declaratively. The code snippet below illustrates how you can achieve this programmatically:

protected void Page_Load(object sender, EventArgs e)
{
    Page.MetaKeywords = "asp.net,SEO";
    Page.MetaDescription = "This is an .net targeting site that hosts all kinds of .NET related tutorials.";
}

The above code will add the meta tags in the client-side HTML code, like the following:

<head>
<title>
</title>
<meta name="description" content="This is an .net targeting site that hosts all kinds of .NET related tutorials." />
<meta name="keywords" content="asp.net,SEO" />
</head>

And also, ASP.Net supports using the Page directive to define the Meta keywords and Description, as shown below.

<%@Page Language="C#" AutoEventWireup="true" 
CodeBehind="CodingSEOMeta.aspx.cs" 
MetaKeywords="asp.net,SEO" 
MetaDescription="This is an .net targeting site that hosts all kinds of .NET related tutorials." 
Inherits="AspNet4_SEO_Gooides.CodingSEOMeta" %>

The last point worth noticing is, if you set the above values programmatically they will override any values declaratively set in either the section or via the @Page attribute.

New RedirectPermanent and RedirectToRoutePermanent Method of the Response Class

Over long time most Web applications would move pages or related stuff here and there. This can probably result in accumulating stale links in search engines. Traditionally, ASP.NET developers do with requests to old URLs using the Response.Redirect method to forward a request to the new URL. Regrettably, this Redirect method issues an HTTP 302 Found response, which means requiring the client to perform a temporary redirect (the original describing phrase was "Moved Temporarily"). Many search engines like Google typically will not follow across multiple redirection hops; this means a temporary redirect will have negative impact upon your page ranking.

The recommendable solution in ASP.NET is using the newly-introduced RedirectPermanent or RedirectToRoutePermanent method of the Response class. In this way, an HTTP 301 Found will be issued as response. The 301 status code is used to indicate that a page has permanently moved. So, search engines like Google would assign the page rank of the old domain to the new redirected domain when it is redirected using this technique. If it is not done in this way then the old domain's page rank will be fully dropped and a new page rank will be assigned to your new site (with new domain name).

Using the method RedirectPermanent is simple, as follows:

Response.RedirectPermanent("/newpath/foroldcontent.aspx");

Let's look at a concrete example to look at the behind-scene action. First, add to the sample project AspNet_SEO_Gooides two Web forms, one named RedirectPermanentWebPage.aspx, and the other named NewWebForm.aspx.

Figure 2 below gives the design-time screenshot for page RedirectPermanentWebPage.aspx.

Figure 2: The simple design for page RedirectPermanentWebPage.aspx

The related behind code looks like this:

protected void btnRedirect_Click(object sender, EventArgs e)
{
    Response.RedirectPermanent("~/NewWebForm.aspx");
}

Another page NewWebForm.aspx only renders the following string:

Hello, this is a NEW Web Form!

Now, right click the page RedirectPermanentWebPage.aspx to select Firefox to browse it. After that, launch Firebug to observe what happens. Now click the button "Permanent Redirect to NewWebForm", then click the Net tab and through the hyperlink "view source" you will find something like the following figure.

Figure 3: Look into the permanent redirection using the Firebug addon

If you change the previous statement to the following:

protected void btnRedirect_Click(object sender, EventArgs e)
{
    //Response.RedirectPermanent("~/NewWebForm.aspx");
    Response.Redirect("~/NewWebForm.aspx");
}

You will find something like the following figure.

Figure 4: Temporary redirection captured via Firebug

Using another method RedirectToRoutePermanent is also easy, as follows:

//issue permanent HTTP 301 redirect to a named route
//form 1: redirect to a route that is named Products.
Response.RedirectToRoutePermanent("Products");
//form 2: redirect to a default route that has parameters that are named productid and category.
Response.RedirectToRoutePermanent(
  new { productid = "1", category = "widgets" });
//form 3: redirect to a route that is named Product and that has parameters that are named productid and category.
Response.RedirectToRoutePermanent("Product",
  new { productid = "1", category = "widgets" });
//form 4: redirect to a route that is named Product and that has parameters that are named productid and category.
Response.RedirectToRoutePermanent("Product",
  new RouteValueDictionary {productId="1", category="widgets"});

Together with new URL routing support, you can also utilize the above code in the Webforms case.

Search engines and other user agents that recognize permanent redirects will store the new URL that is associated with the content, which eliminates the unnecessary round trip made by the browser for temporary redirects.

The last point to remember is you can use the above routes and methods for both ASP.NET Web Forms and ASP.NET MVC based URLs.

Summary

Now that search engine becomes major source of traffic for a website, it is required to make the sites we develop search engine friendly as far as possibly. Thus, Microsoft provides some of the goodies within ASP.Net that can make our life easier to do search engine optimization of our ASP.NET website. However, the article only scratches a pinch of tons of ASP.NET goodies. In developing real ASP.NET applications, there are still a lot techniques concerning SEO to wait for your further digging into.



Posted on Utopian.io - Rewarding Open Source Contributors

Sort:  

Congratulations @bej! You have completed some achievement on Steemit and have been rewarded with new badge(s) :

Award for the total payout received

Click on any badge to view your own Board of Honor on SteemitBoard.

To support your work, I also upvoted your post!
For more information about SteemitBoard, click here

If you no longer want to receive notifications, reply to this comment with the word STOP

Upvote this notification to help all Steemit users. Learn why here!

Your contribution cannot be approved because it does not follow the Utopian Rules, and is considered as plagiarism. Plagiarism is not allowed on Utopian, and posts that engage in plagiarism will be flagged and hidden forever.

Plagiarised from here and Pro ASP.NET 4 in C# 2010 by Matthew MacDonald.

You can contact us on Discord.
[utopian-moderator]

Coin Marketplace

STEEM 0.19
TRX 0.15
JST 0.029
BTC 63657.90
ETH 2656.15
USDT 1.00
SBD 2.84