Microsoft.NET

……………………………………………….Expertise in .NET Technologies

ASP.net Coding Standards

Posted by Ravi Varma Thumati on May 6, 2009

1. Purpose

Purpose of this document is to provide guidelines for ASP.Net developers to follow coding standards.

2.  Coding Standards

The coding techniques defined here are not proposed to form an inflexible set of coding standards. Rather, they are meant to serve as a guide for developing a coding standard for a specific software project.

 2.1          Naming and Capitalization

Below summarizes the naming recommendations for identifiers in .Net. Pascal casing is used mainly (i.e. capitalize first letter of each word) with camel casing (capitalize each word except for the first one) being used in certain circumstances.

Pascal case

The first letter in the identifier and the first letter of each subsequent concatenated word are capitalized. You can use Pascal case for identifiers of three or more characters. For example:

BackColor

Example:

Pascal casing for Class names

public class HelloWorld

{

   …

}

 

Pascal casing for Method names

public class HelloWorld

{

   void SayHello(string

Camel case

The first letter of an identifier is lowercase and the first letter of each subsequent concatenated word is capitalized. For example:

backColor

Example:

Use Camel casing for variables and method parameters

public class HelloWorld

{

   int totalCount = 0;

   void SayHello(string name)

Uppercase

All letters in the identifier are capitalized. Use this convention only for identifiers that consist of two or fewer letters. For example:

System.IO

System.Web.UI

Identifier Case Examples Additional Notes Detailed Info
Class Pascal Person, BankVault, SMSMessage, Dept Class names should be based on “objects” or “real things” and should generally be nouns.  
Method Pascal GetDetails, UpdateStore Methods should use verbs or verb phrases.  
Parameter camel personName, bankCode    
Interface Pascal with “I” prefix IDisposable One of the few times when prefixing is adopted.  
Property

Associated private member variable

 

Pascal

_camelCase

 

ForeColor, BackColor

_foreColor, _backColor

 

Use underscore camel casing for the private member variables, but keep the names the same as associated property accessors.  
Exception Class Pascal with “Exception” suffix WebException, SMSException    
Event Pascal plus optional “EventHandler” suffix where relevant btnSubmit_Click, Painting, Click, Clicked, MyEventHandler VS uses underscores to separate an object from its event. Be careful with tense (pre/past), e.g. a Close event that can be canceled should have a Closing event and a Closed event. MS also recommend adding the “EventHandler” suffix where thought needed.  

Note that acronym parts of phrases may be all in uppercase (e.g. SMSMessage) where relevant.

Naming convention for variables

For purposes of readability and consistency, use the following prefixes with descriptive names for variables in your code. The table given below mentions the data types and its prefixes.

For example: for integer it should be int iAge

Data type Prefix Example
sbyte sb sbTemp
byte byte byteTemp
char c cTemp
short shrt shrtTemp
ushort ushrt ushrtTemp
int i iTemp
uint ui uiTemp
long l lTemp
ulong ul ulTemp
bool b bTemp
decimal deci deciTemp
double d dTemp
float f fTemp
object obj objTemp
string str strTemp
class cls clsTemp
struct struct structTemp
enum enum enumTemp
union union unionTemp
signed sign signTemp
unsigned unsign unsignTemp
private m_Pri m_PriTemp
protected m_Pro m_ProTemp
public m_Pub m_PubTemp

Use Meaningful, descriptive words to name variables

– Do not use abbreviations. Use name, address, salary etc instead of nam, addr, sal
– Do not use single character variable names like i, n, x etc. Use names like index, temp
   one exception in this case would be variables used for iterations in loops:

Example:

for ( int i = 0; i < count; i++ )

{

   …

}

If the variable is used only as a counter for iteration and is not used anywhere else in the loop, many people still like to use a single char variable (i) instead of inventing a different suitable name.
– Do not use underscores (_) in variable names.

– Namespace names should follow the standard pattern

<company name>.<product name>.<top level module>.<bottom level module>

File name should match with class name

For example, for the class HelloWorld, the file name should be helloworld.cs (or, helloworld.vb)

Indentation and Spacing

  • Use TAB for indentation. Do not use SPACES.
  • Comments should be in the same level as the code.
  • Curly braces ( {} ) should be in the same level as the code outside the braces.
  • Use one blank line to separate logical groups of code.

Example:

            bool SayHello (string name)

            {

                        string fullMessage = “Hello ” + name;

                        DateTime currentTime = DateTime.Now;

                        string message = fullMessage + “, the time is : ” + currentTime.ToShortTimeString();

                        MessageBox.Show ( message );

                        if ( … )

                        {

                                    // Do something

                                    // …

                                    return false;

                        }

                        return true;

            }

This code looks better, than the code shown above:

            bool SayHello ( string name )

            {

                        string fullMessage = “Hello ” + name;

                        DateTime currentTime = DateTime.Now;

                        string message = fullMessage + “, the time is : ” + currentTime.ToShortTimeString();

                        MessageBox.Show ( message );

                        if ( … )

                        {

                                    // Do something

                                    // …

                                    return false;

                        }

                        return true;

            }

  • There should be one and only one single blank line between each method inside the class.
  • The curly braces should be on a separate line and not in the same line as if, for etc.

Example:

Good:

                        if ( … )  

                        {

                                    // Do something

                        }

Not Good:

                        if ( … )   {

                                    // Do something

                        }

 Use a single space before and after each operator and brackets.

Example:

Good:

                        if ( showResult == true )

                        {

                                    for ( int i = 0; i < 10; i++ )

                                    {

                                                //

                                    }

                        }

Not Good:

                        if(showResult==true)

                        {

                                    for(int    i= 0;i<10;i++)

                                    {

                                                //

                                    }

2.2   User Interface Objects and Control

This approach uses the “control type” prefix convention. Although this should not be used for indicating variable types, it is useful for user interface controls as it makes it explicitly clear where user interface elements are in your code.

Some samples are below for ASP.Net web form controls:

Control Prefix Example
Label lbl lblSurname
TextBox txt txtSurname
DataGrid dg dgResults
Button btn btnSave
ImageButton ibtn ibtnSave
Hyperlink lnk lnkHomePage
DropDownList ddl ddlCompany
ListBox lst lstCompany
DataList dlst dlstAddress
Repeater rep repSection
Checkbox chk chkMailList
CheckBoxList chk chkAddress
RadioButton rdo rdoSex
RadioButtonList rdo rdoAgeGroup
Image img imgLogo
Panel pan panSection
PlaceHolder plh plhHeader
Calender cal calMyDate
Adrotator adr adrBanner
Table tbl tblResults
[All] Validators val valCreditCardNumber
ValidationSummary vals valsErrors

2.3    Namespaces

The general rule for naming namespaces is to use the company name followed by the technology name and optionally the feature and design as follows.

 CompanyName.TechnologyName[.Feature][.Design]

For example:

Microsoft.Media

Microsoft.Media.Design

2.4   Good Programming Practices

  • Follow the best practices to for best programming
  • Avoid having too large files. If a file has more than 300~400 lines of code, you must consider refactoring code into helper classes.
  • Avoid writing very long methods. A method should typically have 1~25 lines of code. If a method has more than 25 lines of code, you must consider re factoring into separate methods.
  • Method name should tell what it does. Do not use mis-leading names. If the method name is obvious, there is no need of documentation explaining what the method does.

Example:

Good:

            void SavePhoneNumber ( string phoneNumber )

            {

                        // Save the phone number.

            }

Not Good:

            // This method will save the phone number.

            void SaveData ( string phoneNumber )

            {

                        // Save the phone number.

            }

A method should do only ‘one job’. Do not combine more than one job in a single method, even if those jobs are very small.

Example:

Good:

            // Save the address.

            SaveAddress (address );

                  // Send an email to the supervisor to inform that the address is updated.

            SendEmail (address, email );                 

                   void SaveAddress ( string address )

            {

                        // Save the address.

                        // …

            }

            void SendEmail ( string address, string email )

            {

                        // Send an email to inform the supervisor that the address is changed.

                        // …

            }

Not Good:

            // Save address and send an email to the supervisor to inform that the address is updated.

            SaveAddress ( address, email );

 

            void SaveAddress ( string address, string email )

            {

                        // Job 1.

                        // Save the address.

                        // …

                        // Job 2.

                        // Send an email to inform the supervisor that the address is changed.

                        // …

            }

  • Use the c# or VB.NET specific types, rather than the alias types defined in System namespace.

Example:

Good:

            int age;

            string name;

            object contactInfo;
Not Good:

            Int16 age;

            String name;

            Object contactInfo;

  • Do not hardcode numbers. Use constants instead.
  • Do not hardcode strings. Use resource files.
  • Avoid using many member variables. Declare local variables and pass it to methods instead of sharing a member variable between methods. If you share a member variable between methods, it will be difficult to track which method changed the value and when.
  • Use enum wherever required. Do not use numbers or strings to indicate discrete values.

Example:
Good:

            enum MailType

            {

                        Html,

                        PlainText,

                        Attachment

            }

            void SendMail (string message, MailType mailType)

            {

                        switch ( mailType )

                        {

                                    case MailType.Html:

                                                // Do something

                                                break;

                                    case MailType.PlainText:

                                                // Do something

                                                break;

                                    case MailType.Attachment:

                                                // Do something

                                                break;

                                    default:

                                                // Do something

                                                break;

                        }

            }

Not Good:

            void SendMail (string message, string mailType)

            {

                        switch ( mailType )

                        {

                                    case “Html”:

                                                // Do something

                                                break;

                                    case “PlainText”:

                                                // Do something

                                                break;

                                    case “Attachment”:

                                                // Do something

                                                break;

                                    default:

                                                // Do something

                                                break;

                        }

            }

  • Do not make the member variables public or protected. Keep them private and expose public/protected Properties.
  • Never hardcode a path or drive name in code. Get the application path programmatically and use relative path.
  • Never assume that your code will run from drive “C:”. You may never know, some users may run it from network or from a “Z:”.
  • In the application start up, do some kind of “self check” and ensure all required files and dependencies are available in the expected locations. Check for database connection in start up, if required. Give a friendly message to the user in case of any problems.
  • If the required configuration file is not found, application should be able to create one with default values.
  • If a wrong value found in the configuration file, application should throw an error or give a message and also should tell the user what are the correct values.
  • Error messages should help the user to solve the problem. Never give error messages like “Error in Application”, “There is an error” etc. Instead give specific messages like “Failed to update database. Please make sure the login id and password are correct.”
  • When displaying error messages, in addition to telling what is wrong, the message should also tell what the user should do to solve the problem. Instead of message like “Failed to update database.”, suggest what the user should do: “Failed to update database. Please make sure the login id and password are correct.”
  • Show short and friendly message to the user. But log the actual error with all possible information. This will help a lot in diagnosing problems

2.5   Comments

  • Do not write comments for every line of code and every variable declared.
  • Write comments wherever required. But good readable code will require very less comments. If all variables and method names are meaningful, that would make the code very readable and will not need much comment.
  • Fewer lines of comments will make the code more elegant. But if the code is not clean/readable and there are less comments, that is worse.
  • If you have to use some complex or weird logic for any reason, document it very well with sufficient comments.
  • If you initialize a numeric variable to a special number other than 0, -1 etc, document the reason for choosing that value.
  • The bottom line is, write clean, readable code such a way that it doesn’t need any comments to understand.
  • Do a spell check on comments and also make sure proper grammar and punctuation is used.

 2.6    Exception Handling

  • Never do a ‘catch exception and do nothing’. If you hide an exception, you will never know if the exception happened or not.
  • In case of exceptions, give a friendly message to the user, but log the actual error with all possible details about the error, including the time it occurred, method and class name etc.
  • Always catch only the specific exception, not generic exception.

Example:

Good:

            void ReadFromFile ( string fileName )

            {

                        try

                        {

                                    // read from file.

                        }

                        catch (FileIOException ex)

                        {

                                    // log error.

                                    //  re-throw exception depending on your case.

                                    throw;

                        }

            }

Not Good:

            void ReadFromFile ( string fileName )

            {

                        try

                        {

                                    // read from file.

                        }

                        catch (Exception ex)     

                        {

                                    // Catching general exception is bad… we will never know whether it

                                    // was a file error or some other error.

                                   

                                    // Here you are hiding an exception.

                                    // In this case no one will ever know that an exception happened.

 

                                    return “”;                      

                        }

            }

  • No need to catch the general exception in all your methods. Leave it open and let the application crash. This will help you find most of the errors during development cycle.
  • You can have an application level (thread level) error handler where you can handle all general exceptions. In case of an ‘unexpected general error’, this error handler should catch the exception and should log the error in addition to giving a friendly message to the user before closing the application, or allowing the user to ‘ignore and proceed’.
  • Do not write try-catch in all your methods. Use it only if there is a possibility that a specific exception may occur. For example, if you are writing into a file, handle only FileIOException.
  • Do not write very large try-catch blocks. If required, write separate try-catch for each task you perform and enclose only the specific piece of code inside the try-catch. This will help you find which piece of code generated the exception and you can give specific error message to the user.
  • You may write your own custom exception classes, if required in your application. Do not derive your custom exceptions from the base class SystemException. Instead, inherit from ApplicationException.

 2.7    Best Practices

  • It is usually a good idea to set the SmartNavigation property to true on most pages.

The reasoning:

This reduces or eliminates screen flickering during postbacks to the server. Furthermore the scroll position will be preserved.

  • Enable the ability for multiple postbacks when using AutoPostback controls by using a user interface device such as a button.

The reasoning:

If the user has disabled Javascript controls in their browser then there is no way for the user to submit the form unless you provide a button or other user interface device.

  • It is preferred to use the Server.HtmlEncode method when displaying data taken from the database to an HTML control or Web control.

The reasoning:

This makes sure that the special characters are displayed in the correct manner and prevents cross side scripting attacks.

  • It is always best to validate input on the client side by using a validator control. Also, make sure you also validate all data on the server side as well as unforeseen security vulnerabilities can put your server at risk.

The reasoning:

Validation of all data is a best practice in all situations. This ensures a consistent database and data integrity and the integrity of your website.

  • It is usually a best practice to make sure the client is still connected during a time consuming task. This can be accomplished using the Response.IsClientConnected method during a known time consuming task.

The reasoning:

This method allows you to check to see if the client is still connected to the server. If the client is no longer connected you can then use the Response.End method to end the session and free up resources.

  • It is usually a good practice to avoid the use of hidden fields in order to store data between page postbacks.

The reasoning:

There are few very good reasons for storing potentially sensitive information using hidden fields. These do not store data in an encrypted manner or can store any significant amounts of data.

  • It is usually a good practice to store data taken from either files or a database in the ASP.Net cache object if the data does not change much over a period of time and can be shared with multiple users on the webpage.

The reasoning:

By storing and caching the data taken from a file or database you increase the performance and scalability of your application.

  • It is a best practice to use a Global error handler in the Global.asax file of your application.

The reasoning:

This allows you to recover properly from unexpected exceptions in the current application. Also this may allow you to implement a common error recovery mechanism for your web application.

  • It is always best to never use the Off attribute when setting the <custom errors> attribute in the web.config file of your application when it resides on a production server viewable by the outside.

The reasoning:

Doing this will enable unauthorized visitors to view potentially sensitive information about your application thereby increasing the security risk that  your website can be attacked from outside visitors.

  • It is always best to set your application tracing in the web.config file rather than using the @Page directive on individual aspx pages.

The reasoning:

This allows you to enable application level tracing for the entire application rather than for each individual page of your website.

Advertisements

2 Responses to “ASP.net Coding Standards”

  1. Nice article. I was talking to someone the other day that caching solution developers should also use a standard where the developers can easily integrate any distributed cache available. For now session cache is implementable without any code change but if we go for data object cache, we have to change the code to implement.

  2. Bharat said

    Good one. I was looking for a article of this kind. Good Content. Thanks mate.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

 
%d bloggers like this: