Monday, October 13, 2008

Enabling HTTP Compression (IIS 6.0)

  1. In IIS Manager, double-click the local computer, right-click the Web Sites folder, and then click Properties.
  2. Click theService tab, and in the HTTP compression section, select the Compress application files check box to enable compression for dynamic files.
  3. Select the Compress static files check box to enable compression for static files.
  4. In the Temporary directory box, type the path to a local directory or click Browse to locate a directory. Once a static file is compressed, it is cached in this temporary directory until it expires, or the content changes. The directory must be on the local drive of an NTFS–formatted partition. The directory cannot be compressed or shared, and the access control lists (ACLs) for the directory must include Full Control access to the identity of the application pool or to the IIS_WPG group.
  5. Under Maximum temporary directory size, click a folder size option. If you specify a maximum size under Limited to (in megabytes) (the default setting is 95 MB), then when the limit is reached, IIS automatically cleans up the temporary directory by applying the "least recently used" rule.
  6. Click Apply, and then click OK.
  7. Created a web service extension for c:\windows\system32\inetsrv\gzip.dll
  8. Used metabse explorer or Adsutil.vbs to:
    a) edit the compression levels (set to level 9 for both HcDynamicCompressionLevel and HcOnDemandCompLevel) for both deflate and gzip.
    b) ensure that gzip was used for static compression only (HcDoStaticCompression set to 1) c) set HcFileExtensions (static files) for both gzip and deflate to htm,html,txt,js
    d) set HcScriptFileExtensions for both gzip and deflate to asp,dll,exe,aspx,asbx,ashx,asmx,axd,js and css (I have css files that are dynamically generated)
    e) set HcCreateFlags to 0 for deflate and 1 for gzip
    f) Checked that, underneath parameters, HcDoDynamic, HcDoStatic and HcDoOnDemand are set to 1.
    g) Other settings: Buffer sizes are set to 8192, HcMinFileSizeForComp is 1.
Samples for Adsutil.vbs:

To enable HTTP Compression for Individual Sites and Site Elements:

  1. Disable global static compression by executing the following command at a command prompt:
    adsutil set w3svc/filters/compression/parameters/HcDoStaticCompression false
  2. Enable static compression at this directory by executing the following command at a command prompt:
    adsutil set w3svc/1/root/Home/StyleSheets/DoStaticCompression true

To disable static compression for only a single directory, first enable global static compression (if it is disabled) and then disable static compression at that directory. For example, to enable static compression for a directory at http://www.contoso.com/Home/StyleSheets, perform the following steps:

  1. Disable global static compression by executing the following command at a command prompt:
    adsutil set w3svc/filters/compression/parameters/HcDoStaticCompression true
  2. Enable static compression at this directory by executing the following command at a command prompt:
    adsutil set w3svc/1/root/Home/StyleSheets/DoStaticCompression false

Friday, August 29, 2008

Lightweight device-detection

It is a simple C# function which will detect most mobile browsers.


public static bool isMobileBrowser()
{
string user_agent;
int mobile_browser;
Match match;
user_agent = HttpContext.Current.Request.ServerVariables["HTTP_USER_AGENT"];
mobile_browser = 0;
string pattern = "(up.browserup.linkmmpsymbiansmartphonemidpwapphonewindows cepdamobileminipalm)";
Regex agentEx = new Regex(pattern, RegexOptions.IgnoreCase);
match = agentEx.Match(user_agent);
if(match.Success)mobile_browser = mobile_browser+1;
if(HttpContext.Current.Request.ServerVariables["HTTP_ACCEPT"].IndexOf("application/vnd.wap.xhtml+xml")>=0
HttpContext.Current.Request.ServerVariables["HTTP_X_PROFILE"]!=string.Empty
HttpContext.Current.Request.ServerVariables["HTTP_PROFILE"]!=string.Empty)
{
mobile_browser = mobile_browser+1;
}
string[] mobile_agents = {
"w3c ", "acs-", "alav", "alca", "amoi", "audi",
"avan", "benq", "bird", "blac", "blaz", "brew",
"cell", "cldc", "cmd-", "dang", "doco", "eric",
"hipt", "inno", "ipaq", "java", "jigs", "kddi",
"keji", "leno", "lg-c", "lg-d", "lg-g", "lge-",
"maui", "maxo", "midp", "mits", "mmef", "mobi",
"mot-", "moto", "mwbp", "nec-", "newt", "noki",
"oper", "palm", "pana", "pant", "phil", "play",
"port", "prox", "qwap", "sage", "sams", "sany",
"sch-", "sec-", "send", "seri", "sgh-", "shar",
"sie-", "siem", "smal", "smar", "sony", "sph-",
"symb", "t-mo", "teli", "tim-", "tosh", "tsm-",
"upg1", "upsi", "vk-v", "voda", "wap-", "wapa",
"wapi", "wapp", "wapr", "webc", "winw", "winw",
"xda", "xda-"
};
int size = mobile_agents.Length;
string mobile_ua = user_agent.Substring(0, 4).ToUpper();
for(int i=0; i {
if( mobile_agents[i] == mobile_ua)
{
mobile_browser = mobile_browser+1;
break;
}
}
if(mobile_browser>0)
return true;
return false;
}

Tuesday, July 29, 2008

SQL 2005 to delete lots of data in batches

If you want to delete lots of data (millions), Running one query causes the TransactionLog to grow with huge size.

You have 2 solutions for this problem:
1. If you can your data is offline:
  • Copy the rows you want to keep to a temporary table
  • Drop the original table
  • Rename the temporary table to original name
  • Reinstate any indexes

2. Second approach is to delete the rows in a loop. Delete a modest number each time round the loop. Keep looping until no more rows exist to delete.

  • You will need to either backup the TLog frequently during this process (to stop it extending to a vast size), or change the RECOVERY MODEL to SIMPLE whilst this is running, and back to FULL again after it finished.
  • If this batch works 24 hours/7 days you should also put a WAIT for 5 seconds or so inside the loop so that during each iteration other connected users get "their chance"

SQL Script to delete rows in loop:(needs local variables declaring)

SELECT @intRowsToDelete = COUNT(*) -- Number of rows to be deleted FROM dbo.MyTable WHERE ... MyDeleteCriteria ...
WHILE @intRowCount > 0 AND @intErrNo = 0 AND @intLoops > 0

BEGIN
SELECT @dtLoop = GetDate()
SELECT @strSQL =
SET ROWCOUNT @DEL_ROWCOUNT -- number of delete rows / iteration
DELETE D FROM dbo.MyTable AS D WHERE ... MyDeleteCriteria ...
SELECT @intErrNo = @@ERROR, @intRowCount = @@ROWCOUNT
SET ROWCOUNT 0 -- Reset batch size to "all"
SELECT @intRowsToDelete = @intRowsToDelete - @intRowCount,
@intLoops = @intLoops - 1
-- Debugging usage only:
PRINT 'Deleted: ' + CONVERT(varchar(20), @intRowCount)
+ ', Elapsed: ' + CONVERT(varchar(20), DATEDIFF(Second, @dtLoop, GetDate()))
+ ' seconds,' + ' remaining to delete=' + CONVERT(varchar(20), @intRowsToDelete)
+ ', Loops left=' + CONVERT(varchar(20), @intLoops)
WAITFOR DELAY '000:00:05' -- 5 seconds for other users to gain access
END

TFS Cache

If you changed schemas TFS client, will face many strange errors like {Item already exists, out of memory, cannot run query}
Cause:
Visual Studio and Team Explorer provide a caching mechanism which can get out of sync.
Solution:
For Windows Vista delete contents of this folder
C:\Users\{your account}\AppData\Local\Microsoft\Team Foundation\1.0\Cache
C:\Users\{your account}\AppData\Local\Microsoft\Team Foundation\2.0\Cache
For Windows Xp, 2003 delete contents of this folder
C:\Documents and Settings\{your account}\Local Settings\Application Data\Microsoft\Team Foundation\1.0\Cache
C:\Documents and Settings\{your account}\Local Settings\Application Data\Microsoft\Team Foundation\2.0\Cache

Saturday, July 19, 2008

How do you delete a work item?

There is no permanent delete feature for Work Items in this version of the product (2005, 2008). Instead, you put the WI into a terminal state (closed, obsolete, etc.)


There is now a tool in codeplex for this, called TFS Power Pack:
KillBill - Stops a Team Build currently running on a build server.
WorkItem Terminator - Permanently deletes a work item from the TFS database.
http://www.codeplex.com/Wiki/View.aspx?ProjectName=TfsPowerPack

Or delete them via this SQL statement.

Declare @DELID int set @DELID = @WorkItemId

DELETE FROM [TfsWorkItemTracking].[dbo].[WorkItemLongTexts] WHERE ID = @DELID
DELETE FROM [TfsWorkItemTracking].[dbo].[WorkItemsAre] WHERE ID = @DELID
DELETE FROM [TfsWorkItemTracking].[dbo].[WorkItemsWere] WHERE ID = @DELID
DELETE FROM [TfsWorkItemTracking].[dbo].[WorkItemsLatest] WHERE ID = @DELID

Saturday, June 28, 2008

How can you access Running instance of IE and refersh page

First you need to refer SHDocVw.dll and MSHTML.dll. In Visual Studio, go to Project, Add Reference, and then select the COM tab. select these dlls.

Csharp Code:

string myUrl = www.google.com;
SHDocVw.WebBrowser m_browser = null;
SHDocVw.ShellWindows shellWindows = new SHDocVw.ShellWindowsClass();
string filename;
foreach (SHDocVw.WebBrowser ie in shellWindows)
{
filename = Path.GetFileNameWithoutExtension(ie.FullName).ToLower();
if (filename.Equals("iexplore"))
{
m_browser = ie;
//Assign Browser Document
mshtml.IHTMLDocument2 myDoc = (mshtml.IHTMLDocument2)m_browser.Document;
//URL Location
string myLocalLink = myDoc.url;
if (myLocalLink == myUrl)
m_browser.Refresh();
//break;
}

You also can do other actions using m_browser, m_browser.Document to control content ofthis page.

Monday, June 2, 2008

How to resolve the RUP error: Applet RupPresenterApplet notinited

Problem
When publishing the RUP template from IBM® Rational Unified Process builder to IIS Web server on Windows 2003, the published site works when accessing it directly but does not work when it is accessed through the web server. The tree browser on the left hand side of the site gives the error: Applet RupPresenterApplet notinited.

Cause
IIS cannot serve some of the RUP files with special file extensions like .properties, .cfg, .layout, etc. (See below for more info.). Because of this reason the applet cannot download and initialise itself correctly.

Solution
The solution to this problem is to re-configure IIS to add more mime types, shown as follows:
1. Go to Administrative Tools -> IIS Manager, right click the site and bring up the properties dialog box as below:
2. Go to the HTTP Headers tab, and click on MIME Types... button to the following dialog box.
3. Click on the New... button to bring up repeatedly the following MIME Type dialog box and add five extension/MIME type pairs shown in the above list.
4. Close these dialog boxes and apply the changes.
5. Restart the IIS server.
6. Close all sessions of browsers and reopen a new browser to load the RUP.

Tuesday, May 27, 2008

Sort ascending or descending dynamics

You 2 Ways to sort ascending or descending dynamics depends on variable:
First way:
SELECT [Id]
,[Last_Update_Dt]
FROM [Tellas_PhotoGallery].[dbo].[IMAGE]
order by CAST([Last_Update_Dt] AS INT)*-1

SELECT [Id]
,[Last_Update_Dt]
FROM [Tellas_PhotoGallery].[dbo].[IMAGE]order by [Last_Update_Dt] DESC
This technique of multiplying either 1(ASC) or -1(DESC), can be used in many queries, and of course is not limited to datetimes.
Second way
DECLARE @SortOrder int
SET @SortOrder = 1
SELECT [Id]
,[Last_Update_Dt]
FROM [Tellas_PhotoGallery].[dbo].[IMAGE]
ORDER BY
CASE
WHEN @SortOrder = 1 THEN (RANK() OVER (ORDER BY [Last_Update_Dt] ASC))
WHEN @SortOrder = 2 THEN (RANK() OVER (ORDER BY [Last_Update_Dt] DESC))
END

Article below gives you ideas to create dynamic query Sorting and Where Clause without conactenate string:
http://www.sqlteam.com/article/dynamic-order-by

Friday, May 23, 2008

How can we Send SMS?

Before we talk about sending SMS we need to tell you some definitions:

SMSC (Short Message Service Centre):
is a network element in the mobile telephone network which delivers SMS messages.
When a user sends a text message (SMS message) to another user, the message gets stored in the SMSC which delivers it to the destination user when they are available. This is a store and forward op

SMS Gateway:
Average rate of sending SMS for each short number account is 1 message/sec, If you sumbit messages with high rates all messages will failed. SMS gateway application to facilitate the SMS traffic between businesses and mobile subscribers.

Protocols: The
Value-added service provider (VASP) providing the content submits the message to the mobile operator's SMSC(s) using a TCP/IP protocol such as the short message peer-to-peer protocol (SMPP) or the External Machine Interface (EMI). The SMSC delivers the text using the normal Mobile Terminated delivery procedure. The subscribers are charged extra for receiving this premium content, and the amount is typically divided between the mobile network operator and the VASP either through revenue share or a fixed transport fee.

Nokia PC Suite:
is a software package used to establish an interface between Nokia mobile devices and computers that run Microsoft Windows operating system. It can be used to transfer music, photos and applications. It can also be used to send Short Message Service (SMS) messages or act as a modem to connect the computer to the Internet. A mobile phone can be connected by USB, Bluetooth, or infrared.

If you have Application and want to add SMS service to your application, You can send this message by 4 ways:
1. Use Nokia PC Suite to send Short Message Service (SMS) messages from your computer using your SIM card.

2. Use any third party which made applications to send bulk SMS,
This way needn't any knowledge of connection of the operator, It only needs to learn how can you deal with its API.
example of this third party:
http://www.clickatel.com/

3. Use a gateway to connect to SMSC Operators and use its API to send your message.
To use this gateway:
a. Make a deal with operatot to send your SMS through his SMSC.
b. You must have knowledge of mobile network Protocols to configure connection of smsc.
example of this third party:
http://www.kannel.org/ (Free)
http://www.nowsms.com/

4. Use SDK from Third Party to connect to the operator, You will use this SDK to build your gateway application.
Your application Functions:
1. Connect to SMSC
2. Manage rates of sending messages.
3. Send/Receive Message.
4. Logs any actions (Sending/Receive/Notifications/Failure/Succeed)
example of this third party:
http://www.derdack.com/
http://www.devshock.com/ (Free but only for SMPP Protocol)

Notes:
Alias:
UCP Protocol allow you to set alias per each message, While SMPP needs your operator set this alias and will be constant for all messages.

Message Message size:
The maximum single text message size is either 160 7-bit characters, 140 8-bit characters, or 70 16-bit characters. Characters in languages such as Arabic, Chinese, Korean, Japanese or Slavic languages (e.g., Russian) must be encoded using the 16-bit UCS-2 character encoding (see Unicode).Larger content (Concatenated SMS, multipart or segmented SMS or "long sms") can be sent using multiple messages, in which case each message will start with a user data header (UDH) containing segmentation information. Since UDH is inside the payload, the number of characters per segment is lower: 153 for 7-bit encoding, 134 for 8-bit encoding and 67 for 16-bit encoding. The receiving handset is then responsible for reassembling the message and presenting it to the user as one long message. While the standard theoretically permits up to 255 segments, 6 to 8 segment messages are the practical maximum, and long messages are often billed as equivalent to multiple SMS messages.

Saturday, May 17, 2008

Creating a DSL Designer: HRESULT: 0x80020003 (DISP_E_MEMBERNOTFOUND

When try to create DSL Designer in Vistual Sudio 2008, I found Error:
Creating a DSL Designer: HRESULT: 0x80020003 (DISP_E_MEMBERNOTFOUND
and didn't create correct Project.

I install Visual studio 2007 again(Repair), and VS 2008 SDK and problem have been solved. But after I Opened DSL Project created with VS 2005. I faced this problem again. And repairing again didn't solve this problem.

I Found solution removing all database connection from Server Explorer of Visual Studio.

Thursday, May 8, 2008

Ajax getLocation Problem

When I developed a solution using ASPNET and ajax, I faced problem with AJAX
When I used any control used getLocation function and page is scrolled.
For example when I used popup extender and onmousehover popup extender appears shiffted. This problem is occured only in IE.
To Solve this problem I did these steps:
1. I Added ScriptReference to script manager to customize MicrosoftAjax.js
<asp:ScriptManager ID="ScriptManager1" runat="server"
ScriptMode="Release"
EnableScriptLocalization="false">
<Scripts>
<asp:ScriptReference Name="MicrosoftAjax.js"
Path="~/AjaxFramework/MicrosoftAjax.js" />
</Scripts>
</asp:ScriptManager>

2. Customized MicrosoftAjax.js
a. Added these functions to javascript file After line of code Function.__class=true;
function findPos(obj) {
var curleft = curtop = 0;
if (obj.offsetParent) {
do {
curleft += obj.offsetLeft;
curtop += obj.offsetTop;
} while (obj = obj.offsetParent);
}
return [curleft,curtop];
}
function f_scrollLeft() {
return f_filterResults (
window.pageXOffset ? window.pageXOffset : 0,
document.documentElement ? document.documentElement.scrollLeft : 0,
document.body ? document.body.scrollLeft : 0
);
}
function f_scrollTop() {
return 0;
return f_filterResults (
window.pageYOffset ? window.pageYOffset : 0,
document.documentElement ? document.documentElement.scrollTop : 0,
document.body ? document.body.scrollTop : 0
);
}
function f_filterResults(n_win, n_docel, n_body) {
var n_result = n_win ? n_win : 0;
if (n_docel && (!n_result (n_result > n_docel)))
n_result = n_docel;
return n_body && (!n_result (n_result > n_body)) ? n_body : n_result;
}
function getScrollXY() {
var scrOfX = 0, scrOfY = 0;
if( typeof( window.pageYOffset ) == 'number' ) {
//Netscape compliant
scrOfY = window.pageYOffset;
scrOfX = window.pageXOffset;
} else if( document.body && ( document.body.scrollLeft document.body.scrollTop ) ) {
//DOM compliant
scrOfY = document.body.scrollTop;
scrOfX = document.body.scrollLeft;
} else if( document.documentElement && ( document.documentElement.scrollLeft document.documentElement.scrollTop ) ) {
//IE6 standards compliant mode
scrOfY = document.documentElement.scrollTop;
scrOfX = document.documentElement.scrollLeft;
}

return [ scrOfX, scrOfY ];
}

b. search for (Sys.Browser.agent){case Sys.Browser.InternetExplorer:...break;
replace code in this switch case with Code Below:
case Sys.Browser.InternetExplorer:
Sys.UI.DomElement.getLocation = function(element) {
k = findPos(element);
if (Sys.Browser.agent == Sys.Browser.InternetExplorer && Sys.Browser.version < 7) { p = getScrollXY(); offsetX = k[0]+p[0]; offsetY = k[1]+p[1]; return new Sys.UI.Point(offsetX, offsetY); } offsetX = k[0]+f_scrollLeft(); offsetY = k[1]+f_scrollTop(); return new Sys.UI.Point(offsetX, offsetY); }
break;
Note: You can do this change using microsoftAjax.debug.js and use debug Mode (It is easier to edit), But You will find debug file size 250 KB, and 179 KB after you converted it to relase.
It is better to do this change direct to released file because it's size 89 KB.

Sunday, April 20, 2008

Gridview with a single ModalPopupExtender/Panel for row editing

Requirements:
1) I wanted to be able to pop up an edit window for editing that disabled the background window. (or gave the appearance of being disabled)
2) I wanted to control the save and edit server side as I was using custom business objects that were bound to the grids through the ObjectDataSource control.
3) It needed to be asynchronous. I wanted functionality, but I wanted speed, and ease for the customer as well.

I found my solution in this Url:
http://www.codeproject.com/KB/aspnet/GridView-ModalPopupExtend.aspx

Saturday, April 19, 2008

Tips to Improve ASP.net Application Performance

  1. Disable Session StateDisable Session State
    if you're not going to use it. By default it's on. You can actually turn this off for specific pages, instead of for every page:
    <%@ Page language="c#" Codebehind="WebForm1.aspx.cs" AutoEventWireup="false" Inherits="WebApplication1.WebForm1" EnableSessionState="false" %>
    <%@ Page language="c#" Codebehind="WebForm1.aspx.cs" AutoEventWireup="false" Inherits="WebApplication1.WebForm1" EnableSessionState="false" %>

    You can also disable it across the application in the web.config by setting the mode value to Off.
  2. Output Buffering
    Take advantage of this great feature. Basically batch all of your work on the server, and then run a Response.Flush method to output the data. This avoids chatty back and forth with the server.<%response.buffer=true%>

    &lt%response.buffer=true%>

    Then use:

    <%response.flush=true%>
  3. Avoid Server-Side Validation
    Try to avoid server-side validation, use client-side instead. Server-Side will just consume valuable resources on your servers, and cause more chat back and forth.
  4. Repeater Control Good, DataList, DataGrid, and DataView controls
    BadAsp.net is a great platform, unfortunately a lot of the controls that were developed are heavy in html, and create not the greatest scaleable html from a performance standpoint. ASP.net repeater control is awesome! Use it! You might write more code, but you will thank me in the long run!
  5. Take advantage of HttpResponse.IsClientConnected before performing a large
    operation:
    if (Response.IsClientConnected)
    {
    // If still connected, redirect
    // to another page.
    Response.Redirect("Page2CS.aspx", false);
    }
    What is wrong with Response.Redirect? More
  6. Use HTTPServerUtility.Transfer instead of Response.Redirect
    Redirect's are also very chatty. They should only be used when you are transferring people to another physical web server. For any transfers within your server, use .transfer! You will save a lot of needless HTTP requests.
  7. Always check Page.IsValid when using Validator Controls
    So you've dropped on some validator controls, and you think your good to go because ASP.net does everything for you! Right? Wrong! All that happens if bad data is received is the IsValid flag is set to false. So make sure you check Page.IsValid before processing your forms!
  8. Deploy with Release Build
    Make sure you use Release Build mode and not Debug Build when you deploy your site to production. If you think this doesn't matter, think again. By running in debug mode, you are creating PDB's and cranking up the timeout. Deploy Release mode and you will see the speed improvements.
  9. Turn off Tracing
    Tracing is awesome, however have you remembered to turn it off? If not, make sure you edit your web.config and turn it off! It will add a lot of overhead to your application that is not needed in a production environment.

    <configuration>
    <system.web>
    <trace enabled="false" pageOutput="false" />
    <trace enabled="false" requestLimit="10" pageOutput="false" traceMode="SortByTime" localOnly="true"/>
    <compilation debug="false" />
    </system.web>
    </configuration>
  10. Page.IsPostBack is your friend
    Make sure you don't execute code needlessly.
    I don't know how many web developers forget about checking IsPostBack! It seems like such a basic thing to me! Needless processing!
  11. Avoid Exceptions
    Avoid throwing exceptions, and handling useless exceptions. Exceptions are probably one of the heaviest resource hogs and causes of slowdowns you will ever see in web applications, as well as windows applications. Write your code so they don't happen! Don't code by exception!
  12. Caching is Possibly the number one tip!
    Use Quick Page Caching and the ASP.net Cache API! Lots to learn, its not as simple as you might think. There is a lot of strategy involved here. When do you cache? what do you cache?
  13. Create Per-Request Cache
    Use HTTPContect.Items to add single page load to create a per-request cache.
  14. StringBuilder
    StringBuilder. Append is faster than String + String. However in order to use StringBuilder, you must
    new StringBuilder()
    Therefore it is not something you want to use if you don't have large strings. If you are concatenating less than 3 times, then stick with String + String. You can also try String.Concat
  15. Turn Off ViewState
    If you are not using form postback, turn off viewsate, by default, controls will turn on viewsate and slow your site.

    public ShowOrdersTablePage()
    {
    this.Init += new EventHandler(Page_Init);
    }

    private void Page_Init(object sender, System.EventArgs e)
    {
    this.EnableViewState = false;
    }
  16. Use Paging
    Take advantage of paging's simplicity in .net. Only show small subsets of data at a time, allowing the page to load faster. Just be careful when you mix in caching. How many times do you hit the page 2, or page 3 button? Hardly ever right! So don't cache all the data in the grid! Think of it this way: How big would the first search result page be for "music" on Google if they cached all the pages from 1 to goggle ;)
  17. Use the AppOffline.htm when updating binaries
    I hate the generic asp.net error messages! If I never had to see them again I would be so happy. Make sure your users never see them! Use the AppOffline.htm file!
  18. Use ControlState and not ViewState for Controls
    If you followed the last tip, you are probably freaking out at the though of your controls not working. Simply use Control State. Microsoft has an excellent example of using ControlState here
  19. Use the Finally Method
    If you have opened any connections to the database, or files, etc, make sure that you close them at the end! The Finally block is really the best place to do so, as it is the only block of code that will surely execute.
  20. Option Strict and Option Explicit
    This is an oldy, and not so much a strictly ASP.net tip, but a .net tip in general. Make sure you turn BOTH on. you should never trust .net or any compiler to perform conversions for you. That's just shady programming, and low quality code anyway. If you have never turned both on, go turn them on right now and try and compile. Fix all your errors.