Friday, 29 February 2008

Clear Concise HTTP Status Codes List

I've recently been looking into ReST services, and needless to say you need to know your HTTP status codes. These are a set of standardised response codes given by web site servers on the Internet. The codes help identify the cause of the problem when a web page or other resource does not load properly. Here is a concise list for reference purposes.

 Information                    # 1xx
    Continue                       # 100
    SwitchProtocl                  # 101
 Success                        # 2xx
    OK                             # 200
    Created                        # 201
    Accepted                       # 202
    NonAuthoritativeInformation    # 203
    NoContent                      # 204
    ResetContent                   # 205
    PartialContent                 # 206
 Redirection                    # 3xx
    MultipleChoice                 # 300
    MovedPermanently               # 301
    Found                          # 302
    SeeOther                       # 303
    NotModified                    # 304
    UseProxy                       # 305
    TemporaryRedirect              # 307
 ClientError                    # 4xx
    BadRequest                     # 400
    Unauthorized                   # 401
    PaymentRequired                # 402
    Forbidden                      # 403
    NotFound                       # 404
    MethodNotAllowed               # 405
    NotAcceptable                  # 406
    ProxyAuthenticationRequired    # 407
    RequestTimeOut                 # 408
    Conflict                       # 409
    Gone                           # 410
    LengthRequired                 # 411
    PreconditionFailed             # 412
    RequestEntityTooLarge          # 413
    RequestURITooLong              # 414
    UnsupportedMediaType           # 415
    RequestedRangeNotSatisfiable   # 416
    ExpectationFailed              # 417
 ServerError                    # 5xx
    InternalServerError            # 500
    NotImplemented                 # 501
    BadGateway                     # 502
    ServiceUnavailable             # 503
    GatewayTimeOut                 # 504
    VersionNotSupported            # 505

To get more info on these codes check out the page on Status Code Definitions.

Wednesday, 27 February 2008

Windows 2003 IIS returns 404 for ASP.Net pages

Had an issue on one of our externally managed servers which wouldn't process any ASP.Net documents (aspx, asmx etc), but would just return a 404. However, it would happily return other files such as htm, txt, css. There was no web application logging, no logs in event viewer I had nothing to go on, until I remembered about the often forgotten and rarely used IIS logs (see my article on where are my iis logs to find yours :).

The logs showed requests for the ASP.Net documents and that a 404 was being returned. This part wasn't helpful but the logs also provide a sub status code which was 2:

#Fields: date time s-sitename s-ip cs-method cs-uri-stem cs-uri-query s-port cs-username c-ip sc-status sc-substatus 
2008-02-27 12:39:13 W3SVC2 GET /default.aspx - 80 - 404 2

A quick Google led me to Microsofts IIS 6 pages explaining the sub status codes - bingo!

404.2 : "Web service extension lockdown policy prevents this request"

Knowing this and with the power of Google I resolved the issue in less than a minute. Just open the IIS6 interface, select the Web Service Extensions menu node, on the right you will see the web service extensions available - just select the ASP.Net extension and click the allow button.

IIS Web Extensions Menu

Wednesday, 20 February 2008

ASP.Net Production Web Server Top Tip

There are a number of things we want to ensure on our production servers:

The debug attribute in the compilation element in the web.config should be false for all applications. This is mainly for performance reasons, leaving it to false means:

1) The compilation of ASP.NET pages takes longer (since some batch optimizations are disabled)

2) Code can execute slower (since some additional debug paths are enabled)

3) Much more memory is used within the application at runtime

4) Scripts and images downloaded from the WebResources.axd handler are not cached

Page output tracing should be disabled, again for performance reasons.

The customErrors element should be in remoteOnly mode. This means the custom error page will be shown to remote users rather than the actual exception or error message. We never want to output visible errors to users!

Luckily, we can ensure all the above happens using one simple config setting in the machine.config on the web server:

   <deployment retail="true" />
<system.web />

Additional info can be found in the MSDN documentation.

Control name changes due to xhtmlConformance

Another strange and unwanted ASP.Net problem cropped up today when we least needed it to. We had some code problems occurring on some servers, but the exact same code worked fine on other servers. The problem was related to some code that hadn't changed for a long time, and left the development team scratching our heads.

Turns out in the HTML the naming convention for controls were different for controls rendered between the different sets of servers. The HTML control name attributes that were separated by a colon : were now being separated by a dollar sign $ in the name property, the id attribute however stayed constant.

This would cause problems in certain scenarios for Javascript and Serverside parsing of the html form values; basically anywhere the element name was hard coded using the : seperator would now not find the control.

The problem relates back to our transition from .Net 1.1 to .Net 2 (so I'm surprised this took so long to surface) and a similar problem that cropped up with some AJAX integration a while back to do with an xhtmlConformance setting.

ASP.Net 1 and 1.1 did not emit XHTML compliant markup from countless server controls. ASP.Net 2 changed this and defaults to emitting XHTML compliant markup from all controls. Beta testing of ASP.Net 2 showed Microsoft that this could affect certain web apps and to prevent this a xhtmlConformance setting was introduced and added in the conversion to the framework's web.config file:

   <xhtmlConformance mode="Legacy" />

Basically, with the setting set to legacy the following example html control output would be rendered:

<input type="text" name="ParentControl:Control" id="ParentControl_Control" />

With the setting set to Transitional (Default) or Strict the following example html control output would be rendered:

<input type="text" name="ParentControl$Control" id="ParentControl_Control" />

I would recommend you don't set the setting to Legacy and leave it as the default Transitional or set to Strict as this will result in your HTML from your server controls to be well formed (i.e. all tags are closed for all elements). Important in ASP.Net AJAX implementations as mentioned in this post.

Friday, 15 February 2008

Split a text file with VBScript

I had to split some text reports (csv format) that are read by colleagues in Excel just the other day. Excel can only read ~65k lines on one sheet, but the reports were ~100k lines - so I had to split the files in two. The reports are generated via script; so I decided to write another script to split the files at around the 60K mark. Hope this can save someone else some time :)

