Monday, April 30, 2007

Our Vendor Skipped the Gym to Help Us Out

My company outsourced its data center. Now the most trivial task is like resolving a bad cable bill.

As part of the transition to a "cheaper" solution, we moved a bunch of our web servers from our data centers (which were once run by in-house employees with domain knowledge) to the vendors. Lo and behold, stuff stopped working, particularly applications' ability to connect and perform database operations.

So that's all the back story. Here was the kicker...this dba for the vendor wanted us to know that she skipped the gym to get our products, that our customers rely on, up and running again.


Never ever tell a customer that you are really put out by their request. Some analogies:

    "I'll have you know I'm missing my high colonic to make you this bagel"
    "I skipped my nap to perform this hysterectomy"

Friday, April 27, 2007

Implementing a "Click Through" in Classic ASP

To simulate a client request for a given url, use Javascript that automatically fires during the test page load event.
To test that this "referral" script works, point the "referrer" to a handy ServerVariables display page.

Both the "referrer" (click.asp) and the "target" (servervars.asp) are illustrated here.
Here is a screen shot of the resulting HTTP_REFERER display page (servervars.asp)

Here's How you Force SSL in Creaky Old ASP

Say you have a Classic ASP site or application where you want to force a secure (SSL) connection.

Use the ASP ServerVariables collection to check the current connection, then redirect appropriately.

Copy/Paste the following into a text file and name it ForceSSL.asp:

<%

If UCase(Request.ServerVariables("HTTPS")) = "OFF" Then
'''get page
    sRedirect = "https://" & Request.ServerVariables("SERVER_NAME") &
    Request.ServerVariables("PATH_INFO") & "?" & Request.Querystring
    Response.Redirect sRedirect
End If

%>

For each page in the site/application, add a server-side include that looks like this:

<!--#include virtual="/ForceSSL.asp"-->

AG, hope this helps you out. I'm probably weeks too late.

Tuesday, April 17, 2007

Web.config - Using an External File

You may find it necessary to separately manage a particular section of your web application's configuration.

Say, for instance, you want to manage a single code base (one web.config file) but you want the application to behave differently on different servers (development, QA, production).

ASP.NET 2.0 allows you to modularize a configuration section using the configSource attribute. The following is an illustrative example:

MyApp has a web.config file that specifies an external source for the appSettings section:

You can store the external file, appSettings.config, anywhere within the application, provided the configSource attribute must specifies a virtual path. Sorry, physical paths or paths outside the application are prohibited.

Getting back to the example, appSettings.config contains a well-formed <appSettings> section:

That's all there is to it! To test the retrieval of these settings, here is a simple .aspx form, testconfig.aspx:

Finally, here's what the output looks like when you visit http://localhost/myapp/testconfig.aspx:


Link to Cut-and-paste-friendly code

Monday, April 16, 2007

Escape!

Check out the following . I was able to last just over 21 seconds. How about you?

Google Driving Directions

Aunt Jojo showed me this tidbit:

  1. Go to Google and select "Maps"
  2. Select "Get Directions"
  3. Get directions from "New York, New York" to "London, England" or other major European city.
  4. Read the instructions very carefully.

Friday, April 13, 2007

Aspnet_regiis -c

Have you ever seen the following ASP.NET client-side error?

It is most common in production environments that host multiple IIS sites and applications.

ASPNET_CLIENT
If your ASP.NET 1.1 application implements dynamic validation controls, it is dependent on the existence of an /aspnet_client directory. This directory must be a child folder of the site's home directory. Here is a sample scenario:

  1. We have a site on a production server, abc.com.
  2. abc.com serves web pages residing on the server's file system at c:\abc. This is the home directory.
  3. I have an asp.net application hosted at abc.com/newapp
  4. My application serves web forms residing at c:\myapps\newapp

My "newapp", which uses validation controls, depends on the existence of c:\abc\aspnet_client. If the ABC site is managed by someone else (some other department in your company), you may not be comfortable with this dependency! E.G, what if someone managing the site content in abc.com ignorantly deletes /aspnet_client, fearing it to be malicious?

Furthermore, while /aspnet_client is handled for you in VS.NET, it is not automatically created for new sites added to IIS. So if you are launching a new site and a new ASP.NET 1.1 application, you will have to include a step to build the /aspnet_client directory. This step is:

Aspnet_regiis -c

This creates the /asnet_client folder under EVERY website node in IIS. So you are safe until the next time some fool deletes it or renames it on the shared server.

Alternative to /aspnet_client

You can remove the dependency of your app on the parent root by overriding the location of the ASP.NET client scripts in web.config. First, copy the scripts folder from the parent root (e.g. c:\abc\aspnet_client) to the application root (e.g. c:\myapps\newapp\aspnet_client). For clarity, rename the folder from aspnet_client to aspnet_override. Then, set the override in web.config:

    <system.web>

    <!-- WEB CONTROLS
    This section is settings to enable client-side validation code.
    -->
    <webControls clientScriptsLocation="aspnet_override\\"/>
    ...

Now you manage the client scripts yourself!

Monday, April 9, 2007

Aspnet_Regiis - Encrypt/Decrypt Web.config

Encrypting a Configuration Section
IIS/ASP.NET will not serve direct requests to Web.config, which protects possibly sensitive information (e.g. connection strings, email addresses) from the public...at least in theory.

You can further protect web.config information via encryption. Out of the box, the aspnet_regiis.exe utility will encrypt web.config according to your preferences.

Here is a sample <appsettings> section:

Assume that this application runs under http://localhost/myApp, we could run the following command to encrypt:

    aspnet_regiis -pe "appSettings" -app "/myApp"

After which, the <appsettings> section would look like this:


Implementing Code to Retrieve Configuration Settings
What's great is that the code that accesses the configuration settings need not change, e.g.:
    string strGUID = ConfigurationSettings.AppSettings["ROOTGUID"];

...would work before and after encryption.

Decryption
To decrypt the configuration settings, just substitute a "-pd" switch for "-pe":

    aspnet_regiis -pd "appSettings" -app "/myApp"

...Finally, I came across a good article about handling this encryption/decryption programmatically (e.g. via an ASP.NET page or a Console App). Here's the 4gfr link.

Friday, April 6, 2007

Intro to Aspnet_Regiis.exe

WHAT IS IT?
Aspnet_regiis.exe is a command line utility that installs ASP.NET features to Internet Information Server (IIS). You find it in your c:\windows\microsoft.net\framework\v#.### directory. Installable components include such things as:

  • An ISAPI Filter - used by IIS to direct incoming requests to the appropriate asp.net
    runtime engine based on the extension (e.g. .asp, .aspx)
  • Script Maps - configuration settings in each IIS node that specify how various extensions are processed (see Figure 1).

  • Client Validation Scripts - /aspnet_client Javascripts that provide dynamic behavior to web form validation controls (see Figure 2)

  • Options for encrypting asp.net configuration (*.config) files.

  • etc


(figure 1 - aspx script mapping)


(figure 2 - client validation scripts)


HOW DO I USE IT?
Very carefully :). Read the various options by typing "aspnet_regiis.exe -?". Run them on a development server to get familiar with them, backing up the IIS metabase appropriately.

CAUTION: Using the "-i" Switch
If you run the utility with "-i", you will install the ASP.NET version specified by the utility's parent directory (e.g. "v1.1.4322"). This includes the ISAPI filter and script maps for all nodes in the IIS tree...

Think about that, because it could get you in to trouble, say, if you are running the utility from the v2.0.50727 directory of a web server that currently runs a bunch of older 1.1 applications. Those applications will be forced to the 2.0 version of the asp.net processing engine (aspnet_isapi.dll) and could very well stop working. Better to leave well enough alone!

To leave existing asp.net scripts as-is, use the combination switch "-ir". Per the documentation, this installs the specified version of ASP.NET without updating script maps. Then to set assign applications to the appropriate version, set them manually in IIS or use script explained in this earlier blog.

Wednesday, April 4, 2007

VBScript Fun - Create a File System Directory

Okay, I was stretching for something to write today. So I thought I'd include an entry on my good friend, FileSystemObject, which has been my "go-to" on many occasions.

So, an example...

Say you want to automate the creation of a file system hierarchy, with folders that don't currently exist, and branch pretty deeply. Using the following function, you can pass a long path and the File System Object will create each layer:

makeDirectory "c:\diablopup\testing\a"
  • '''''''''''''''''''''''''''''''''''''''''''''''''''

  • ' This method is responsible for creating a directory

  • ' The directory can be several layers deep, and if the

  • ' parent directories don't exist, it creates them.

  • ' If the directory already exists, it is left alone

  • ''''''''''''''''''''''''''''''''''''''''''''''''

  • sub makeDirectory (newPath)
      Dim myArray,length,count,path,outputFileObject
        Set outputfileObject = CreateObject("Scripting.FileSystemObject")
          if outputfileObject.FolderExists(newPath) then
        • wscript.echo "Dir: "&newPath&" already exists <-- makeDirectory() "

        • exit sub

          end if
            path = ""
            count = 0
            myArray = split(newPath, "\")
            length = ubound(myArray)

            while count <= length
          • path = path + myArray(count) + "\"
          • count = count + 1
          • if not outputfileObject.FolderExists(path) then
            • outputfileObject.CreateFolder(path)
          • end if
            wend
              wscript.echo "Created Dir: "&newPath&" <-- makeDirectory() "
              end sub

            Tuesday, April 3, 2007

            VB.NET - Visual SourceSafe Journal Monitor Service

            During an interview with a prospective employee last week, we got to talking about Visual SourceSafe.

            He remarked that while VSS provides solid version control facilities, the reporting was lacking. How do you get a snapshot of the VSS activity for a time period, or for a person?

            VSS is project-centric, providing history for a project. If you want info on activity for a time period or a person, you are left to eyeball the journal (text file), provided you have one configured.

            This guy brought up a good point, and it was clear from the discussion that he was used to working with the tool. But I got to thinking. The VSS Journal is a list of entries like the following:

            $/MyApp/bin/MyApp.dll
            Version: 10
            User: diablopup Date: 4/03/07 Time: 4:10p
            Checked in

            Couldn't we parse this file into a normalized database, indexed, say, by VSS Path, User, DateTime? Then I thought, I bet someone has done this before. A little Google research, and...Thank you, Lewis Moten!

            He created this neat Windows Service. Not only does it parse the journal data into a database, it keeps the database up to date by polling the journal file on a regular basis.

            You can also configure it to send you notifications as a project is updated, or even to send you an instant message from MSN Messenger (I found this feature distracting, and removed it). Team Foundation Server is supposed to have these features built-in, but you (like me) may not be using it at your company for awhile.

            Monday, April 2, 2007

            C# Reflection Example - Debug or Release?

            Use .NET reflection to gather information about the current application.

            For example, to verify whether the current application was compiled in release or debug mode:


            1. Inspect the Attributes collection of the Assembly object specified by a dll path.
            2. Find the Attribute of type DebuggableAttribute.
            3. Check that Attribute's IsJITTrackingEnabled property.

            Here is a link to the code.

            I used it to display the compile mode in an About screen: