:::: MENU ::::

Thursday, September 17, 2009

In SQL Server you can specify a column as an Identity column (ColumnName int IDENTITY(1,1) NOT NULL) to have SQL Server automatically set the value of this column upon insert by incrementing a seed value.  This works great but I have run into situations where I wanted to change what identity value is assigned during the next insert. 

What had happened is that this table in question had the primary key column set as an Identity column.  There were only a couple thousand rows in the table but SQL Server was handing out identity values in the 10-million range.  In most cases this would not be a big deal, but for this table the identity value was actually used by customers so a eight digit number was not as easy to remember and repeat as a 4-digit number. 

What had happened is that a row had been inserted into the table with a high identity value (over 10 million) and then SQL Server took over from there and handed out new identity values that were incremented from that number – 23000001, 23000002, 23000003, etc...

To fix this, I was able to change the seed of the Identity field by using a DBCC CHECKIDENT statement.

You can use this DBCC CHECKIDENT statement to check the current identity value:

DBCC CHECKIDENT('table_name', NORESEED)

And then you can use this DBCC CHECKIDENT statement to change the identity value to another value:

DBCC CHECKIDENT('table_name', RESEED, 2300)

After making this change new records inserted into the table now were assigned 4-digit values and were much easier for customers to remember and use.

 

Monday, September 14, 2009

MSBuildShellExtension lets you build .NET projects without ever opening Visual Studio or the command prompt. MSBuild targets can be executed from your favourite file system tool like Windows Explorer or Total Commander. The possibility to extend MSBuildShellExtension with your own targets and editors, makes it a very flexible and useful tool for all .NET developers.

Friday, September 11, 2009

0. Know your Keybindings! All these are in the General Development Settings.

Searching

1. How to behold the power of incremental search

http://blogs.msdn.com/saraford/archive/2007/07/23/did-you-know-behold-the-power-of-incremental-search.aspx

Command: Edit.IncrementalSearch

Shortcut: Ctrl+i

2. Ctrl+F3 to search for currently-selected word

http://blogs.msdn.com/saraford/archive/2007/10/26/did-you-know-ctrl-f3-searches-for-the-currently-selected-string-without-brining-up-the-find-window.aspx

Command: Edit.FindNextStatement

3. F3 to search for last thing you searched for

http://blogs.msdn.com/saraford/archive/2007/10/25/did-you-know-f3-searches-for-the-last-thing-you-searched-for.aspx

Command: Edit.FindNext

4. Customize what files to find in

http://blogs.msdn.com/saraford/archive/2007/11/07/did-you-know-how-to-customize-what-files-to-find-in.aspx

Find In Files – Look in – Choose Search Folders

5. You can use a reg hack for customizing search results

http://blogs.msdn.com/saraford/archive/2008/11/24/did-you-know-you-can-customize-how-search-results-are-displayed-in-the-find-results-window-363.aspx

HKCU\Software\Microsoft\VisualStudio\9.0\Find String Find=$f$e($l,$c):$t\r\n

Editing

6. How not to accidentally copy a blank line

http://blogs.msdn.com/saraford/archive/2007/09/28/did-you-know-how-not-to-accidentally-copy-a-blank-line.aspx

Tools – Options – Text Editor – All Languages – General, Uncheck Apply cut or copy to blank lines

7. How to cycle through the Clipboard ring

http://blogs.msdn.com/saraford/archive/2007/10/01/did-you-know-how-to-cycle-through-the-clipboard-ring-to-paste-different-things.aspx

Command: Edit.CycleClipboardRing

Shortcut: Ctrl+Shift+v

8. How to use box/column selection in the editor

http://blogs.msdn.com/saraford/archive/2007/07/27/did-you-know-how-to-do-box-selection-in-the-editor.aspx

Command: Edit.LineUpColumnExtend, Edit.LineDownColumnExtend, Edit.CharRightColumnExtend, Edit.CharLeftColumnExtend

Shortcut: Shift+Alt+Arrow

9. You can copy a file’s full path / open windows explorer from the file tab channel

http://blogs.msdn.com/saraford/archive/2008/01/09/did-you-know-you-can-copy-a-file-s-full-path-from-the-file-tab-channel.aspx

Command: File.CopyFullPath

10. Drag and drop code onto the toolbox’s general tab

http://blogs.msdn.com/saraford/archive/2008/04/10/did-you-know-you-can-drag-and-drop-code-onto-the-toolbox-general-tab-191.aspx

11. You can use Ctrl+. to show a smart tag

http://blogs.msdn.com/saraford/archive/2008/11/18/did-you-know-ctrl-shows-a-smart-tag-359.aspx

Command: View.ShowSmartTag

12. You can insert a snippet by pressing Tab Tab

http://blogs.msdn.com/saraford/archive/2008/06/10/did-you-know-you-can-insert-a-snippet-via-tab-tab-234.aspx

Type in snippet shortcut, then press Tab Tab

Customizing

13. You can create temp or throw away projects

http://blogs.msdn.com/saraford/archive/2008/02/25/did-you-know-you-can-create-temp-or-throw-away-projects-158.aspx

Tools - Options - Projects and Solutions - General, uncheck Save new projects when created

14. Change text editor font size via keyboard (Accessibility macros)

http://blogs.msdn.com/saraford/archive/2008/06/20/did-you-know-you-can-bind-macros-to-keyboard-shortcuts-or-how-to-quickly-increase-decrease-your-text-editor-font-size-242.aspx

Command: Macros.Samples.Accessibility.DecreaseTextEditorFontSize

Command: Macros.Samples.Accessibility.IncreaseTextEditorFontSize

15. How to open a file without any UI

http://blogs.msdn.com/saraford/archive/2007/11/26/did-you-know-how-to-have-fun-with-the-find-combo-box.aspx

Ctrl+/ (or whatever Tools.GoToCommandLine is bound to)

alias fo file.openfile

fo <filename>

16. Guidelines in the editor registry key hack

http://blogs.msdn.com/saraford/archive/2008/04/01/did-you-know-you-can-display-guidelines-in-the-editor-and-tip-of-the-day-ends-today-184.aspx

HKEY_CURRENT_USER\Software\Microsoft\VisualStudio\9.0\Text Editor  String RBG(128,0,0) 5, 20

17. You can create a macro for your import/export settings – see http://blog.jeffhandley.com/archive/2009/03/31/vs-profiles.aspx

http://blogs.msdn.com/saraford/archive/2008/12/05/did-you-know-you-can-create-toolbar-buttons-to-quickly-toggle-your-favorite-vs-settings-371.aspx

18. How to not show the start page (or have the last loaded solution open)

http://blogs.msdn.com/saraford/archive/2008/01/03/did-you-know-how-to-customize-what-visual-studio-opens-to-or-how-to-make-the-start-page-not-show-up-when-vs-opens.aspx

Tools - Options - Environment - Startup, At Startup

19. File tab channel registry hack

http://blogs.msdn.com/saraford/archive/2008/10/09/did-you-know-you-can-keep-recently-used-files-from-falling-off-the-file-tab-channel-331.aspx

HKEY_CURRENT_USER\Software\Microsoft\VisualStudio\9.0 key, you can create a DWORD UseMRUDocOrdering = 1

20. How to show Misc Files Project to keep your files around

http://blogs.msdn.com/saraford/archive/2008/01/01/did-you-know-how-to-show-the-miscellaneous-files-project-in-the-solution-explorer.aspx

tools - options - environment – documents, show miscellaneous files in Solution Explorer

21. Edit project file from within IDE (unload project)
http://blogs.msdn.com/saraford/archive/2008/10/10/did-you-know-how-to-edit-a-csproj-or-vbproj-project-file-within-the-ide-332.aspx

Unload project, edit project, reload project

Debugging

22. You can use tracepoints to log stuff in your code

http://blogs.msdn.com/saraford/archive/2008/06/13/did-you-know-you-can-use-tracepoints-to-log-printf-or-console-writeline-info-without-editing-your-code-237.aspx

Right-click in indicator margin, select breakpoints, select Insert Tracepoint

23. How to get the find source dialog back

http://blogs.msdn.com/saraford/archive/2008/09/17/did-you-know-how-to-get-the-find-source-dialog-back-instead-of-the-there-is-no-source-code-available-message-315.aspx

Solution Properties, under Common Properties - Debug Source Files, Delete Do no look for these source files edit box contents

24. You can disable the exception assistant

http://blogs.msdn.com/saraford/archive/2008/08/05/did-you-know-you-can-disable-the-exception-assistant-274.aspx

Tools – Options – Debugging – General, uncheck Enable the Exception Assistant

25. You can use the XML Visualizer

http://blogs.msdn.com/saraford/archive/2008/09/25/did-you-know-you-can-use-the-xml-visualizer-to-view-xml-321.aspx

Drop down the little down arrow on the data tip or in the watch window.

More

Wednesday, September 9, 2009

To test the tools which we develop on the team, at times I need to build a website and publish it. I use a simple way of publishing websites from the command line that saves me a LOT of time so thought I would share it.

Launch notepad and copy paste the code below and save it as Publish.cmd file. Run visual studio command prompt (as administrator) and run the publish.cmd.

 

   1: @ECHO OFF

   2: set WEB_ROOT=C:\inetpub\wwwroot\mytestsite

   3: set PROJECT_ROOT=D:\Source\website

   4: 

   5: echo Publishing site %PROJECT_ROOT% to %WEB_ROOT%

   6: 

   7: del /S /Q %WEB_ROOT%\*.* || goto Error

   8: rmdir /S /Q %WEB_ROOT%\ || goto Error

   9: aspnet_compiler -p "%PROJECT_ROOT%" /v /commercesite /d "%WEB_ROOT%" || goto Error

  10: 

  11: goto Success

  12: :Error

  13: echo Site was not published

  14: 

  15: goto End

  16: 

  17: :Success

  18: echo Site published successfully

  19: 

  20: :End

If there aren’t any errors the site will be published successfully as shown below

C:\Windows\system32>D:\Source\website\publish.cmd
Publishing site D:\Source\website to c:\inetpub\wwwroot\mytestsite Utility to precompile an ASP.NET application
Copyright (C) Microsoft Corporation. All rights reserved.

Site published successfully
C:\Windows\system32>

Modify the above script parameters appropriately to publish your site successfully!

 

Building a connection string from scratch can sometimes be a little daunting when you do not know the exact syntax. Of course, you can always visit www.connectionstrings.com and find some great help there. In lieu of this you can also use the ConnectionStringBuilder class. Each of the ADO.NET providers supplies a version of this class that will build a connection string for you. Below is an example of how to use this class.

VB.NET
Imports System.Data.SqlClient

Private Sub CreateConnectionString()
  Dim builder As New SqlConnectionStringBuilder

  builder.DataSource = "(local)"
  builder.InitialCatalog = "Northwind"
  builder.UserID = "user1"
  builder.Password = "P@ssw0rd"

  MessageBox.Show(builder.ConnectionString)
End Sub

C#
using System.Data.SqlClient;

private void CreateConnectionString()
{
  SqlConnectionStringBuilder builder = new SqlConnectionStringBuilder();

  builder.DataSource = "(local)";
  builder.InitialCatalog = "Northwind";
  builder.UserID = "user1";
  builder.Password = "P@ssw0rd";

  MessageBox.Show(builder.ConnectionString);
}

This is a pretty easy class to use. You can just fill in the basic information such as the DataSource, InitialCatalog, the UserId and Password and it will create a connection string for you. The output from the above code will be: "Data Source=(local);Initial Catalog=Northwind;User ID=user1;Password=p@ssword".

To add on additional keywords for your connection string you may use the Add method. This method takes the keyword and the value and will add them in the appropriate format to your connection string.

As mentioned, each ADO.NET data provider supplies one of these classes. For example, if you are using Oracle, you would use the System.Data.OracleClient namespace, then use the OracleConnectionStringBuilder.

The ConnectionStringBuilder class allows you to parse the individual elements of a connection string and put them into the corresponding properties in the ConnectionStringBuilder. In the following example you take an existing connection string like the one shown in the code below and place it into the ConnectionString property of the ConnectionStringBuilder. The ConnectionStringBuilder will then break it into the appropriate properties.

VB.NET
Private Sub ParseConnectionString()
  Dim cnn As String
  Dim builder As New SqlConnectionStringBuilder

  cnn = "Server=Localhost;Initial Catalog=Northwind;User ID=user1;Password=P@ssw0rd"

  builder.ConnectionString = cnn

  MessageBox.Show(builder.DataSource)
  MessageBox.Show(builder.InitialCatalog)
  MessageBox.Show(builder.UserID)
End Sub

C#
private void ParseConnectionString()
{
  string cnn;
  SqlConnectionStringBuilder builder = new SqlConnectionStringBuilder();

  cnn = "Server=Localhost;Initial Catalog=Northwind;User ID=user1;Password=P@ssw0rd";

  builder.ConnectionString = cnn;

  Debug.WriteLine(builder.DataSource);
  Debug.WriteLine(builder.InitialCatalog);
  Debug.WriteLine(builder.UserID);
}

So the next time you have a connection string that you wish to extract the elements from, or you need to build a connection string, consider using the ConnectionStringBuilder class. I would not recommend using this in a production application as I can't imagine that the performance would be that great, but for figuring out a connection string, this works great.

 

Tuesday, September 8, 2009

Most of the time (If not all) when working on the project we view the website with the help of localhost in debugging mode. Many a times when working on some modules, for solving small problem, we want to write some code that should execute only when running in the localhost or debugging environment.

Normally developers would write the code and then take it as their responsibility to remove the code before the code goes to the next environment. But some time we might make a mistake of not removing the code and letting it go to the next environment, which can cause a lots of trouble.

In these kinds of circumstances and Asp.Net developer can take help of the IsLocal method of the Request class. The method will return true in case the application is running from localhost.

If (Request.IsLocal)
{

}

To know if the application is running in the debugging mode, we can use the

If (HttpContext.Current.IsDebuggingEnabled)
{
// Do task that should execute only when Application is running in debugging mode.
}

 

Tuesday, September 1, 2009

Some programming situations require you to use Dynamic SQL. Of course the problem with using Dynamic SQL is that this can lead to SQL Injection attacks. However, you can avoid these problems, by just changing how you submit Dynamic SQL to your back end database.

To illustrate this, consider the sample table of users listed below.

CREATE TABLE User
(
Login char(16) not null primary key,
Password varchar(20) not null
)
go
INSERT INTO User values('PSheriff', 'password')
go
INSERT INTO User values('Keng', 'password')
go

You can copy and paste the above SQL code into your database management system and create this table. After you have created this table, you might create a login screen and use some code like the following to see if the users are in the User table.


Private Sub BADLoginCode()
 Dim sql As String
 Dim cmd As SqlClient.SqlCommand
 Dim rows As Integer

 sql = " SELECT Count(*) As TotalRows FROM User "
 sql &= " WHERE Login = '" & txtLogin.Text & "'"
 sql &= " AND Password = '" & txtPassword.Text & "'"

 cmd = New SqlClient.SqlCommand(sql)
 cmd.Connection = New SqlClient.SqlConnection(AppConfig.ConnectString)
 cmd.Connection.Open()

 rows = Convert.ToInt32(cmd.ExecuteScalar())

 If rows > 0 Then
   MessageBox.Show("Success")
 Else
   MessageBox.Show("Failure")
 End If
End Sub

The problem with the above code is if a hacker where to type in the following into the Login ID field;

' OR 1=1 DELETE FROM Users --

Then the resulting SQL that is submitted to the back end database is the following:


SELECT Count(*) As TotalRows
FROM User
WHERE Login = '' OR 1=1
DELETE FROM User --'
AND Password = ''


As you can see this will not only allow the user into the application, but will also delete all other users in the system! This is not a good thing.

However, with just a very minor change to this code, you can protect yourself against this type of attack. Just like when calling a stored procedure you use Parameters on the command object to submit the login id and password to the input parameters, you can do the same type of coding with dynamic SQL.


Private Sub LoginGood()
 Dim sql As String
 Dim cmd As SqlClient.SqlCommand
 Dim rows As Integer

 sql = " SELECT Count(*) As TotalRows FROM User "
 sql &= " WHERE Login = @sLogin "
 sql &= " AND Password = @sPassword"

 cmd = New SqlClient.SqlCommand(sql)
 cmd.Connection = New SqlClient.SqlConnection(AppConfig.ConnectString)
 cmd.Connection.Open()
 cmd.Parameters.Add(New _
   SqlClient.SqlParameter("@Login", SqlDbType.Char))
 cmd.Parameters.Add(New _
   SqlClient.SqlParameter("@Password", SqlDbType.Char))
 cmd.Parameters.Item("@Login").Value = txtLogin.Text
 cmd.Parameters.Item("@Password").Value = txtPassword.Text

 rows = Convert.ToInt32(cmd.ExecuteScalar())
 If rows > 0 Then
   MessageBox.Show("Success")
 Else
   MessageBox.Show("Failure")
 End If
End Sub

Notice the use of the Parameters in the dynamic SQL. When you now run this code, the command object and the parameters ensure that no SQL injection attacks will affect your code.

 

Thursday, August 27, 2009

Introduction
The .NET Framework is big. Really big. The System.Web assembly, which contains the guts of ASP.NET, is comprised of nearly 2,000 types, over 23,000 methods, and more than 12,500 properties. And that's not counting any of the functionality added to ASP.NET since version 2.0. ASP.NET AJAX, the ListView control, Dynamic Data, URL routing, and other features add hundreds of new types and thousands of new methods and properties.

Given the size and scope of the .NET Framework and ASP.NET even there are certain to be dark corners for even the most experienced developers. There are certain classes, methods, and properties in the .NET Framework that every ASP.NET developer is intimately familiar with: the Request.QueryString collection; the Session object; Page object properties like IsValid and IsPostBack. Yet even in these familiar classes there are very useful and very helpful properties, methods, and features that are less widely known. Heck, I've been building ASP.NET applications and writing about ASP.NET functionality and features full time since 2001, and once or twice a month I still stumble across an unknown feature or a helpful property or method buried in some dark corner of the framework.

This article lists four helpful methods, properties, and features in the .NET Framework that, in my experience, are not widely known to ASP.NET developers. Read on to see my list!


Typically, ASP.NET developers design, implement, and test their web applications from their personal computer, visiting the website through localhost. When the site is ready to be deployed it is moved to a different web server and the visitors are remote, reaching the website from a domain name like www.yoursite.com. Likewise, when developing the application it is not uncommon to have debugging enabled, which entails going to Web.config and setting the <compilation> element's debug attribute to true. However, this setting should always be set to false in production, as Scott Guthrie notes in his blog entry Don't run production ASP.NET Applications with debug="true" enabled.

Sometimes its helpful to know if the user visiting the website is coming from localhost or if debugging is enabled. For example, you might want to display debugging- or development-related information at the top of each web page, such as the time it took to execute the page or detailed information about the currently logged-in user. However, this information should not be shown to end users; rather, it should only be displayed if the user is visiting locally or if debugging is enabled.

The good news is that it's quite easy to determine whether a visitor has arrived at the site locally, thanks to the Response object's IsLocal property. Response.IsLocal returns True if the visitor is coming from localhost, False otherwise. To determine whether debugging is enabled, use the HttpContext object's IsDebuggingEnabled property. The code snippet below shows how to display a Panel (pnlDiagnosticInfo) only if the user is arriving from localhost and debugging is enabled.

// C#
if (Request.IsLocal && HttpContext.Current.IsDebuggingEnabled)
   pnlDiagnosticInfo.Visible = true;


' VB
If Request.IsLocal AndAlso HttpContext.Current.IsDebuggingEnabled Then
   pnlDiagnosticInfo.Visible = True
End If

Note that to use the HttpContext object's properties you need to first use HttpContext.Current to get a reference to the HttpContext object associated with this request.

2. The Panel Web Control's DefaultButton Property
A <form> in a web page can be submitted in a number of ways: a user can click a submit button; JavaScript can submit the form by calling its submit() function; or a user may hit Enter in a textbox. It's that last technique - hitting Enter in a textbox to submit the form - that can cause problems for web pages that contain multiple submit buttons. For example, an ASP.NET web application might have a master page that includes a search TextBox and Button Web control on every page. When the search Button on the master page is clicked, a postback ensues, the Button control's Click event handler runs, and the user is taken to a page that displays the results of their search query.

Now, imagine a content page that uses this master page and contains its own TextBox controls and a Button control titled "Insert." When the Insert Button is clicked, there is a postback and the Button's Click event handler fires, at which point a new record is added to the database, say.

What happens when we visit this content page in a browser, type some text into the search TextBox, and hit Enter? Hitting Enter causes the browser to submit the <form>, but what Button does the browser indicate as having been "clicked?" If the browser says that the Search Button was clicked, then that Button's Click event handler will fire on postback, but if the browser indicates that the Insert Button is clicked then that Button's Click event handler will fire. Typically, when hitting Enter in a TextBox the browser will report that the first submit button in the form has been clicked. The net result is that regardless of whether the focus was in the Search TextBox or in one of the TextBox controls in the content page, the same Button will report as being "clicked" when the user hits the Enter key. What we want is for the browser to report that the Search Button was "clicked" when the user hits Enter in the search TextBox, and for the browser to report that the Insert Button was "clicked" when the user hits Enter from one of the TextBoxes in the content page. (For a more in-depth discussion of this problem, see Two Common Pitfalls When Submitting a Web Form Using the Enter Key.)

This conundrum can be fixed by placing the search TextBox and Button inside a Panel Web control and setting the Panel's DefaultButton property to the ID of the search Button Web control. The master page's markup would look something like:

<asp:Panel runat="server" ID="pnlSearch" DefaultButton="btnSearch" ...>
   Search: <asp:TextBox runat="server" ID="txtSearch" ... />
   <asp:Button runat="server" ID="btnSearch" Text="Search" ... />
</asp:Panel>

Setting the Panel's DefaultButton property causes the Panel to render with additional JavaScript that is triggered whenever the user presses a key when focused within the Panel. The JavaScript function monitors these keystrokes, and when the Enter key is pressed the code submits the <form>, reporting that the associated Button control was clicked.

For more information on this property, check out my blog entry, The DefaultButton Property - News To Me!

3. Creating Fully Qualified URLs Using Request.Url.GetLeftPart(UriPartial.Authority)
The Request object includes a number of properties for determining path information. For example, the Request object's PhysicalPath property returns the physical path to the currently executing page (e.g., D:\Websites\DemoApp\Tutorial01\MyPage.aspx) whereas the Url property returns the fully qualified URL of the currently requested page (e.g., http://www.yourserver.com/Tutorial01/MyPage.aspx). But what if you want to build a fully qualified URL from scratch?

This is a common challenge when writing code that sends an e-mail that includes a URL back to the website. For example, if your site supports user accounts you might want to send newly registered users an e-mail message welcoming them to the site. You might want to include a URL to the login page in this e-mail. If you know the fully qualified URL of the login page - such as http://www.yourserver.com/Login.aspx - you can hard-code it into the e-mail's body. But what if you haven't settled on a domain name yet? Or what if the software you are developing will be used by various clients, each who have their own domain names? In this case you need to generate a fully qualified URL programmatically. You know the file name of the login page (~/Login.aspx), but you need to write code to generate the left-hand portion, http://www.yourserver.com/, or perhaps http://www.yourserver.com/MyApp/, if the application is rooted at a virtual directory.

Rick Strahl shows how this information can be pieced together from various variables in the ServerVariables collection, but there's an even easier way using the Request object's Url property's GetLeftPart method. In short, the GetLeftPart method returns the specified portion of the URL. The UriPartial.Authority enumeration value passed into this method instructs GetLeftPart method to return the protocol (http:// or https://) along with the domain name and port number (if present). For example, if the requested page's URL is http://www.yourserver.com:8080/Tutorial01/MyPage.aspx, then calling Request.Url.GetLeftPart(UriPartial.Authority) returns the string http://www.yourserver.com:8080.

The following code snippet shows how to build up a fully qualified URL for the login page using Request.Url.GetLeftPart(UriPartial.Authority):

// C#
string loginUrl = Request.Url.GetLeftPart(UriPartial.Authority) +
                  Page.ResolveUrl("~/Login.aspx");

' VB
Dim loginUrl As String = Request.Url.GetLeftPart(UriPartial.Authority) & _
                         Page.ResolveUrl("~/Login.aspx")

The call to Page.ResolveUrl("~/Login.aspx") generates a rooted path to the login page, such as /Tutorial01/Login.aspx. The net effect is that loginUrl is assigned the fully qualified path to the login page, http://www.yourserver.com:8080/Tutorial01/Login.aspx.

4. Taking An ASP.NET Web Application Offline
When performing maintenance on a production website, pushing up new or modified code/web pages, or taking any other sort of action that may disrupt a user's experience, it is a good idea to take the application offline and replace it with a single web page that explains that the website is currently unavailable. IIS, Microsoft's production-grade web server, includes an option to redirect all incoming traffic to a specific URL. This includes requests for any sort of content - ASP.NET pages, static HTML pages, images, CSS files, JavaScript files... whatever.

ASP.NET provides its own mechanism for taking an application offline. In short, if you upload a file to your website named App_Offline.htm the ASP.NET engine will automatically display the contents of the App_Offline.htm for any request to an ASP.NET page. By merely uploading such a file you effectively take your site offline and can display a nice-looking, informative message to visitors explaining why the site is offline, when you expect it to be back up, and so on. To bring the site back up, simply delete (or rename) the App_Offline.htm file.

The main benefit of App_Offline.htm over configuring IIS to redirect all traffic to a specified URL is that App_Offline.htm can be used in virtually any environment, whereas configuring IIS requires access and permission to modify the web server's settings. Typically, such access is not granted in a shared hosting environment, making the App_Offline.htm approach more amenable for such situations.

An earlier article on 4Guys, Taking an ASP.NET Application Offline, shows how to configure IIS to redirect all requests to a static URL, examines alternative approaches to taking an ASP.NET application offline, and discusses App_Offline.htm in more detail. It also includes a demo on how to programmatically create the App_Offline.htm file from a web page, thereby allowing a site to be taken offline from the web. (No need to FTP a file!)

Bear in mind that there are some subtleties that you must be aware of when using App_Offline.htm. As noted in Taking an ASP.NET Application Offline:

The ASP.NET runtime will not return an App_Offline.htm file if it exceeds 1 MB in size. Furthermore, if your App_Offline.htm file is too small (less than 512 bytes), Internet Explorer will display its "friendly 404 error page" rather than the content returned by App_Offline.htm (assuming friendly HTTP error pages are enabled in IE, which they are, by default).

Conclusion
Due to its size and scope, the .NET Framework has a lot of pigeonholes where useful functionality is tucked away. Even when working with the .NET Framework on a daily basis for years on end there are still spots that remain unexplored. This article shared four helpful bits of knowledge on ASP.NET that you may not have known about before. Is there a golden nugget or two in the .NET Framework that you use on a regular basis, but have found that your fellow developers are usually unaware of?

Wednesday, August 26, 2009

Refactoring is an integral part of continually improving your code while it moves forward through time. Without refactoring you accrue technical debt, forget what portions of code do and create code that is resistant to any form of testing. It is an easy concept to get started with and opens the door to much better practices such as unit testing, shared code ownership and more reliable, bug-free code in general.
Because of the importance of refactoring, throughout the month of August I will be describing one refactoring a day for the 31 days of August. Before I begin, let me prefix this series with the fact that I am not claiming ownership of the refactorings I will describe, although I will try to bring some additional description and perhaps some discussion around each. I have chosen not to list the full set of refactorings on this first post until I actually post the refactoring. So as the month progresses I will update this post with links to each of the refactorings.
First on the list is credit where it is due. The majority of these refactorings can be found Refactoring.com, some are from Code Complete 2nd Edition and others are refactorings that I find myself doing often and from various other places on the interwebs. I don’t think it’s important to note on each refactoring where it came from, as you can find refactorings of similar names found on various blogs and articles online.
On that note, I will be publishing the first post starting tomorrow that begins the 31 day marathon of various refactorings. I hope you all enjoy and learn something from the refactorings! 
  1. Refactoring Day 1 : Encapsulate Collection
  2. Refactoring Day 2 : Move Method
  3. Refactoring Day 3 : Pull Up Method
  4. Refactoring Day 4 : Push Down Method
  5. Refactoring Day 5 : Pull Up Field
  6. Refactoring Day 6 : Push Down Field
  7. Refactoring Day 7 : Rename (method, class, parameter)
  8. Refactoring Day 8 : Replace Inheritance with Delegation
  9. Refactoring Day 9 : Extract Interface
  10. Refactoring Day 10 : Extract Method
  11. Refactoring Day 11 : Switch to Strategy
  12. Refactoring Day 12 : Break Dependencies
  13. Refactoring Day 13 : Extract Method Object
  14. Refactoring Day 14 : Break Responsibilities
  15. Refactoring Day 15 : Remove Duplication
  16. Refactoring Day 16 : Encapsulate Conditional
  17. Refactoring Day 17 : Extract Superclass
  18. Refactoring Day 18 : Replace exception with conditional
  19. Refactoring Day 19 : Extract Factory Class
  20. Refactoring Day 20 : Extract Subclass
  21. Refactoring Day 21 : Collapse Hierarchy
  22. Refactoring Day 22 : Break Method
  23. Refactoring Day 23 : Introduce Parameter Object
  24. Refactoring Day 24 : Remove Arrowhead Antipattern
  25. Refactoring Day 25 : Introduce Design By Contract Checks
  26. Refactoring Day 26 : Remove Double Negative 
  27. Refactoring Day 27 : Remove God Classes 
  28. Refactoring Day 28 : Rename boolean methods 
  29. Refactoring Day 29 : Remove Middle Man 
  30. Refactoring Day 30 : Return ASAP 
  31. Refactoring Day 31 : Replace Conditional with Polymorphism

    Thursday, August 20, 2009

    There was a question about this on the Asp.Net forums and after a quick search I didn't find a good generic function so I thought I'd supply one.

    Note: I wanted this to be as broad and useful as possible, so the second parameter is a ListControl which both the ListBox and DropDownList inherit from.

    I also made sure the function would handle enums that had non-contiguous values that didn't necessarily start at zero.

    // ---- EnumToListBox ------------------------------------

    //

    // Fills List controls (ListBox, DropDownList) with the text

    // and value of enums

    //

    // Usage:  EnumToListBox(typeof(MyEnum), ListBox1);

     

    static public void EnumToListBox(Type EnumType, ListControl TheListBox)

    {

        Array Values = System.Enum.GetValues(EnumType);

     

        foreach (int Value in Values)

        {

            string Display = Enum.GetName(EnumType, Value);

            ListItem Item = new ListItem(Display, Value.ToString());

            TheListBox.Items.Add(Item);

        }

    }

     

    I tested with an existing enum and a custom enum:

    enum CustomColors

    {

        BLACK = -1,

        RED = 7,

        GREEN = 14,

        UNKNOWN = -13

    }

     

    protected void Button1_Click(object sender, EventArgs e)

    {

        EnumToListBox(typeof(DayOfWeek), DropDownList1);

     

        EnumToListBox(typeof(CustomColors), ListBox1);

    }

    Note: I initially tried to get the order of the items in the ListBox to match the order of the items in the enum but both the Enum.GetValues and Enum.GetNames functions return the items sorted by the value of the enum. So if you want the enums sorted a certain way, the values of the enums must be sorted that way. I think this is reasonable; how the enums are physically sorted in the source code shouldn't necessarily have any meaning.

     

    You could use an Extension Method on a ListControl to create a new method. This would allow you to create code that looks like this:DropDownList.BindToEnum(typeof(enum));

    Doesn't make it any more or less functional, just a bit prettier.