Saturday, September 24, 2011

SEO Friendly URL using URL Routing in ASP.NET

Many SEO (Search Engine Optimization) professionals say that dirty URLs are not appealing to web search engines. ASP.NET web pages are basically dynamic web pages and so tend to be dirty URLs. It is common that ASP.NET .aspx page has some parameters in its URL. For example, a sample of dirty URL is like http://x.com/shop.aspx?Category=Car&Maker=Ford. Search engines tend to have difficult time to figure query string parameters. SEO friendly URL is a.k.a clean URL which has folder-like structure. The dirty URL above can be rewritten to http://x.com/shop/car/ford. And from userability point of view, it's much easier to remember as well.

By and large, there are two ways of making website more SEO friendly. One is URL Rewriting and the other is URL Routing.

URL Rewriting
When a client issues a URL to Web server, the URL-rewriting ISAPI DLL analyzes the requested URL and changes it to other URL before it sends the request to web page. Most IIS servers (v5, v6, v7) supports it.

URL Routing
ASP.NET URL routing does not actually change incoming URL and dispatches a URL request to a specific handler based on the requested URL path. Works on latest ASP.NET version (3.5, 4.0).

So assuming we're using ASP.NET 4.0, let's take a look at how to make ASP.NET webpage more SEO friendly by using URL routing scheme.

1) Define URL Routing tables in Global.asax. In Global.asax;
void Application_Start(object sender, EventArgs e)
{
    this.RegisterRoutes(RouteTable.Routes);
}

void RegisterRoutes(RouteCollection routes)
{            
    //If you use ASP.NET AJAX
    routes.Ignore("{resource}.axd/{*pathInfo}");

    // Define Routing Tables
    routes.MapPageRoute("item", "shop/{item}", "~/shop.aspx");
}

If you use ASP.NET AJAX, you might get an error:
'ASP.NET Ajax client-side framework failed to load.'
This can be avoided by adding routes.Ignore statement above.

MapPageRoute() method has many overrodes but here first parameter is route map name; you need to put any unique mapping name. 2nd parameter is URL input routing pattern. With this pattern, the incoming URL is like http://x.com/shop/iPhone. In this case, the string 'iPhone' corresponds to {item}. 3rd parameter is physical file that will process the URL. So shop.aspx will take parameter {item} (which is iPhone) and process the incoming URL request.

2) Process URL request in designated .ASPX page.
In Page_Load() method of shop.aspx.cs file, {item} data can be retrieved by looking up Page.RouteData.Values collection.
protected void Page_Load(object sender, EventArgs e)
{
  string item = Page.RouteData.Values["item"] as string;                
  if (!string.IsNullOrEmpty(item))
  {   
      // set item data here
      return;
    }
  }
  Response.Redirect("/Default.aspx");
}

So URL routing is quite simple, but it's powerful in terms of SEO.
One thing worthy adding is that Routing tables are looked up sequentially, so one can add special routing case before generic routing pattern.

Wednesday, September 21, 2011

Send email in ASP.NET ( from Arvixe web hosting )

This post explains about how to send email in ASP.NET. Sending mail from ASP.NET is not complex, per se. But, it might take a while to figure out since we normally don't set it up often. If you're using Web Hosting, typically web hosting company already set up the mail server, so all you need is to create mail account and use it. I am using Arvixe ASP.NET web hosting so I will show you how to send email by using Arvixe SMTP mail server.

1) First, you have to create mail account in Arvixe Control Panel (or your web hosting control panel)
Log in to Control Panel and select Mail -> Accounts and create new email account.




2) Once SMTP email account is created, you can send email in ASP.NET with the following code. Let's say your domain is TEST.COM; in that case your mail server will be mail.test.com in Arvixe.

MailMessage msg = new MailMessage();
msg.From = new MailAddress("admin@test.com");
msg.To.Add(new MailAddress("tom@gmail.com"));
msg.Subject = "Meeting";
msg.Body ="Body message";            

SmtpClient smtp = new SmtpClient("mail.test.com", 25);
smtp.Credentials = new NetworkCredential("admin@test.com", "admin1234");            
smtp.Send(msg);

 In your ASP code-behind or any business class, you create MailMessage which includes From/To/Subject and Body message and send it to SMTP mail server through SMTP port 25.

You have to specify your mail server (mail.test.com) in SmtpClient constructor and since your SMTP server requires authentication, you also have to provide Credential. You can use your mail account information in credential username (admin@test.com in this example) and its password. If SMTP server requires credential but you don't specify username and password, the following exception will occur.

The SMTP server requires a secure connection or the client was not authenticated. The server response was: SMTP authentication is required.

3) The above code snippet will work but server name and user/password info are hardcoded. Not a good way. In ASP.NET, we can move those information to web.config as follows.

<system.net>
<mailSettings>
<smtp>
<network host="mail.test.com" port="25" userName="admin@test.com" password="admin1234" />
</smtp>
</mailSettings>
</system.net>

And then C# code can be simplified like this.

private void SendSmtpMail(MailMessage message)
{
  SmtpClient smtp = new SmtpClient();
  smtp.Send(message);
}

As you can see, you do not specify mail server name and port number. And credential information can come from web.config file.

4) Now, you can check your email. In our example, you are supposed to check your email from http://mail.test.com (in Arvixe case), assuming the domain is test.com.

Tuesday, September 20, 2011

How to pass parameters to ASP.NET user control

One common way of passing parameters to ASP.NET user control is to use public properties in user control. As always, let's take a look at a simple example here. The following user control displays main title with a specific style.

MainTitle.ascx
<%@ Control Language="C#" AutoEventWireup="true" CodeBehind="MainTitle.ascx.cs" Inherits="MyWeb.Modules.MainTitle" %>
   
<div class="main-title">
  <asp:Label ID="lblTitle" runat="server" Text="Main" />
</div>
<br />

In .aspx page that includes this user control, one might want to change title text of this control. To pass title parameter, one public property called Title is added to user control code-behind file as follows.

MainTitle.ascx.cs
namespace MyWeb.Modules
{
   public partial class MainTitle : System.Web.UI.UserControl
   {
      protected void Page_Load(object sender, EventArgs e)
      {
          if (!string.IsNullOrEmpty(Title))
          {
              lblTitle.Text = Title;
          }          
      }

      public string Title { get; set; }
   }
}

Now, ASP.NET page containing the user control can pass parameter by setting any value to the public property of the ascx control. First, test.aspx file below registers the user control and add MainTitle user control to the web page.

Test.aspx
<%@ Page Language="C#" MasterPageFile="~/Masters/DefaultLayout.master" AutoEventWireup="true"
    CodeBehind="Test.aspx.cs" Inherits="Test.Article" %>
<%@ Register TagPrefix="myControl" TagName="MainTitle" Src="~/Modules/MainTitle.ascx" %>

<asp:Content ID="BodyContent" runat="server" ContentPlaceHolderID="Main">
    <myControl:MainTitle runat="server" ID="mainTitle" />       
</asp:Content>

Then in the code-behind, Title property of the mainTitle object can be set as follows.

Test.aspx.cs
public partial class Test: System.Web.UI.Page
{
  protected void Page_Load(object sender, EventArgs e)
  {
    if (!this.IsPostBack)
    {                                
       mainTitle.Title = "New Title"; //set property              
    }
  }
}

Friday, September 9, 2011

Convert byte array to image in ASP.NET

There are several cases you want to convert byte array to image. For example, if you have image data in your database, your image will be byte array. Another example is you might to want to draw picture on th fly in your memory and send the image to web browser. This article shows how to convert the binary data to actual image in ASP.NET.

1) First, create a new ASP.NET webpage(.aspx) and remove all content except first line as follows. We will send image directly from code-behind code.

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="WebForm1.aspx.cs" Inherits="TestWeb1.WebForm1" %>

2) In code-behind page, call CreateImage method in Page_Load. This means when the aspx page is loaded, the image will be sent to web browser.

using System;
using System.Drawing;
using System.IO;

namespace TestWeb1
{
   public partial class WebForm1 : System.Web.UI.Page
   {
      protected void Page_Load(object sender, EventArgs e)
      {
         this.CreateImage();
      }

      protected void CreateImage()
      {
         int width = 100;
         int height = 100;
         Bitmap image = new Bitmap(width, height);
         Graphics g = Graphics.FromImage(image);

         try
         {
            // Draw something
            for (int i = 0; i < height/2; i+=4)
            {
               g.DrawRectangle(new Pen(Color.Red), i, i, image.Width - 1, image.Height - 1);
            }

            // Save it to memory in image format
            MemoryStream mem = new MemoryStream();
            image.Save(mem, System.Drawing.Imaging.ImageFormat.Gif);

            // Send byte array
            Response.ClearContent();
            Response.ContentType = "image/gif";
            Response.BinaryWrite(mem.ToArray());
            Response.End();
         }
         finally
         {
            g.Dispose();
            image.Dispose();
         }
      }
   }
}
In CreateImage() method, you create empty Bitmap image (100x100 in this example) and draw some rectangles by using graphics object. Once drawing is done, save the bitmap image to memory with specific image format. The example above (image.Save() method) shows that bitmap image is saved into memory in GIF format. Once formatted image is in memory, you can convert it to byte array. To send data to web browser, clear all content in Response object and set ContentType to specific image type (image/gif in this case). Then The byte array is sent to web browser by using Response.BinaryWrite(). When everything is done, call Response.End() and finish the work.

3) In your another web page, set <img> src attribe to the webpage created in step (1).

<img src="WebForm1.aspx" />
Since image is an independent web object, imageloading can be done separately by this way.