Tuesday, May 8, 2007

Don't Damage Your Site's Ranking

Here's some quick tips on implementing a 301 redirect for your site or pages. Make sure when you modify your site's structure that you account for search engine issues. We provide some code snippets here for you to implement in order to maintain your site's ranking. Making sure your site comes at the top of listings of search engines are probably one of the main issues many Webmasters concern themselves with. One thing that can impact search engine rankings and listings is changing a site's structure. This could be changing file names, like what commonly happens when moving a site from a static HTML site to one that is driven dynamically. Another issue could come from domain name consolidation where you have several domains names and wish to consolidate them into one domain. This is common when a company decides to change marketing strategy or comes through consolidation. In this article we'll focus on some issues of consolidating domains into one domain, or even changing page references and dealing with search engines. 301 Redirects Whenever you want to move or change your domain to something else you should always use a 301 Redirect. 301 Redirects are included as part of the HTTP header information sent to the browser or requesting client. The 301 informs the requesting client that the site or resource being requested has been permanently moved. It is best to include this information for search engines in order to prevent a negative impact on your search engine ranking. For example, say I have two domains, somedomain.com and someotherdomain.com, and both these domains point to the same content. Some engines consider multiple domains pointing to the same spamming their engine and this could adversely affect your ranking on that engine. Another issue is if you want to do a branding change and as part of the new brand change the domain name. It is not simply a manner of submitting the new domain to the search engines and expecting your new domain to be indexed in the search results. If your old domain exists in their index with identical content, then most likely the search engines will ignore your submission. In addition, many of the major search engines consider posting multiple domains with the same content "spamming", and it could negatively affect your site's ranking. Bring 301 redirects to the rescue. As mentioned the 301 code sent in the header information informs the search engine that you no longer want the requested domain to be the focus, it tells them that you moved your site to a new domain. It's kind of like filling out a change of address form at the post office where yes, you'll still get mail to the old address, but the post office knows to forward it on to your new address. Eventually all mail will go to the new address and the old address is no longer associated with your mail. This is what we want to do with our old domains, let them know we moved. By doing this you can avoid confusion with search results, and limit the adverse affects on your site's ranking with the new domain name. 301 Redirects via IIS One way of accomplishing this is to use IIS and letting it know that the domain has moved. Simply go to the old site and instead of pointing to a folder location for your site, change it to do a permanent redirect for the resource. You can use the following directions to accomplish this in IIS: Open Computer Management to manage your IIS Website. Right click on your site and select Properties. Under the Folder tab select "A redirection to a URL". Type in the new domain information in the text box below. Select "The exact URL entered above" and "A permanent redirection for this resource" in order to ensure that the 301 header will be sent to the client. 301 Redirects via Code Many people use an ISP to host their sites and may not have access to the Web server settings. The following code will provide you with how to redirect using server-side code via ASP.Net. There are many ways you can accomplish this, you could intercept the request via a HTTP handler, but in this example we'll simply provide a method at a file level in the Page_Load event. C# private void Page_Load(object sender, System.EventArgs e) { Response.Status = "301 Moved Permanently"; Response.AddHeader("Location","http://www.someotherdomain.com/page.aspx"); } In VB.Net Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Response.Status = "301 Moved Permanently"; Response.AddHeader("Location","http://www.someotherdomain.com/page.aspx")End Sub You can also perform a redirect for your entire domain via code, by first checking the domain of the request, if the domain does not match the domain that you want to be the primary, then send a 301 redirect and redirect them to the appropriate file and domain. This could be done either in the global.asax or via a HTTP handler. Remember, in order to perform a redirect, the requested file will need to be processed by the ASPNet_ISAPI.dll, this means by default they're either aspx files. You can change this setting via IIS if you need to, but if you have that ability then you can change the 301 error at a server level. Redirect Your Legacy ASP Files Now to complete this article, many of you may be porting ASP files over to ASP.Net. Let's provide some code to let the search engines know that your site should be redirect

Get a File ContentType from a Windows Forms App

Introduction

I do most of my development in ASP.NET, but recently, I needed to
convert a large number of articles from *.asp files into a format that we could
store in our database. Part of this conversion involved storing all the images
and files from the *.asp pages into the database in a binary format. There are
many good articles on the web about how to accomplish this task, however all of
them seem to involve the process of selecting the file in a web form, and then
uploading that file for storage in the database. That process looks something
like this:


Collapse
Private Sub UploadFile()
Dim iLength As Integer = CType( _
File1.PostedFile.InputStream.Length, Integer)
If iLength = 0 Then Exit Sub 'not a valid file
Dim sContentType As String = File1.PostedFile.ContentType
Dim sFileName As String, i As Integer
Dim bytContent As Byte()
ReDim bytContent(iLength) 'byte array, set to file size
'strip the path off the filename
i = InStrRev(File1.PostedFile.FileName.Trim, "\")
If i = 0 Then
sFileName = File1.PostedFile.FileName.Trim
Else
sFileName = Right(File1.PostedFile.FileName.Trim, _
Len(File1.PostedFile.FileName.Trim) - i)
End If
Try
File1.PostedFile.InputStream.Read(bytContent, 0, iLength)
With cmdInsertFile
.Parameters("@FileName").Value = sFileName
.Parameters("@FileSize").Value = iLength
.Parameters("@FileData").Value = bytContent
.Parameters("@ContentType").Value = sContentType
.ExecuteNonQuery()
End With
Catch ex As Exception
dbConn.Close()
End Try
End Sub

The ContentType Snagfu

That code above is all fine and dandy, and was an excellent jumping
off point for me to begin storing the files from a WindowsForms application. The
Windows application doesn't suffer from the same file access restrictions as the
ASP.NET application does. I can access the file directly (which is the point of
doing it this way). So first, I'll need a quick change to the way we access the
file. It is not being passed through a web form, so I'll just pass the Path the
the file as a parameter.

Private Sub UploadFile(Byval filename as String)

Then, instead of using a stream from the posted file, we create a
FileStream from the file itself.

Dim Fs As FileStream = New FileStream(filename, _
FileMode.Open, FileAccess.Read)
Dim iLength As Integer = CType(Fs.Length, Integer)
..
..
Fs.Read(bytContent, 0, iLength)

Ah, finally, all we need now is to get the ContentType. But as you'll quickly notice, there is no ContentType property associated with FileStream. Now what?

The Registry To The Rescue - Almost

My first thought was to handle this own my own, and start making up a
simple lookup table of all the common file formats - .zip, .doc, .xls, .jpg,
.jpeg - I quickly realized that this list was going to get enormous very
quickly. This wasn't going to work. Our employees upload files from hundreds of
applications, I'd never get them all.

Then a friend tipped me off (Thanks TheLearnedOne) - he said to look
in the registry, under \\HKEY_CLASSES_ROOT. I looked, and therein was a list of
file extensions! And under the file extensions was a key called ContentType. Hooray! An answer! Or so I thought. As it turns out,
there is not a ContentType key under ALL the file types,
only some of them. Which means this method would only help SOME of the time.
Since I like to keep my job ALL of the time, I needed a better answer. It wasn't
far away.

The Registry To The Rescue - Again

The registry idea was a good one. I did a search on ContentType and came up with this path (
\\HKEY_CLASSES_ROOT\MIME\Database\Content Type\). Finally, here is a complete
listing of every ContentType available. And under each one,
a key with the file extenstion that maps to that ContentType. Since I have a filename, all I have to do is match
the key to the ContentType, and we have a winner.


Collapse
Public Function GetMIMEType(_
ByVal filepath As String) As String
Dim regPerm As RegistryPermission = _
New RegistryPermission(RegistryPermissionAccess.Read, _
"\\HKEY_CLASSES_ROOT")
Dim classesRoot As RegistryKey = Registry.ClassesRoot
Dim fi = New FileInfo(filepath)
Dim dotExt As String = LCase(fi.Extension)
Dim typeKey As RegistryKey = classesRoot.OpenSubKey(_
"MIME\Database\Content Type")
Dim keyname As String

For Each keyname In typeKey.GetSubKeyNames()
Dim curKey As RegistryKey = classesRoot.OpenSubKey( _
"MIME\Database\Content Type\" & keyname)
If LCase(curKey.GetValue("Extension")) = dotExt Then
'Debug.WriteLine("Content type was " & keyname)
Return keyname
End If
Next
End Function

Using the code

I'm not even going to post a download file here. Just copy the code
from above, and paste it into your VB.NET application. I'm sure it can be easily
converted to C# as well. You may need to add the following lines to your
application as well:

Imports System.Security.Permissions
Imports Microsoft.Win32

In Closing

By the way, here is the final modified code. This of course assumes
that you have code defined in order to access your database, and a stored
procedure to store the file in the database. Like I said, there are many good
articles on the web regarding this process, so I won't repeat them here.


Collapse
Private Sub UploadFile(ByVal filename as String)
Dim Fs As FileStream = New FileStream(filename, _
FileMode.Open, FileAccess.Read)
Dim iLength As Integer = CType(Fs.Length, Integer)
If iLength = 0 Then Exit Sub 'not a valid file
Dim sContentType As String = GetMIMEType(filename)
Dim sFileName As String, i As Integer
Dim bytContent As Byte()
ReDim bytContent(iLength) 'byte array, set to file size
'strip the path off the filename
i = InStrRev(FileName.Trim, "\")
If i = 0 Then
sFileName = FileName.Trim
Else
sFileName = Right(FileName.Trim, Len(FileName.Trim) - i)
End If
Try
fs.Read(bytContent, 0, iLength)
With cmdInsertFile
.Parameters("@FileName").Value = sFileName
.Parameters("@FileSize").Value = iLength
.Parameters("@FileData").Value = bytContent
.Parameters("@ContentType").Value = sContentType
.ExecuteNonQuery()
End With
Catch ex As Exception
dbConn.Close()
End Try
End Sub

OOPs Concepts and .NET Part 1: Classes, Objects, and Structures

Summary

The following article kicks off a three-part article series that will present definitions and samples for different Object-Oriented Programming concepts and its implementation in .NET. The first part will examine the concepts of classes, objects, and structures. The second part will examine the concepts of inheritance, abstraction, and polymorphism. The third and last part will examine the concepts of interface, multiple interface inheritance, collections, and overloading.

Introduction

Object-Oriented Programming (OOP) is a software development paradigm that suggests developers to split a program in building blocks known as objects. The OOP paradigm allows developers to define the object's data, functions, and its relationship with other objects.

Microsoft created the .NET Framework using OOP, and knowing this concepts has helped me to understand the .NET Framework and to design and develop better software components. The purpose of this article is to describe the basic OOP concepts using real world scenarios and to provide some code samples that demonstrate how to work with OOP and .NET.

Class

The most common definition states that a class is a template for an object. Suppose that someone builds a paper pattern for a shirt. All the shirts done with the same paper pattern will be identical (same design, size, etc.). In this sample, the paper pattern is the class and the shirt is the object. To build the same exact shirt over and over, you need the paper pattern as a template. Another great example are house plans and blueprints. The plans and blueprints define the number of rooms, the size of the kitchen, the number of floors, and more. In this real world sample, the house plans and blueprints are the class and the house is the object. In OOP you program a class as a template for a specific object or groups ob objects that will always have the same features.

Class members

A class has different members, and developers in Microsoft suggest to program them in the following order:

  • Namespace: The namespace is a keyword that defines a distinctive name or last name for the class. A namespace categorizes and organizes the library (assembly) where the class belongs and avoids collisions with classes that share the same name.
  • Class declaration: Line of code where the class name and type are defined.
  • Fields: Set of variables declared in a class block.
  • Constants: Set of constants declared in a class block.
  • Constructors: A method or group of methods that contains code to initialize the class.
  • Properties: The set of descriptive data of an object.
  • Events: Program responses that get fired after a user or application action.
  • Methods: Set of functions of the class.
  • Destructor: A method that is called when the class is destroyed. In managed code, the Garbage Collector is in charge of destroying objects; however, in some cases developers need to take extra actions when objects are being released, such as freeing handles or deallocating unmanaged objects. In .NET, there is no concept of deterministic destructors. The Garbage Collector will call the Finalize() method at a non-deterministic time while reclaiming memory for the application.

Access keywords

Access keywords define the access to class members from the same class and from other classes. The most common access keywords are:

  • Public: Allows access to the class member from any other class.
  • Private: Allows access to the class member only in the same class.
  • Protected: Allows access to the class member only within the same class and from inherited classes.
  • Internal: Allows access to the class member only in the same assembly.
  • Protected internal: Allows access to the class member only within the same class, from inherited classes, and other classes in the same assembly.
  • Static: Indicates that the member can be called without first instantiating the class.

The following sample code illustrates a sample class in C#:

///Imported namespaces
using System;
/// Namespace: Consider using CompanyName.Product.ComponentType
namespace DotNetTreats.OOSE.OOP_CSharp {
///Class declaration
public class employee {
///Fields
private string _name;
private int _salary;
///Constants
private const int anualBonus = 1000;
///Constructor
public employee(){
}
///Properties
public string Name {
get {
return _name;
}
set {
_name = value;
}
}
public int Salary {
get {
return _salary;
}
set {
_salary = value;
}
}
/// Event handlers
public event EventHandler OnPromotion {
add {
}
remove {
}
}
/// Methods
public void DuplicateSalary()
{
_salary = _salary*2;
}
}
}

Listing 1. Sample class implementation in C#

The following sample code illustrates a sample class in VB.NET:

'Imported namespaces
Imports System
' Namespace: Consider using CompanyName.Product.ComponentType
Namespace DotNetTreats.OOSE.OOP_VBNET
'Class declaration
Public Class employee
'Fields
Private _name As String
Private _salary As Integer
'Constants
Private Const anualBonus As Integer = 1000
'Constructors
Public Sub New()
MyBase.New()
End Sub
'Properties
Public Property Name() As String
Get
Return _name
End Get
Set(ByVal Value As String)
_name = value
End Set
End Property
Public Property Salary() As Integer
Get
Return _salary
End Get
Set(ByVal Value As Integer)
_salary = value
End Set
End Property
' Event handlers
Public Event OnPromotion As EventHandler
'Methods
Public Sub DuplicateSalary()
_salary = (_salary * 2)
End Sub
End Class
End Namespace

Listing 2. Sample class implementation in VB.NET

Object

Objects are the building blocks of OOP and are commonly defined as variables or data structures that encapsulate behavior and data in a programmed unit. Objects are items that can be individually created, manipulated, and represent real world things in an abstract way.

Object composition

Every object is composed by:

  • Object identity: Means that every object is unique and can be differentiated from other objects. Each time and object is created (instantiated) the object identity is defined.
  • Object behavior: What the object can do. In OOP, methods work as functions that define the set of actions that the object can do.
  • Object state: The data stored within the object at any given moment. In OOP, fields, constants, and properties define the state of an object.

Structures

Not everything in the real world should be represented as a class. Structures are suitable to represent lightweight objects. Structures can have methods and properties and are useful for defining types that act as user-defined primitives, but contain arbitrary composite fields. The .NET Framework defines some structures such as System.Drawing.Rectangle, System.Drawing.Point, and System.Drawing.Color.

The following code sample represents a structures in C#:

struct Point
{
private int _x;
private int _y;
Point(int x, int y)
{
this._x = x;
this._y = y;
}
public int X
{
get
{
return _x;
}
set
{
_x = value;
}
}
public int Y
{
get
{
return _y;
}
set
{
_y = value;
}
}
}

Listing 3. Sample structure implementation in C#

The following code sample represents a structure in VB.NET:

Structure Point
Private _x As Integer
Private _y As Integer
Sub New(ByVal x As Integer, ByVal y As Integer)
MyBase.New()
Me._x = x
Me._y = y
End Sub
Public Property X() As Integer
Get
Return _x
End Get
Set(ByVal Value As Integer)
_x = value
End Set
End Property
Public Property Y() As Integer
Get
Return _y
End Get
Set(ByVal Value As Integer)
_y = value
End Set
End Property
End Structure

Listing 4. Sample structure implementation in VB.NET

Conclusion

OOP is full of abstract concepts, and the best approach to understand them is practical and not only theoretical. I learned more OOP after making some designs and after implementing some components. The concepts presented in this article might clarify the meaning, but I strongly recommend to go and have fun playing around with OOP. In this article, I examined the concept of classes, objects, and structs. The second part will examine the concepts of inheritance, abstraction, and polymorphism.

Reference

  • Matt Weisfeld, The Object-Oriented Thought Process, SAMS, 2000.
  • Don Box, Chris Sells, Essential .NET, Addison-Wesley, 2002.