ASP.NET Best Practices (for Webforms)
This has been pending since long. People have been requesting this information and I've not been able to find time to write on Best Practices. And this fine day, finally I pen this down.
I hope this helps to you. These best practices are direct-from-real-world i.e. noted down as observations from live projects.
String Concatenation
Use of StringBuilder is preferred over String.Concat or use of operator '+'
It is observed that when number of strings to be concatenated is greater than 3, StringBuilder does it much faster than String.Concat. For lesser number of strings, String.Concat can also be used.
Avoid round trips to server
- Usage of Ajax UpdatePanel is preferred to avoid full postback to the server.
- Client side scripts for validations should be used.
- Check Page.IsPostBack at Page Load to ensure that only page initialization logic is performed when a page is loaded the first time and not in response to client postbacks.
ViewState & HiddenFields
- ViewState is valid only for postback of same pages - as data is passed to client & returned in a hidden field
- Keep minimal data in ViewState - higher the data, slower the system
- Disable ViewState at PageLevel using EnableViewState
Session Variables
- Not more than 20 session variables should exist in application context.
- Keep Session TimeOut
- Disable Session State, if you are not using in particular Page/Application.
Server.Transfer vs Response.Redirect
- Use Server.Transfer to redirect between pages of same application.
- Use Response.Redirect to redirect to external page or when new context needs to be started.
Use DataReader for data binding
- If application does not demand caching, DataReader can be used. Use DataReader to retrieve data & then load it in a DataSet
- Don't pass this DataSet across layers. Pass custom serialize-able entities across layers.
Grid Pagination at SQL end
- Pagination logic can be written @ SQL end, than writing it at Grid level.
- Send Page Number, number of records to Stored Procedure to retrieve records from DB
- Sorting should also be implemented @ DB.
- Check for SQL Injection.
Close resources
- Close the connections when not in use - improves security & enhances the performance.
- Such closures should be done in finally block or in using block
Optimize loops
- Avoid foreach - use for, while loops
foreach degrades the performance. It is better to use for loop instead of a foreach - While deleting records/rows from a collection, iterate backward (counter=Max to 1). This will avoid Stack Overflow exceptions
- Avoid try-catch in for loops - it degrades performance.
Variable Initialization @ right place
- Initializing variable @ start & using it at a later stage will cause many PUSH/POP operations. Hence initialize variables at right place.
- Integer variables need not to be initialized to ZERO. They are automatically initialized; String variables need to be initialized explicitly.
Use Fiddler to intercept HTTP requests.
- Use Fiddler to intercept the HTTP requests and to know which request is consuming more time.
- Also find out the exceptions caused during each HTTP request.
URL Rewriting
- For URLs that have confidential information, it is advisable to implement URL Rewriters.
- URLs should be consistent
Caching Mechanism
- Cache static content for longer period - use high value for Expires property
- Use Friendly folder structure - contentimagesheader.gif, etc.
- Minimize use of SSL as SSL is not cached
- Use IIS HTTP Headers to configure static caching.
Application Settings
- Content-Length should be fixed. This keeps the connection open for limited time & closes automatically when the content length is greater than declared one.
- Encrypt connection strings on server.
- Make sure all the reference DLLs are present in GAC
- Disable tracing and debugging
Set <deployment retail="true" /> in machine.config file - it forces debug to be false, disables output tracing, and redirects to custom error page rather than the actual error page.
Progressive UI
- Progressive UI enables fast & smooth surfing - load/visible the DIV tags only when required.
Web Services
- Prevent overloading of web services through DoS (Denial of Service) attacks. Check if it is the First time visit, or repeated visit for the same function from same IP.
- Use trusted SQL connections in Web Services
- Make sure there are asynchronous calls to web services
Exception Handling
- Log the exceptions & display appropriate message to user.
- Define a base class say : MyException
- This class should have following information for display to user
- What Happened
- What has been affected
- What actions to do
- Support Information
- This class should have following information for logging purpose
- Server Name
- Instance id
- User Id
- Call Stack
- Assembly Name & Version
- Exception Source, Type & Message
- Redirect as per the Error-Level
- Application Level: Catch errors in global.asax in Application_Error function.
- Page Level: Use Page_Error function to log errors.
Deployment - IIS
- Create separate application pool for your site
- Use App_Offline.htm file. This will help you take your application offline by displaying user friendly message while fixing issues.
- Automate the build process for
- Development
- Production environments
- Make sure application is not built in DEBUG mode.
- Load test application.