The script below takes as arguements; source filename, base filename and the target directory.

if WScript.Arguments.Count > 0 then

 ' retrieve the command line arguments
 sourceFile = WScript.arguments.Item(0)
        basename = WScript.arguments.Item(1)
        targetDir = WScript.arguments.Item(2)
 set objFSO = CreateObject("Scripting.FileSystemObject")

 ' check the file exists
        if objFSO.FileExists( sourceFile ) then
  WScript.Echo ("input file exists...")

  ' new files
  new1 = targetDir + "\" + basename + "_" + "a." + objFSO.GetExtensionName(sourceFile)
  new2 = targetDir + "\" + basename + "_" + "b." + objFSO.GetExtensionName(sourceFile)
  set fs = CreateObject("Scripting.FileSystemObject")  
  set w1 = objFSO.CreateTextFile(new1, True)  
  set w2 = objFSO.CreateTextFile(new2, True)  
  isNotSplit = True
  with fs.OpenTextFile(sourceFile)  
   while Not .AtEndOfStream  
    if .Line < 60000 then  
     w1.WriteLine .ReadLine  
     w2.WriteLine .ReadLine  
     if( isNotSplit ) then
      isNotSplit = False
      WScript.Echo ("file being split...")
     end iF
    end if  
  end with  
  if( isNotSplit ) then
   WScript.Echo ("input file not split...")
   WScript.Echo ("input file split...")
  end if
  WScript.Echo ("input file does not exist...")
 end if
 WScript.Echo ("finished!")
end if

HTML Email Newsletter Top Tips

Email newsletters are common place for advertising products, services and events. Considering it's uses, it is easy to understand why html newsletters are king; who wants to send plain text emails when we can send fancy text and graphics?! Below are some simple tips to get you started with your html email newsletter creation.

1. Tables for layout not CSS... Unfortunately, there are alot of email clients that were developed in the last ice age still being used. This means CSS is poorly and wildly interpreted in terms of displaying your newsletter's layout. It's back to tables for cross email application consistency.

2. Inline styles... Although CSS shouldn't be used for layout, it is fine to use simple CSS stlying for the content of the email newsletter. Some email clients can strip out html head styles, so put the <styles section in the body tag, or even better, put the css styles inline.

<p style="color: red;">

3. Javascript... Put simply, no JsvaScript! Most email clients will just strip it out.

4. Test, test and test... First test the design in Firefox and IE, chances are if it works in these then you should have a consistent design across the web email clients and most app email clients. Finally test with as many email applications as possible (outlook, outlook express, thunderbird, lotus notes etc).

Using the above tips you should achieve a fairly consistent viewing experience of your newsletter for recipients. If you are having consistency issues the links below may help.

A Guide to CSS Support in Email A top compatabilities article
Example table layouts
Useful email marketing blog
CSS support in HTML emails of Hotmail, Yahoo! Mail and Gmail
CSS and Email, Kissing in a Tree

Thursday, 7 February 2008

Finding a User Mac Address (Javascript)

Unless a user is on an internal network, there is no way server-side (I know of) to retrieve the mac address of a user accessing a web page, simply because it isn't sent in the http headers for a request. Any attempt to analyze the underlying network communications server side is pointless as it will just return the MAC address for the last routing machine. However, it is possible to retrieve the mac address of the user simply using client-side Javascript in IE.

Once you've accessed the WMI and got the MAC address you can even send the value server-side if necessary.

Implications: You are connecting to the WMI (Windows Management Instrumentation) for the local machine and therefore you may have a problem if your IE security settings are restrictive. Also, this won't work in non-IE browsers; only works for Windows operating systems. Not all that restrictive then?! ;)

Troubleshooting: If you get an 'automation server can't create object' error when running the script it is probably for one of the reasons below.

  • You need to enable 'Initialize and script ActiveX controls not marked as safe' on the security tab -> custom level options in IE
  • WMI isn't installed correctly
  • WMI isn't installed
  • Some other permission issue. Are you an administrator? If on Windows 2000 server, have you installed sp4?

P.S. Another plausible option is to use an ActiveX control in connecting to WMI.

Friday, 1 February 2008

Could not load file or assembly App_Web_XXX

Came across a completely random exception today on a new web server:

System.IO.FileNotFoundException: Could not load file or assembly 'App_Web_XXX, Version=, Culture=neutral, PublicKeyToken=null' or one of its dependencies. The system cannot find the file specified. File name: 'App_Web_XXX, Version=, Culture=neutral, PublicKeyToken=null'

After some digging, I found issue is now resolved in .Net 2 SP1, which I recommend you all download if you haven't done so already. You can alternatively download the individual fix for this from Microsoft Support. If you are unable to install the fix or service pack there are a couple of workarounds that may work:

1. Editing the aspx file throwing the error (if appropriate)
2. Clear the Temporary ASP.Net Files folder and restart the application pool
3. Setting batch="false" in the web.config file compilation section (it is true by default)

All the workarounds are fairly simple and harmless except option 3. This has other performance implications; therefore may not be the best option for a production environment.